use std::{alloc::Layout, marker, mem};
use crate::alloc::{self, array};
#[repr(transparent)]
#[derive(Debug)]
pub struct Plan<T, E: alloc::raw::Extent> {
extent: E,
value: marker::PhantomData<fn() -> T>,
}
impl<T, E: alloc::raw::Extent> Plan<T, E> {
pub fn try_new(extent: E) -> Result<Self, alloc::Overflow> {
alloc::raw::Layout::<T>::try_layout(extent.len())?;
Ok(Self {
extent,
value: marker::PhantomData,
})
}
pub fn try_allocate<S>(
self,
state: S,
) -> Result<array::Block<mem::MaybeUninit<T>, E, S>, alloc::Exhausted> {
Ok(array::Block {
pointer: alloc::raw::LayoutExt::try_allocate(self.layout())?,
plan: self.uninit(),
state,
})
}
pub(in crate::alloc::array) const fn empty(extent: alloc::raw::Empty<E>) -> Self {
Self {
extent: extent.into_inner(),
value: marker::PhantomData,
}
}
pub const fn extent(&self) -> &E {
&self.extent
}
pub(in crate::alloc::array) fn layout(&self) -> Layout {
unsafe { alloc::raw::Layout::<T>::layout(self.extent.len()) }
}
pub(in crate::alloc::array) const fn uninit(self) -> Plan<mem::MaybeUninit<T>, E> {
Plan {
extent: self.extent,
value: marker::PhantomData,
}
}
}
impl<T, E: alloc::raw::Extent> Plan<mem::MaybeUninit<T>, E> {
pub(super) const fn initialized(self) -> Plan<T, E> {
Plan {
extent: self.extent,
value: marker::PhantomData,
}
}
}
impl<T> Plan<T, usize> {
pub const fn from_slice(source: &[T]) -> Self {
Self {
extent: source.len(),
value: marker::PhantomData,
}
}
pub fn try_reserve(capacity: usize, required: usize) -> Result<Self, alloc::Overflow> {
Self::try_new(alloc::raw::Layout::<T>::reserve(capacity, required))
}
pub(crate) fn from(len: u8) -> Self {
const {
assert!(Layout::array::<T>(u8::MAX as usize).is_ok(), "layout");
};
Self {
extent: usize::from(len),
value: marker::PhantomData,
}
}
pub fn try_vec(self) -> Result<Vec<T>, alloc::Exhausted> {
let pointer = alloc::raw::LayoutExt::try_allocate::<T>(self.layout())?;
Ok(unsafe { Vec::from_raw_parts(pointer.as_ptr(), 0, self.extent) })
}
}
impl Plan<u8, usize> {
pub fn try_string(self) -> Result<String, alloc::Exhausted> {
Ok(unsafe { String::from_utf8_unchecked(self.try_vec()?) })
}
}
impl<T, E: alloc::raw::Extent> Clone for Plan<T, E> {
fn clone(&self) -> Self {
*self
}
}
impl<T, E: alloc::raw::Extent> Copy for Plan<T, E> {}
const _: () = assert!(mem::size_of::<Plan<u8, usize>>() == mem::size_of::<usize>());