use super::*;
use crate::typeplan::{TypePlan, TypePlanCore, TypePlanNode};
use crate::{AllocError, AllocatedShape, partial::arena::Idx};
use ::alloc::collections::BTreeMap;
use ::alloc::sync::Arc;
use ::alloc::vec;
use core::marker::PhantomData;
impl<'facet> Partial<'facet, true> {
#[inline]
pub fn alloc<T: Facet<'facet>>() -> Result<Self, AllocError> {
TypePlan::<T>::build()?.partial()
}
#[inline]
pub fn alloc_with_plan(plan: Arc<TypePlanCore>) -> Result<Self, AllocError> {
let root_id = plan.root_id();
create_partial_internal::<true>(plan, root_id)
}
#[inline]
pub unsafe fn alloc_shape(shape: &'static facet_core::Shape) -> Result<Self, AllocError> {
let plan = unsafe { TypePlanCore::from_shape(shape)? };
let root_id = plan.root_id();
create_partial_internal::<true>(plan, root_id)
}
}
impl Partial<'static, false> {
#[inline]
pub fn alloc_owned<T: Facet<'static>>() -> Result<Self, AllocError> {
TypePlan::<T>::build()?.partial_owned()
}
#[inline]
pub fn alloc_owned_with_plan(plan: Arc<TypePlanCore>) -> Result<Self, AllocError> {
let root_id = plan.root_id();
create_partial_internal::<false>(plan, root_id)
}
#[inline]
pub unsafe fn alloc_shape_owned(shape: &'static facet_core::Shape) -> Result<Self, AllocError> {
let plan = unsafe { TypePlanCore::from_shape(shape)? };
let root_id = plan.root_id();
create_partial_internal::<false>(plan, root_id)
}
}
impl<'facet, const BORROW: bool> Partial<'facet, BORROW> {
pub unsafe fn from_raw(
data: PtrUninit,
plan: Arc<TypePlanCore>,
type_plan_id: crate::typeplan::NodeId,
) -> Result<Self, AllocError> {
let shape = plan.node(type_plan_id).shape;
let layout = shape.layout.sized_layout().map_err(|_| AllocError {
shape,
operation: "type is not sized",
})?;
let allocated = AllocatedShape::new(shape, layout.size());
Ok(Self {
mode: FrameMode::Strict {
stack: vec![Frame::new(
data,
allocated,
FrameOwnership::External,
type_plan_id,
)],
},
state: PartialState::Active,
root_plan: plan,
_marker: PhantomData,
})
}
pub unsafe fn from_raw_with_shape(
data: PtrUninit,
shape: &'static facet_core::Shape,
) -> Result<Self, AllocError> {
let plan = unsafe { TypePlanCore::from_shape(shape)? };
let root_id = plan.root_id();
unsafe { Self::from_raw(data, plan, root_id) }
}
}
impl<'a, T: Facet<'a> + ?Sized> TypePlan<T> {
#[inline]
pub fn partial<'facet>(&self) -> Result<Partial<'facet, true>, AllocError> {
create_partial_internal::<true>(self.core(), self.core().root_id())
}
#[inline]
pub fn partial_owned(&self) -> Result<Partial<'static, false>, AllocError> {
create_partial_internal::<false>(self.core(), self.core().root_id())
}
}
fn create_partial_internal<'facet, const BORROW: bool>(
plan: Arc<TypePlanCore>,
type_plan_id: Idx<TypePlanNode>,
) -> Result<Partial<'facet, BORROW>, AllocError> {
let node = plan.node(type_plan_id);
let shape = node.shape;
let layout = shape.layout.sized_layout().map_err(|_| AllocError {
shape,
operation: "type is not sized",
})?;
let data = unsafe { alloc_layout(layout)? };
let allocated = AllocatedShape::new(shape, layout.size());
Ok(Partial {
mode: FrameMode::Strict {
stack: vec![Frame::new(
data,
allocated,
FrameOwnership::Owned,
type_plan_id,
)],
},
state: PartialState::Active,
root_plan: plan,
_marker: PhantomData,
})
}
unsafe fn alloc_layout(layout: core::alloc::Layout) -> Result<PtrUninit, AllocError> {
use ::alloc::alloc::{alloc, handle_alloc_error};
if layout.size() == 0 {
let ptr: *mut u8 = core::ptr::NonNull::dangling().as_ptr();
return Ok(PtrUninit::new(ptr));
}
let ptr = unsafe { alloc(layout) };
if ptr.is_null() {
handle_alloc_error(layout);
}
Ok(PtrUninit::new(ptr))
}
impl<'facet, const BORROW: bool> Partial<'facet, BORROW> {
pub fn enter_deferred(self) -> Self {
use core::mem::ManuallyDrop;
let start_depth = self.frames().len();
let mut this = ManuallyDrop::new(self);
let stack = core::mem::take(this.frames_mut());
let mut root_plan = Arc::new(TypePlanCore::empty());
core::mem::swap(&mut root_plan, &mut this.root_plan);
Self {
mode: FrameMode::Deferred {
stack,
start_depth,
stored_frames: BTreeMap::new(),
},
state: this.state,
root_plan,
_marker: PhantomData,
}
}
}