use std::marker;
use crate::depot::{
index::Initialized,
queue::{indexed::keyed, links},
raw,
};
#[repr(transparent)]
pub struct Slot<O: crate::depot::raw::KeyOwner<P>, P = (), const LINKED: bool = true> {
owner: O,
plane: marker::PhantomData<fn(P) -> P>,
}
impl<
O: crate::depot::raw::KeyOwner<
P,
Fifo = keyed::Fifo<<O as crate::depot::raw::KeyOwner<P>>::Key, P>,
>,
P,
> Slot<O, P>
{
pub fn try_new(owner: O) -> Result<Self, Slot<O, P, false>> {
let (index, link) = keyed::selected::<_, P>(&owner);
if link.raw.previous.get() == index.raw() {
return Err(Slot::from_source(unsafe {
crate::depot::raw::Proof::new(owner)
}));
}
Ok(Self {
owner,
plane: marker::PhantomData,
})
}
pub fn front<Q: crate::depot::raw::KeyPlane<P, Slot = O>>(owner: Q) -> Option<Self> {
let slot = Q::select(keyed::Fifo::first(owner)?);
Some(Self {
owner: slot,
plane: marker::PhantomData,
})
}
pub fn key(&self) -> O::Key {
self.owner.parts().0
}
pub fn successor(
&self,
) -> Option<crate::depot::raw::Proof<(&O, links::Index), Initialized<P>>> {
let index = self.owner.parts().1.raw.next_index()?;
Some(unsafe { crate::depot::raw::Proof::new((&self.owner, index)) })
}
pub fn advance(
self,
) -> Result<crate::depot::raw::Proof<(O, links::Index), Initialized<P>>, Self> {
let Some(index) = self.owner.parts().1.raw.next_index() else {
return Err(self);
};
Ok(unsafe { crate::depot::raw::Proof::new((self.owner, index)) })
}
pub fn move_to_back(self) -> Self {
if links::Index::encode(self.owner.fifo().raw.last())
== keyed::selected::<_, P>(&self.owner).0.raw()
{
return self;
}
self.remove().push::<false>()
}
pub fn remove(self) -> Slot<O, P, false> {
let (index, link) = keyed::selected::<_, P>(&self.owner);
let before = link.raw.prev_index();
let after = link.raw.next_index();
let resolve = |index: Option<links::Index>| {
index.map(|index| {
let link = O::link(unsafe { raw::Proof::new((&self.owner, index)) });
raw::EndpointHook::from(&link.raw)
})
};
let previous = resolve(before);
let next = resolve(after);
let fifo = &self.owner.fifo().raw;
let neighbor = |index, hook| match hook {
Some(hook) => raw::Neighbor::node(links::Index::encode(index), hook),
None => raw::Neighbor::head(links::Index::END, fifo),
};
unsafe {
raw::EndpointHook::from(&link.raw).detach(
index,
neighbor(before, previous),
neighbor(after, next),
)
};
Slot::from_source(unsafe { crate::depot::raw::Proof::new(self.owner) })
}
}
impl<
O: crate::depot::raw::KeyRoute<
P,
Fifo = keyed::Fifo<<O as crate::depot::raw::KeyOwner<P>>::Key, P>,
>,
P,
> Slot<O, P>
{
pub fn transfer(self) -> Slot<O::Target, P> {
self.remove().route().push::<false>()
}
}
impl<
O: crate::depot::raw::KeyFinish<LINKED, P>
+ crate::depot::raw::KeyOwner<
P,
Fifo = keyed::Fifo<<O as crate::depot::raw::KeyOwner<P>>::Key, P>,
>,
P,
const LINKED: bool,
> Slot<O, P, LINKED>
{
pub fn release(self) -> O::Output {
unsafe { <O as crate::depot::raw::KeyFinish<LINKED, P>>::finish(self.owner) }
}
}
impl<
O: crate::depot::raw::KeyOwner<
P,
Fifo = keyed::Fifo<<O as crate::depot::raw::KeyOwner<P>>::Key, P>,
>,
P,
> Slot<O, P, false>
{
pub fn try_vacant(owner: O) -> Result<Self, Slot<O, P>> {
match Slot::<O, P>::try_new(owner) {
Ok(linked) => Err(linked),
Err(vacant) => Ok(vacant),
}
}
pub fn push<const FRONT: bool>(self) -> Slot<O, P> {
let (index, link) = keyed::selected::<_, P>(&self.owner);
let fifo = &self.owner.fifo().raw;
let end = if FRONT { fifo.first() } else { fifo.last() };
let adjacent = end.map(|index| {
let link = O::link(unsafe { raw::Proof::new((&self.owner, index)) });
(index, raw::EndpointHook::from(&link.raw))
});
unsafe {
raw::EndpointHook::from(&link.raw).push::<FRONT, _>(
fifo,
index,
links::Index::END,
adjacent,
)
};
Slot::from_source(unsafe { crate::depot::raw::Proof::new(self.owner) })
}
}
impl<
O: crate::depot::raw::KeyRoute<
P,
Fifo = keyed::Fifo<<O as crate::depot::raw::KeyOwner<P>>::Key, P>,
>,
P,
> Slot<O, P, false>
{
pub fn route(self) -> Slot<O::Target, P, false> {
Slot::from_source(unsafe { crate::depot::raw::Proof::new(self.owner.route()) })
}
}
impl<O: crate::depot::raw::KeyOwner<P>, P, const LINKED: bool> Slot<O, P, LINKED> {
pub fn from_source(source: crate::depot::raw::Proof<O, keyed::Membership<LINKED>>) -> Self {
Self {
owner: source.into_inner(),
plane: marker::PhantomData,
}
}
}
impl<O: crate::depot::raw::KeyOwner<P>, P> Slot<O, P> {
pub fn owner_mut(source: crate::depot::raw::Proof<&mut Self, keyed::Exclusive>) -> &mut O {
&mut source.into_inner().owner
}
}