pub(super) struct Slots<T> {
slots: Vec<Slot<T>>,
free: Vec<u32>,
len: usize,
}
struct Slot<T> {
uses: u32,
value: Option<T>,
}
impl<T> Slots<T> {
pub(super) const fn new() -> Self {
Self {
slots: Vec::new(),
free: Vec::new(),
len: 0,
}
}
pub(super) fn insert(&mut self, value: T) -> u64 {
let index = match self.free.pop() {
Some(index) => index,
None => {
self.slots.push(Slot {
uses: 0,
value: None,
});
(self.slots.len() - 1) as u32
}
};
let slot = &mut self.slots[index as usize];
slot.uses = slot.uses.wrapping_add(1).max(1);
slot.value = Some(value);
self.len += 1;
(u64::from(slot.uses) << 32) | u64::from(index)
}
fn slot_mut(&mut self, id: u64) -> Option<&mut Slot<T>> {
let slot = self.slots.get_mut(id as u32 as usize)?;
(u64::from(slot.uses) == id >> 32).then_some(slot)
}
pub(super) fn get_mut(&mut self, id: u64) -> Option<&mut T> {
self.slot_mut(id)?.value.as_mut()
}
pub(super) fn contains(&self, id: u64) -> bool {
self.slots
.get(id as u32 as usize)
.is_some_and(|slot| u64::from(slot.uses) == id >> 32 && slot.value.is_some())
}
pub(super) fn remove(&mut self, id: u64) -> Option<T> {
let value = self.slot_mut(id)?.value.take()?;
self.free.push(id as u32);
self.len -= 1;
Some(value)
}
pub(super) fn iter(&self) -> impl Iterator<Item = (u64, &T)> {
self.slots.iter().enumerate().filter_map(|(index, slot)| {
let value = slot.value.as_ref()?;
Some(((u64::from(slot.uses) << 32) | index as u64, value))
})
}
pub(super) fn len(&self) -> usize {
self.len
}
pub(super) fn is_empty(&self) -> bool {
self.len == 0
}
pub(super) fn capacity(&self) -> usize {
self.slots.capacity()
}
}