use std::{cell, mem, pin};
use crate::{
alloc::tail,
depot::{arena::pool, capacity},
};
pub mod release;
pub trait Recycle {
type Seed: Copy;
type Release;
fn from_seed(seed: Self::Seed) -> Self;
fn recycle(self: pin::Pin<&mut Self>) -> Self::Release;
}
#[derive(Debug)]
pub struct Header<T, C = ()> {
pub(in crate::depot::arena::pool) free: cell::Cell<*mut pool::Entry<T, C>>,
pub(in crate::depot::arena::pool) context: mem::ManuallyDrop<C>,
}
#[repr(transparent)]
pub struct Store<T> {
block: tail::Block<Header<T>, pool::Entry<T>, capacity::Count>,
}
impl<T> Store<T> {
pub fn try_new(capacity: capacity::Count) -> Result<Self, crate::alloc::Error>
where
T: Default,
{
Self::try_from_fn(capacity, |_| T::default())
}
pub fn try_from_fn(
capacity: capacity::Count,
init: impl FnMut(u32) -> T,
) -> Result<Self, crate::alloc::Error> {
Ok(Self {
block: pool::Entry::try_init(capacity, (), init)?,
})
}
pub fn vacancies(&self) -> &Header<T> {
tail::View::new(&self.block).header()
}
pub fn take(&self) -> Option<pool::Unique<'_, T>> {
self.vacancies().take()
}
}
impl<T> Header<T> {
pub fn take(&self) -> Option<pool::Unique<'_, T>> {
Some(pool::Vacant::new(self)?.reserve())
}
}