//! A table that grows as it fills, bounded by storage's memory rather than //! a count: an entry keeps its index for life (a handle names it), and a //! freed index is reused first. At most what a `FileHandle` can name. use alloc::vec::Vec; pub const MAX: usize = u16::MAX as usize + 1; pub struct Slots(Vec>); impl Slots { pub const fn new() -> Self { Self(Vec::new()) } /// The index the next entry would get, if there is room for one. pub fn free(&self) -> Option { let i = self.0.iter().position(Option::is_none).unwrap_or(self.0.len()); (i < MAX).then_some(i) } /// Puts `value` at `index`, growing to it. pub fn put(&mut self, index: usize, value: T) { if index >= MAX { return; } if self.0.len() <= index { self.0.resize_with(index + 1, || None); } self.0[index] = Some(value); } pub fn get(&self, index: usize) -> Option<&T> { self.0.get(index)?.as_ref() } pub fn get_mut(&mut self, index: usize) -> Option<&mut T> { self.0.get_mut(index)?.as_mut() } pub fn take(&mut self, index: usize) -> Option { self.0.get_mut(index)?.take() } /// Every entry, with its index. pub fn iter(&self) -> impl Iterator { self.0.iter().enumerate().filter_map(|(i, v)| v.as_ref().map(|v| (i, v))) } } impl Default for Slots { fn default() -> Self { Self::new() } }