use std::{marker, num::NonZero};
use heap::{Live, indexed};
use crate::{alloc, depot::heap};
pub struct Slot<'a, P: Ord, C: alloc::raw::Extent, T, M = ()> {
owner: &'a mut indexed::Min<P, C>,
context: T,
position: NonZero<u32>,
phase: marker::PhantomData<fn(M) -> M>,
}
impl<'a, P: Ord, C: alloc::raw::Extent, T, M> Slot<'a, P, C, T, M> {
pub fn from_source(live: Live<(&'a mut indexed::Min<P, C>, T), NonZero<u32>, M>) -> Self {
let ((owner, context), position) = live.into_inner();
Self {
owner,
context,
position,
phase: marker::PhantomData,
}
}
}
impl<'a, P: Ord, C: alloc::raw::Extent, T> Slot<'a, P, C, T> {
pub fn entry(self) -> (indexed::Entry<'a, P, C>, T) {
let index = self.position.get() as usize - 1;
let live = unsafe {
crate::depot::raw::Proof::new((
(self.owner, self.context),
heap::Direct::from_index(index),
))
};
let (slot, context) = heap::Slot::from_source(live);
(indexed::Entry::from_slot(slot), context)
}
}
impl<'a, P: Ord, C: alloc::raw::Extent, T> Slot<'a, P, C, T, indexed::Empty> {
pub fn entry(self) -> (indexed::Vacant<'a, P, C>, T) {
let key = unsafe { heap::Direct::from_index(self.position.get() as usize - 1) };
let entry = unsafe { heap::Vacancy::new(self.owner, key) };
(indexed::Vacant { entry }, self.context)
}
}
impl<'a, P: Ord, C: alloc::raw::Extent, T> Slot<'a, P, C, T, indexed::Full> {
pub fn entry(self) -> (indexed::Occupied<'a, P, C>, T) {
let position = unsafe {
*self
.owner
.storage
.tail()
.get_unchecked(self.position.get() as usize - 1)
};
let entry = unsafe { heap::Entry::new(self.owner, position as usize, ()) };
(indexed::Occupied { entry }, self.context)
}
}