use std::{cell, pin, ptr};
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> {
pub(in crate::depot::arena::pool) free: cell::Cell<*mut pool::Entry<T, Header<T>>>,
}
#[repr(transparent)]
pub struct Store<T> {
block: tail::Block<Header<T>, pool::Entry<T, Header<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::init(
tail::Plan::try_new(capacity)?.try_allocate()?,
Header {
free: cell::Cell::new(ptr::null_mut()),
},
init,
),
})
}
pub fn vacancies(&self) -> &Header<T> {
tail::View::new(&self.block).header()
}
pub fn take(&self) -> Option<pool::Unique<'_, T, Header<T>>> {
self.vacancies().take()
}
}
impl<T> Header<T> {
pub fn take(&self) -> Option<pool::Unique<'_, T, Self>> {
Some(pool::Vacant::new(self)?.reserve())
}
pub(in crate::depot) fn free_list(&self) -> &cell::Cell<*mut pool::Entry<T, Self>> {
&self.free
}
}