use slab::slot;
use crate::depot::{
capacity,
queue::{indexed::slab, links},
};
pub struct Cursor<
'a,
T,
Tag = (),
const MAX: u32 = { u32::MAX },
C: crate::depot::raw::Count = capacity::Count,
> {
pub(in crate::depot) entry: slab::Slot<'a, T, Tag, MAX, links::Hook, 0, C>,
pub(in crate::depot) parent: Option<links::Index>,
}
impl<'a, T, Tag, const MAX: u32, C: crate::depot::raw::Count> Cursor<'a, T, Tag, MAX, C> {
pub(in crate::depot) fn new(entry: slab::Slot<'a, T, Tag, MAX, links::Hook, 0, C>) -> Self {
Self {
entry,
parent: None,
}
}
pub fn try_insert(
self,
build: impl FnOnce(Option<&mut T>, slab::Handle<Tag, MAX>) -> T,
) -> Result<Self, C> {
let parent = Some(self.entry.index);
self.splice(parent, build)
}
pub fn try_prepend(
self,
build: impl FnOnce(Option<&mut T>, slab::Handle<Tag, MAX>) -> T,
) -> Result<Self, C> {
let parent = self.parent;
self.splice(parent, build)
}
fn splice(
self,
parent: Option<links::Index>,
build: impl FnOnce(Option<&mut T>, slab::Handle<Tag, MAX>) -> T,
) -> Result<Self, C> {
let (core, _) = self.entry.into_owner();
let capacity = core.capacity();
let Some(slot) = core.vacant() else {
return Err(capacity);
};
let splice = unsafe { slot::Splice::new(slot, parent) };
Ok(Self {
entry: splice.insert(build),
parent,
})
}
pub fn remove<R>(self, unlink: impl FnOnce(Option<&mut T>, T) -> R) -> R {
let (value, slot) = self.entry.detach().into_spare();
let splice = unsafe { slot::Splice::new(slot, self.parent) };
splice.remove(value, unlink)
}
}
const _: () = assert!(size_of::<Cursor<'static, u64>>() == 3 * size_of::<usize>());