diff --git a/src/lib.rs b/src/lib.rs index 9a81010a..4bb60f6a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -73,6 +73,7 @@ pub use generic_array::ArrayLength; pub use indexmap::{FnvIndexMap, IndexMap}; pub use indexset::{FnvIndexSet, IndexSet}; pub use linear_map::LinearMap; +pub use slab::Slab; pub use string::String; pub use vec::Vec; @@ -80,6 +81,7 @@ pub use vec::Vec; mod indexmap; mod indexset; mod linear_map; +mod slab; mod string; mod vec; diff --git a/src/slab.rs b/src/slab.rs new file mode 100644 index 00000000..b983b297 --- /dev/null +++ b/src/slab.rs @@ -0,0 +1,130 @@ +// NOTE this code has been based on slab (crates.io) v0.4.2 + +use core::{mem, slice}; +use generic_array::ArrayLength; + +use crate::Vec; + +/// Implementation detail +#[doc(hidden)] +pub enum Entry { + Vacant(usize), + Occupied(T), +} + +/// TODO +pub struct Slab +where + N: ArrayLength>, +{ + // entries: MaybeUninit, N>>, + entries: Vec, N>, + len: usize, + next: usize, +} + +impl Slab +where + N: ArrayLength>, +{ + /// TODO + pub fn new() -> Self { + Self { + entries: Vec::new(), + len: 0, + next: 0, + } + } + + /// TODO + pub fn insert(&mut self, val: T) -> Result { + let key = self.next; + self.insert_at(key, val)?; + Ok(key) + } + + fn insert_at(&mut self, key: usize, val: T) -> Result<(), T> { + self.len += 1; + + if key == self.entries.len() { + self.entries.push(Entry::Occupied(val)).map_err(|entry| { + if let Entry::Occupied(val) = entry { + val + } else { + unreachable!() + } + })?; + self.next = key + 1; + } else { + let prev = mem::replace(&mut self.entries[key], Entry::Occupied(val)); + + match prev { + Entry::Vacant(next) => { + self.next = next; + } + _ => unreachable!(), + } + } + + Ok(()) + } + + /// TODO + pub fn remove(&mut self, key: usize) -> T { + // Swap the entry at the provided value + let prev = mem::replace(&mut self.entries[key], Entry::Vacant(self.next)); + + match prev { + Entry::Occupied(val) => { + self.len -= 1; + self.next = key; + val + } + _ => { + // Woops, the entry is actually vacant, restore the state + self.entries[key] = prev; + panic!("invalid key"); + } + } + } + + /// TODO + pub fn iter_mut(&mut self) -> IterMut<'_, T> { + IterMut { + entries: self.entries.iter_mut(), + curr: 0, + } + } +} + +impl Default for Slab +where + N: ArrayLength>, +{ + fn default() -> Self { + Self::new() + } +} + +/// TODO +pub struct IterMut<'a, T> { + entries: slice::IterMut<'a, Entry>, + curr: usize, +} + +impl<'a, T> Iterator for IterMut<'a, T> { + type Item = (usize, &'a mut T); + + fn next(&mut self) -> Option<(usize, &'a mut T)> { + while let Some(entry) = self.entries.next() { + let curr = self.curr; + self.curr += 1; + + if let Entry::Occupied(ref mut v) = *entry { + return Some((curr, v)); + } + } + + None + } +}