use alloc::{collections::BTreeMap, sync::Arc, vec::Vec};
mod arena;
mod iset;
mod rope;
pub(crate) mod typeplan;
pub use typeplan::{DeserStrategy, NodeId, TypePlan, TypePlanCore};
mod partial_api;
use crate::{ReflectErrorKind, TrackerKind, trace};
use facet_core::Facet;
use facet_path::{Path, PathStep};
use core::marker::PhantomData;
mod heap_value;
pub use heap_value::*;
use facet_core::{
Def, EnumType, Field, PtrMut, PtrUninit, Shape, SliceBuilderVTable, Type, UserType, Variant,
};
use iset::ISet;
use rope::ListRope;
use typeplan::{FieldDefault, FieldInitPlan, FillRule};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum PartialState {
Active,
Built,
}
enum FrameMode {
Strict {
stack: Vec<Frame>,
},
Deferred {
stack: Vec<Frame>,
start_depth: usize,
stored_frames: BTreeMap<Path, Frame>,
},
}
impl FrameMode {
const fn stack(&self) -> &Vec<Frame> {
match self {
FrameMode::Strict { stack } | FrameMode::Deferred { stack, .. } => stack,
}
}
const fn stack_mut(&mut self) -> &mut Vec<Frame> {
match self {
FrameMode::Strict { stack } | FrameMode::Deferred { stack, .. } => stack,
}
}
const fn is_deferred(&self) -> bool {
matches!(self, FrameMode::Deferred { .. })
}
const fn start_depth(&self) -> Option<usize> {
match self {
FrameMode::Deferred { start_depth, .. } => Some(*start_depth),
FrameMode::Strict { .. } => None,
}
}
}
pub struct Partial<'facet, const BORROW: bool = true> {
mode: FrameMode,
state: PartialState,
root_plan: Arc<TypePlanCore>,
_marker: PhantomData<&'facet ()>,
}
#[derive(Clone, Copy, Debug)]
pub(crate) enum MapInsertState {
Idle,
PushingKey {
key_ptr: PtrUninit,
key_initialized: bool,
key_frame_on_stack: bool,
},
PushingValue {
key_ptr: PtrUninit,
value_ptr: Option<PtrUninit>,
value_initialized: bool,
value_frame_on_stack: bool,
key_frame_stored: bool,
},
}
#[derive(Debug, Clone, Copy)]
pub(crate) enum FrameOwnership {
Owned,
Field { field_idx: usize },
TrackedBuffer,
BorrowedInPlace,
External,
RopeSlot,
}
impl FrameOwnership {
const fn needs_dealloc(&self) -> bool {
matches!(self, FrameOwnership::Owned | FrameOwnership::TrackedBuffer)
}
}
pub(crate) struct AllocatedShape {
shape: &'static Shape,
allocated_size: usize,
}
impl AllocatedShape {
pub(crate) const fn new(shape: &'static Shape, allocated_size: usize) -> Self {
Self {
shape,
allocated_size,
}
}
pub(crate) const fn shape(&self) -> &'static Shape {
self.shape
}
pub(crate) const fn allocated_size(&self) -> usize {
self.allocated_size
}
}
#[must_use]
pub(crate) struct Frame {
pub(crate) data: PtrUninit,
pub(crate) allocated: AllocatedShape,
pub(crate) is_init: bool,
pub(crate) tracker: Tracker,
pub(crate) ownership: FrameOwnership,
pub(crate) using_custom_deserialization: bool,
pub(crate) shape_level_proxy: Option<&'static facet_core::ProxyDef>,
pub(crate) type_plan: typeplan::NodeId,
}
#[derive(Debug)]
pub(crate) enum Tracker {
Scalar,
Array {
iset: ISet,
current_child: Option<usize>,
},
Struct {
iset: ISet,
current_child: Option<usize>,
},
SmartPointer {
building_inner: bool,
pending_inner: Option<PtrUninit>,
},
SmartPointerSlice {
vtable: &'static SliceBuilderVTable,
building_item: bool,
current_child: Option<usize>,
},
Inner {
building_inner: bool,
},
Enum {
variant: &'static Variant,
variant_idx: usize,
data: ISet,
current_child: Option<usize>,
},
List {
current_child: Option<usize>,
rope: Option<ListRope>,
},
Map {
insert_state: MapInsertState,
pending_entries: Vec<(PtrUninit, PtrUninit)>,
current_entry_index: Option<usize>,
building_key: bool,
},
Set {
current_child: bool,
},
Option {
building_inner: bool,
pending_inner: Option<PtrUninit>,
},
Result {
is_ok: bool,
building_inner: bool,
},
DynamicValue {
state: DynamicValueState,
},
}
#[derive(Debug)]
#[allow(dead_code)] pub(crate) enum DynamicValueState {
Uninit,
Scalar,
Array {
building_element: bool,
pending_elements: alloc::vec::Vec<PtrUninit>,
},
Object {
insert_state: DynamicObjectInsertState,
pending_entries: alloc::vec::Vec<(alloc::string::String, PtrUninit)>,
},
}
#[derive(Debug)]
#[allow(dead_code)] pub(crate) enum DynamicObjectInsertState {
Idle,
BuildingValue {
key: alloc::string::String,
},
}
impl Tracker {
const fn kind(&self) -> TrackerKind {
match self {
Tracker::Scalar => TrackerKind::Scalar,
Tracker::Array { .. } => TrackerKind::Array,
Tracker::Struct { .. } => TrackerKind::Struct,
Tracker::SmartPointer { .. } => TrackerKind::SmartPointer,
Tracker::SmartPointerSlice { .. } => TrackerKind::SmartPointerSlice,
Tracker::Enum { .. } => TrackerKind::Enum,
Tracker::List { .. } => TrackerKind::List,
Tracker::Map { .. } => TrackerKind::Map,
Tracker::Set { .. } => TrackerKind::Set,
Tracker::Option { .. } => TrackerKind::Option,
Tracker::Result { .. } => TrackerKind::Result,
Tracker::DynamicValue { .. } => TrackerKind::DynamicValue,
Tracker::Inner { .. } => TrackerKind::Inner,
}
}
const fn set_current_child(&mut self, idx: usize) {
match self {
Tracker::Struct { current_child, .. }
| Tracker::Enum { current_child, .. }
| Tracker::Array { current_child, .. } => {
*current_child = Some(idx);
}
_ => {}
}
}
fn clear_current_child(&mut self) {
match self {
Tracker::Struct { current_child, .. }
| Tracker::Enum { current_child, .. }
| Tracker::Array { current_child, .. }
| Tracker::List { current_child, .. } => {
*current_child = None;
}
Tracker::Set { current_child } => {
*current_child = false;
}
_ => {}
}
}
}
impl Frame {
fn new(
data: PtrUninit,
allocated: AllocatedShape,
ownership: FrameOwnership,
type_plan: typeplan::NodeId,
) -> Self {
let is_init = matches!(
allocated.shape().ty,
Type::User(UserType::Struct(struct_type)) if struct_type.fields.is_empty()
);
Self {
data,
allocated,
is_init,
tracker: Tracker::Scalar,
ownership,
using_custom_deserialization: false,
shape_level_proxy: None,
type_plan,
}
}
fn deinit(&mut self) {
if matches!(
self.ownership,
FrameOwnership::BorrowedInPlace | FrameOwnership::RopeSlot
) {
self.is_init = false;
self.tracker = Tracker::Scalar;
return;
}
match &mut self.tracker {
Tracker::Scalar => {
if self.is_init {
unsafe {
self.allocated
.shape()
.call_drop_in_place(self.data.assume_init())
};
}
}
Tracker::Array { iset, .. } => {
if let Type::Sequence(facet_core::SequenceType::Array(array_def)) =
self.allocated.shape().ty
{
let element_layout = array_def.t.layout.sized_layout().ok();
if let Some(layout) = element_layout {
for idx in 0..array_def.n {
if iset.get(idx) {
let offset = layout.size() * idx;
let element_ptr = unsafe { self.data.field_init(offset) };
unsafe { array_def.t.call_drop_in_place(element_ptr) };
}
}
}
}
}
Tracker::Struct { iset, .. } => {
if let Type::User(UserType::Struct(struct_type)) = self.allocated.shape().ty {
if iset.all_set(struct_type.fields.len()) {
unsafe {
self.allocated
.shape()
.call_drop_in_place(self.data.assume_init())
};
} else {
for (idx, field) in struct_type.fields.iter().enumerate() {
if iset.get(idx) {
let field_ptr = unsafe { self.data.field_init(field.offset) };
unsafe { field.shape().call_drop_in_place(field_ptr) };
}
}
}
}
}
Tracker::Enum { variant, data, .. } => {
for (idx, field) in variant.data.fields.iter().enumerate() {
if data.get(idx) {
let field_ptr = unsafe { self.data.field_init(field.offset) };
unsafe { field.shape().call_drop_in_place(field_ptr) };
}
}
}
Tracker::SmartPointer { pending_inner, .. } => {
if let Some(inner_ptr) = pending_inner
&& let Def::Pointer(ptr_def) = self.allocated.shape().def
&& let Some(inner_shape) = ptr_def.pointee
{
unsafe {
inner_shape.call_drop_in_place(PtrMut::new(inner_ptr.as_mut_byte_ptr()))
};
}
if self.is_init {
unsafe {
self.allocated
.shape()
.call_drop_in_place(self.data.assume_init())
};
}
}
Tracker::SmartPointerSlice { vtable, .. } => {
let builder_ptr = unsafe { self.data.assume_init() };
unsafe {
(vtable.free_fn)(builder_ptr);
}
}
Tracker::List { rope, .. } => {
if let Some(mut rope) = rope.take()
&& let Def::List(list_def) = self.allocated.shape().def
{
let element_shape = list_def.t;
unsafe {
rope.drain_into(|ptr| {
element_shape.call_drop_in_place(PtrMut::new(ptr.as_ptr()));
});
}
}
if self.is_init {
unsafe {
self.allocated
.shape()
.call_drop_in_place(self.data.assume_init())
};
}
}
Tracker::Map {
insert_state,
pending_entries,
..
} => {
if self.is_init {
unsafe {
self.allocated
.shape()
.call_drop_in_place(self.data.assume_init())
};
}
if let Def::Map(map_def) = self.allocated.shape().def {
for (key_ptr, value_ptr) in pending_entries.drain(..) {
unsafe { map_def.k().call_drop_in_place(key_ptr.assume_init()) };
if let Ok(key_layout) = map_def.k().layout.sized_layout()
&& key_layout.size() > 0
{
unsafe { alloc::alloc::dealloc(key_ptr.as_mut_byte_ptr(), key_layout) };
}
unsafe { map_def.v().call_drop_in_place(value_ptr.assume_init()) };
if let Ok(value_layout) = map_def.v().layout.sized_layout()
&& value_layout.size() > 0
{
unsafe {
alloc::alloc::dealloc(value_ptr.as_mut_byte_ptr(), value_layout)
};
}
}
}
match insert_state {
MapInsertState::PushingKey {
key_ptr,
key_initialized,
key_frame_on_stack,
} => {
if !*key_frame_on_stack
&& let Def::Map(map_def) = self.allocated.shape().def
{
if *key_initialized {
unsafe { map_def.k().call_drop_in_place(key_ptr.assume_init()) };
}
if let Ok(key_layout) = map_def.k().layout.sized_layout()
&& key_layout.size() > 0
{
unsafe {
alloc::alloc::dealloc(key_ptr.as_mut_byte_ptr(), key_layout)
};
}
}
}
MapInsertState::PushingValue {
key_ptr,
value_ptr,
value_initialized,
value_frame_on_stack,
key_frame_stored,
} => {
if let Def::Map(map_def) = self.allocated.shape().def {
if !*key_frame_stored {
unsafe { map_def.k().call_drop_in_place(key_ptr.assume_init()) };
if let Ok(key_layout) = map_def.k().layout.sized_layout()
&& key_layout.size() > 0
{
unsafe {
alloc::alloc::dealloc(key_ptr.as_mut_byte_ptr(), key_layout)
};
}
}
if !*value_frame_on_stack && let Some(value_ptr) = value_ptr {
if *value_initialized {
unsafe {
map_def.v().call_drop_in_place(value_ptr.assume_init())
};
}
if let Ok(value_layout) = map_def.v().layout.sized_layout()
&& value_layout.size() > 0
{
unsafe {
alloc::alloc::dealloc(
value_ptr.as_mut_byte_ptr(),
value_layout,
)
};
}
}
}
}
MapInsertState::Idle => {}
}
}
Tracker::Set { .. } => {
if self.is_init {
unsafe {
self.allocated
.shape()
.call_drop_in_place(self.data.assume_init())
};
}
}
Tracker::Option {
building_inner,
pending_inner,
} => {
let had_pending = pending_inner.is_some();
if let Some(inner_ptr) = pending_inner.take()
&& let Def::Option(option_def) = self.allocated.shape().def
{
unsafe { option_def.t.call_drop_in_place(inner_ptr.assume_init()) };
if let Ok(layout) = option_def.t.layout.sized_layout()
&& layout.size() > 0
{
unsafe { alloc::alloc::dealloc(inner_ptr.as_mut_byte_ptr(), layout) };
}
}
if !*building_inner && !had_pending {
unsafe {
self.allocated
.shape()
.call_drop_in_place(self.data.assume_init())
};
}
}
Tracker::Result { building_inner, .. } => {
if !*building_inner {
unsafe {
self.allocated
.shape()
.call_drop_in_place(self.data.assume_init())
};
}
}
Tracker::DynamicValue { state } => {
if let DynamicValueState::Object {
pending_entries, ..
} = state
{
if let Def::DynamicValue(dyn_def) = self.allocated.shape().def {
let value_shape = self.allocated.shape(); for (_key, value_ptr) in pending_entries.drain(..) {
unsafe {
value_shape.call_drop_in_place(value_ptr.assume_init());
}
if let Ok(layout) = value_shape.layout.sized_layout()
&& layout.size() > 0
{
unsafe {
alloc::alloc::dealloc(value_ptr.as_mut_byte_ptr(), layout);
}
}
}
let _ = dyn_def; }
}
if let DynamicValueState::Array {
pending_elements, ..
} = state
{
let element_shape = self.allocated.shape(); for element_ptr in pending_elements.drain(..) {
unsafe {
element_shape.call_drop_in_place(element_ptr.assume_init());
}
if let Ok(layout) = element_shape.layout.sized_layout()
&& layout.size() > 0
{
unsafe {
alloc::alloc::dealloc(element_ptr.as_mut_byte_ptr(), layout);
}
}
}
}
if self.is_init {
let result = unsafe {
self.allocated
.shape()
.call_drop_in_place(self.data.assume_init())
};
if result.is_none() {
panic!(
"DynamicValue type {} has no drop_in_place implementation",
self.allocated.shape()
);
}
}
}
Tracker::Inner { .. } => {
if self.is_init {
unsafe {
self.allocated
.shape()
.call_drop_in_place(self.data.assume_init())
};
}
}
}
self.is_init = false;
self.tracker = Tracker::Scalar;
}
fn deinit_for_replace(&mut self) {
if matches!(self.ownership, FrameOwnership::BorrowedInPlace) && self.is_init {
unsafe {
self.allocated
.shape()
.call_drop_in_place(self.data.assume_init());
}
if let Def::DynamicValue(dyn_def) = &self.allocated.shape().def {
unsafe {
(dyn_def.vtable.set_null)(self.data);
}
self.tracker = Tracker::DynamicValue {
state: DynamicValueState::Scalar,
};
return;
}
self.is_init = false;
self.tracker = Tracker::Scalar;
return;
}
self.deinit();
}
const unsafe fn mark_as_init(&mut self) {
self.is_init = true;
}
fn dealloc(self) {
if !self.ownership.needs_dealloc() {
return;
}
if self.is_init {
unreachable!("a frame has to be deinitialized before being deallocated")
}
if self.allocated.allocated_size() > 0 {
if let Ok(layout) = self.allocated.shape().layout.sized_layout() {
let actual_layout = core::alloc::Layout::from_size_align(
self.allocated.allocated_size(),
layout.align(),
)
.expect("allocated_size must be valid");
unsafe { alloc::alloc::dealloc(self.data.as_mut_byte_ptr(), actual_layout) };
}
}
}
fn fill_defaults(&mut self) -> Result<(), ReflectErrorKind> {
if !self.is_init
&& matches!(self.tracker, Tracker::Scalar)
&& let Type::User(UserType::Struct(struct_type)) = self.allocated.shape().ty
{
if unsafe { self.allocated.shape().call_default_in_place(self.data) }.is_some() {
self.is_init = true;
return Ok(());
}
self.tracker = Tracker::Struct {
iset: ISet::new(struct_type.fields.len()),
current_child: None,
};
}
if !self.is_init
&& matches!(self.tracker, Tracker::Scalar)
&& matches!(self.allocated.shape().def, Def::Option(_))
{
if unsafe { self.allocated.shape().call_default_in_place(self.data) }.is_some() {
self.is_init = true;
return Ok(());
}
}
match &mut self.tracker {
Tracker::Struct { iset, .. } => {
if let Type::User(UserType::Struct(struct_type)) = self.allocated.shape().ty {
if iset.all_set(struct_type.fields.len()) {
return Ok(());
}
let no_fields_set = (0..struct_type.fields.len()).all(|i| !iset.get(i));
if no_fields_set {
if unsafe { self.allocated.shape().call_default_in_place(self.data) }
.is_some()
{
self.tracker = Tracker::Scalar;
self.is_init = true;
return Ok(());
}
}
let container_has_default = self.allocated.shape().has_default_attr();
for (idx, field) in struct_type.fields.iter().enumerate() {
if iset.get(idx) {
continue;
}
let field_ptr = unsafe { self.data.field_uninit(field.offset) };
if unsafe {
Self::try_init_field_default(field, field_ptr, container_has_default)
} {
iset.set(idx);
} else if field.has_default() {
return Err(ReflectErrorKind::DefaultAttrButNoDefaultImpl {
shape: field.shape(),
});
}
}
}
}
Tracker::Enum { variant, data, .. } => {
let num_fields = variant.data.fields.len();
if num_fields == 0 || data.all_set(num_fields) {
return Ok(());
}
let container_has_default = self.allocated.shape().has_default_attr();
for (idx, field) in variant.data.fields.iter().enumerate() {
if data.get(idx) {
continue;
}
let field_ptr = unsafe { self.data.field_uninit(field.offset) };
if unsafe {
Self::try_init_field_default(field, field_ptr, container_has_default)
} {
data.set(idx);
} else if field.has_default() {
return Err(ReflectErrorKind::DefaultAttrButNoDefaultImpl {
shape: field.shape(),
});
}
}
}
_ => {}
}
Ok(())
}
unsafe fn try_init_field_default(
field: &Field,
field_ptr: PtrUninit,
container_has_default: bool,
) -> bool {
use facet_core::DefaultSource;
if let Some(default_source) = field.default {
match default_source {
DefaultSource::Custom(default_fn) => {
unsafe { default_fn(field_ptr) };
return true;
}
DefaultSource::FromTrait => {
if unsafe { field.shape().call_default_in_place(field_ptr) }.is_some() {
return true;
}
}
}
}
if container_has_default
&& unsafe { field.shape().call_default_in_place(field_ptr) }.is_some()
{
return true;
}
if matches!(field.shape().def, Def::Option(_))
&& unsafe { field.shape().call_default_in_place(field_ptr) }.is_some()
{
return true;
}
if field.shape().is_type::<()>()
&& unsafe { field.shape().call_default_in_place(field_ptr) }.is_some()
{
return true;
}
if matches!(field.shape().def, Def::List(_) | Def::Map(_) | Def::Set(_))
&& unsafe { field.shape().call_default_in_place(field_ptr) }.is_some()
{
return true;
}
false
}
fn drain_rope_into_vec(
mut rope: ListRope,
list_def: &facet_core::ListDef,
list_data: PtrUninit,
) -> Result<(), ReflectErrorKind> {
let count = rope.initialized_count();
if count == 0 {
return Ok(());
}
let push_fn = list_def
.push()
.ok_or_else(|| ReflectErrorKind::OperationFailed {
shape: list_def.t(),
operation: "List missing push function for rope drain",
})?;
let list_ptr = unsafe { list_data.assume_init() };
if let Some(reserve_fn) = list_def.reserve() {
unsafe {
reserve_fn(list_ptr, count);
}
}
unsafe {
rope.drain_into(|element_ptr| {
push_fn(
facet_core::PtrMut::new(list_ptr.as_mut_byte_ptr()),
facet_core::PtrMut::new(element_ptr.as_ptr()),
);
});
}
Ok(())
}
fn drain_pending_into_map(
pending_entries: &mut Vec<(PtrUninit, PtrUninit)>,
map_def: &facet_core::MapDef,
map_data: PtrUninit,
) -> Result<(), ReflectErrorKind> {
let insert_fn = map_def.vtable.insert;
let map_ptr = unsafe { map_data.assume_init() };
for (key_ptr, value_ptr) in pending_entries.drain(..) {
unsafe {
insert_fn(
facet_core::PtrMut::new(map_ptr.as_mut_byte_ptr()),
facet_core::PtrMut::new(key_ptr.as_mut_byte_ptr()),
facet_core::PtrMut::new(value_ptr.as_mut_byte_ptr()),
);
}
if let Ok(key_layout) = map_def.k().layout.sized_layout()
&& key_layout.size() > 0
{
unsafe { alloc::alloc::dealloc(key_ptr.as_mut_byte_ptr(), key_layout) };
}
if let Ok(value_layout) = map_def.v().layout.sized_layout()
&& value_layout.size() > 0
{
unsafe { alloc::alloc::dealloc(value_ptr.as_mut_byte_ptr(), value_layout) };
}
}
Ok(())
}
fn complete_pending_option(
option_def: facet_core::OptionDef,
option_data: PtrUninit,
inner_ptr: PtrUninit,
) -> Result<(), ReflectErrorKind> {
let init_some_fn = option_def.vtable.init_some;
let inner_shape = option_def.t;
let inner_value_ptr = unsafe { inner_ptr.assume_init() };
unsafe {
init_some_fn(option_data, inner_value_ptr);
}
if let Ok(layout) = inner_shape.layout.sized_layout()
&& layout.size() > 0
{
unsafe { alloc::alloc::dealloc(inner_ptr.as_mut_byte_ptr(), layout) };
}
Ok(())
}
fn complete_pending_smart_pointer(
smart_ptr_shape: &'static Shape,
smart_ptr_def: facet_core::PointerDef,
smart_ptr_data: PtrUninit,
inner_ptr: PtrUninit,
) -> Result<(), ReflectErrorKind> {
if let Some(new_into_fn) = smart_ptr_def.vtable.new_into_fn {
let Some(inner_shape) = smart_ptr_def.pointee else {
return Err(ReflectErrorKind::OperationFailed {
shape: smart_ptr_shape,
operation: "SmartPointer missing pointee shape",
});
};
let _ = unsafe { inner_ptr.assume_init() };
unsafe {
new_into_fn(smart_ptr_data, PtrMut::new(inner_ptr.as_mut_byte_ptr()));
}
if let Ok(layout) = inner_shape.layout.sized_layout()
&& layout.size() > 0
{
unsafe { alloc::alloc::dealloc(inner_ptr.as_mut_byte_ptr(), layout) };
}
return Ok(());
}
if let Some(pointee) = smart_ptr_def.pointee()
&& pointee.is_shape(str::SHAPE)
{
use alloc::{rc::Rc, string::String, sync::Arc};
use facet_core::KnownPointer;
let Some(known) = smart_ptr_def.known else {
return Err(ReflectErrorKind::OperationFailed {
shape: smart_ptr_shape,
operation: "SmartPointer<str> missing known pointer type",
});
};
let string_ptr = inner_ptr.as_mut_byte_ptr() as *mut String;
let string_value = unsafe { core::ptr::read(string_ptr) };
match known {
KnownPointer::Box => {
let boxed: alloc::boxed::Box<str> = string_value.into_boxed_str();
unsafe {
core::ptr::write(
smart_ptr_data.as_mut_byte_ptr() as *mut alloc::boxed::Box<str>,
boxed,
);
}
}
KnownPointer::Arc => {
let arc: Arc<str> = Arc::from(string_value.into_boxed_str());
unsafe {
core::ptr::write(smart_ptr_data.as_mut_byte_ptr() as *mut Arc<str>, arc);
}
}
KnownPointer::Rc => {
let rc: Rc<str> = Rc::from(string_value.into_boxed_str());
unsafe {
core::ptr::write(smart_ptr_data.as_mut_byte_ptr() as *mut Rc<str>, rc);
}
}
_ => {
return Err(ReflectErrorKind::OperationFailed {
shape: smart_ptr_shape,
operation: "Unsupported SmartPointer<str> type",
});
}
}
let string_layout = alloc::string::String::SHAPE.layout.sized_layout().unwrap();
if string_layout.size() > 0 {
unsafe { alloc::alloc::dealloc(inner_ptr.as_mut_byte_ptr(), string_layout) };
}
return Ok(());
}
Err(ReflectErrorKind::OperationFailed {
shape: smart_ptr_shape,
operation: "SmartPointer missing new_into_fn and not a supported unsized type",
})
}
fn require_full_initialization(&mut self) -> Result<(), ReflectErrorKind> {
match &mut self.tracker {
Tracker::Scalar => {
if self.is_init {
Ok(())
} else {
Err(ReflectErrorKind::UninitializedValue {
shape: self.allocated.shape(),
})
}
}
Tracker::Array { iset, .. } => {
match self.allocated.shape().ty {
Type::Sequence(facet_core::SequenceType::Array(array_def)) => {
if (0..array_def.n).all(|idx| iset.get(idx)) {
Ok(())
} else {
Err(ReflectErrorKind::UninitializedValue {
shape: self.allocated.shape(),
})
}
}
_ => Err(ReflectErrorKind::UninitializedValue {
shape: self.allocated.shape(),
}),
}
}
Tracker::Struct { iset, .. } => {
match self.allocated.shape().ty {
Type::User(UserType::Struct(struct_type)) => {
if iset.all_set(struct_type.fields.len()) {
Ok(())
} else {
let first_missing_idx =
(0..struct_type.fields.len()).find(|&idx| !iset.get(idx));
if let Some(missing_idx) = first_missing_idx {
let field_name = struct_type.fields[missing_idx].name;
Err(ReflectErrorKind::UninitializedField {
shape: self.allocated.shape(),
field_name,
})
} else {
Err(ReflectErrorKind::UninitializedValue {
shape: self.allocated.shape(),
})
}
}
}
_ => Err(ReflectErrorKind::UninitializedValue {
shape: self.allocated.shape(),
}),
}
}
Tracker::Enum { variant, data, .. } => {
let num_fields = variant.data.fields.len();
if num_fields == 0 {
Ok(())
} else if (0..num_fields).all(|idx| data.get(idx)) {
Ok(())
} else {
let first_missing_idx = (0..num_fields).find(|&idx| !data.get(idx));
if let Some(missing_idx) = first_missing_idx {
let field_name = variant.data.fields[missing_idx].name;
Err(ReflectErrorKind::UninitializedField {
shape: self.allocated.shape(),
field_name,
})
} else {
Err(ReflectErrorKind::UninitializedValue {
shape: self.allocated.shape(),
})
}
}
}
Tracker::SmartPointer {
building_inner,
pending_inner,
} => {
if *building_inner {
Err(ReflectErrorKind::UninitializedValue {
shape: self.allocated.shape(),
})
} else if let Some(inner_ptr) = pending_inner.take() {
let smart_ptr_shape = self.allocated.shape();
if let Def::Pointer(smart_ptr_def) = smart_ptr_shape.def {
Self::complete_pending_smart_pointer(
smart_ptr_shape,
smart_ptr_def,
self.data,
inner_ptr,
)?;
self.is_init = true;
Ok(())
} else {
Err(ReflectErrorKind::OperationFailed {
shape: smart_ptr_shape,
operation: "SmartPointer frame without SmartPointer definition",
})
}
} else if self.is_init {
Ok(())
} else {
Err(ReflectErrorKind::UninitializedValue {
shape: self.allocated.shape(),
})
}
}
Tracker::SmartPointerSlice { building_item, .. } => {
if *building_item {
Err(ReflectErrorKind::UninitializedValue {
shape: self.allocated.shape(),
})
} else {
Ok(())
}
}
Tracker::List {
current_child,
rope,
} => {
if self.is_init && current_child.is_none() {
if let Some(rope) = rope.take()
&& let Def::List(list_def) = self.allocated.shape().def
{
Self::drain_rope_into_vec(rope, &list_def, self.data)?;
}
Ok(())
} else {
Err(ReflectErrorKind::UninitializedValue {
shape: self.allocated.shape(),
})
}
}
Tracker::Map {
insert_state,
pending_entries,
..
} => {
if self.is_init && matches!(insert_state, MapInsertState::Idle) {
if !pending_entries.is_empty()
&& let Def::Map(map_def) = self.allocated.shape().def
{
Self::drain_pending_into_map(pending_entries, &map_def, self.data)?;
}
Ok(())
} else {
Err(ReflectErrorKind::UninitializedValue {
shape: self.allocated.shape(),
})
}
}
Tracker::Set { current_child } => {
if self.is_init && !*current_child {
Ok(())
} else {
Err(ReflectErrorKind::UninitializedValue {
shape: self.allocated.shape(),
})
}
}
Tracker::Option {
building_inner,
pending_inner,
} => {
if *building_inner {
Err(ReflectErrorKind::UninitializedValue {
shape: self.allocated.shape(),
})
} else {
if let Some(inner_ptr) = pending_inner.take()
&& let Def::Option(option_def) = self.allocated.shape().def
{
Self::complete_pending_option(option_def, self.data, inner_ptr)?;
}
Ok(())
}
}
Tracker::Result { building_inner, .. } => {
if *building_inner {
Err(ReflectErrorKind::UninitializedValue {
shape: self.allocated.shape(),
})
} else {
Ok(())
}
}
Tracker::Inner { building_inner } => {
if *building_inner {
Err(ReflectErrorKind::UninitializedValue {
shape: self.allocated.shape(),
})
} else if self.is_init {
Ok(())
} else {
Err(ReflectErrorKind::UninitializedValue {
shape: self.allocated.shape(),
})
}
}
Tracker::DynamicValue { state } => {
if matches!(state, DynamicValueState::Uninit) {
Err(ReflectErrorKind::UninitializedValue {
shape: self.allocated.shape(),
})
} else {
if let DynamicValueState::Object {
pending_entries,
insert_state,
} = state
{
if !matches!(insert_state, DynamicObjectInsertState::Idle) {
return Err(ReflectErrorKind::UninitializedValue {
shape: self.allocated.shape(),
});
}
if !pending_entries.is_empty()
&& let Def::DynamicValue(dyn_def) = self.allocated.shape().def
{
let object_ptr = unsafe { self.data.assume_init() };
let value_shape = self.allocated.shape();
for (key, value_ptr) in pending_entries.drain(..) {
unsafe {
(dyn_def.vtable.insert_object_entry)(
object_ptr,
&key,
value_ptr.assume_init(),
);
}
if let Ok(layout) = value_shape.layout.sized_layout()
&& layout.size() > 0
{
unsafe {
alloc::alloc::dealloc(value_ptr.as_mut_byte_ptr(), layout);
}
}
}
}
}
if let DynamicValueState::Array {
pending_elements,
building_element,
} = state
{
if *building_element {
return Err(ReflectErrorKind::UninitializedValue {
shape: self.allocated.shape(),
});
}
if !pending_elements.is_empty()
&& let Def::DynamicValue(dyn_def) = self.allocated.shape().def
{
let array_ptr = unsafe { self.data.assume_init() };
let element_shape = self.allocated.shape();
for element_ptr in pending_elements.drain(..) {
unsafe {
(dyn_def.vtable.push_array_element)(
array_ptr,
element_ptr.assume_init(),
);
}
if let Ok(layout) = element_shape.layout.sized_layout()
&& layout.size() > 0
{
unsafe {
alloc::alloc::dealloc(
element_ptr.as_mut_byte_ptr(),
layout,
);
}
}
}
}
}
Ok(())
}
}
}
}
#[allow(unsafe_code)]
fn fill_and_require_fields(
&mut self,
plans: &[FieldInitPlan],
num_fields: usize,
type_plan_core: &TypePlanCore,
) -> Result<(), ReflectErrorKind> {
if !self.is_init
&& matches!(self.tracker, Tracker::Scalar)
&& matches!(self.allocated.shape().ty, Type::User(UserType::Struct(_)))
{
if unsafe { self.allocated.shape().call_default_in_place(self.data) }.is_some() {
self.is_init = true;
return Ok(());
}
self.tracker = Tracker::Struct {
iset: ISet::new(num_fields),
current_child: None,
};
}
let iset = match &mut self.tracker {
Tracker::Struct { iset, .. } => iset,
Tracker::Enum { data, .. } => data,
Tracker::Scalar if self.is_init => return Ok(()),
_ => return Ok(()),
};
let all_fields_set = iset.all_set(num_fields);
for plan in plans {
if !all_fields_set && !iset.get(plan.index) {
match &plan.fill_rule {
FillRule::Defaultable(default) => {
let field_ptr = unsafe { self.data.field_uninit(plan.offset) };
let success = match default {
FieldDefault::Custom(default_fn) => {
unsafe { default_fn(field_ptr) };
true
}
FieldDefault::FromTrait(shape) => {
unsafe { shape.call_default_in_place(field_ptr) }.is_some()
}
};
if success {
iset.set(plan.index);
} else {
return Err(ReflectErrorKind::UninitializedField {
shape: self.allocated.shape(),
field_name: plan.name,
});
}
}
FillRule::Required => {
return Err(ReflectErrorKind::UninitializedField {
shape: self.allocated.shape(),
field_name: plan.name,
});
}
}
}
if !plan.validators.is_empty() {
let field_ptr = unsafe { self.data.field_init(plan.offset) };
for validator in type_plan_core.validators(plan.validators) {
validator.run(field_ptr.into(), plan.name, self.allocated.shape())?;
}
}
}
Ok(())
}
pub(crate) const fn get_enum_type(&self) -> Result<EnumType, ReflectErrorKind> {
match self.allocated.shape().ty {
Type::User(UserType::Enum(e)) => Ok(e),
_ => Err(ReflectErrorKind::WasNotA {
expected: "enum",
actual: self.allocated.shape(),
}),
}
}
pub(crate) fn get_field(&self) -> Option<&Field> {
match self.allocated.shape().ty {
Type::User(user_type) => match user_type {
UserType::Struct(struct_type) => {
if let Tracker::Struct {
current_child: Some(idx),
..
} = &self.tracker
{
struct_type.fields.get(*idx)
} else {
None
}
}
UserType::Enum(_enum_type) => {
if let Tracker::Enum {
variant,
current_child: Some(idx),
..
} = &self.tracker
{
variant.data.fields.get(*idx)
} else {
None
}
}
_ => None,
},
_ => None,
}
}
}
impl<'facet, const BORROW: bool> Partial<'facet, BORROW> {
#[inline]
pub(crate) const fn frames(&self) -> &Vec<Frame> {
self.mode.stack()
}
#[inline]
pub(crate) fn frames_mut(&mut self) -> &mut Vec<Frame> {
self.mode.stack_mut()
}
#[inline]
pub const fn is_deferred(&self) -> bool {
self.mode.is_deferred()
}
#[inline]
pub(crate) const fn start_depth(&self) -> Option<usize> {
self.mode.start_depth()
}
pub(crate) fn derive_path(&self) -> Path {
let root_shape = self
.frames()
.first()
.map(|f| f.allocated.shape())
.unwrap_or_else(|| {
<() as facet_core::Facet>::SHAPE
});
let mut path = Path::new(root_shape);
let frames = self.frames();
for (frame_idx, frame) in frames.iter().enumerate() {
match &frame.tracker {
Tracker::Struct {
current_child: Some(idx),
..
} => {
path.push(PathStep::Field(*idx as u32));
}
Tracker::Enum {
current_child: Some(idx),
..
} => {
path.push(PathStep::Field(*idx as u32));
}
Tracker::List {
current_child: Some(idx),
..
} => {
path.push(PathStep::Index(*idx as u32));
}
Tracker::Array {
current_child: Some(idx),
..
} => {
path.push(PathStep::Index(*idx as u32));
}
Tracker::Option {
building_inner: true,
..
} => {
path.push(PathStep::OptionSome);
}
Tracker::SmartPointer {
building_inner: true,
..
} => {
path.push(PathStep::Deref);
}
Tracker::SmartPointerSlice {
current_child: Some(idx),
..
} => {
path.push(PathStep::Index(*idx as u32));
}
Tracker::Inner {
building_inner: true,
} => {
path.push(PathStep::Inner);
}
Tracker::Map {
current_entry_index: Some(idx),
building_key,
..
} => {
if *building_key {
path.push(PathStep::MapKey(*idx as u32));
} else {
path.push(PathStep::MapValue(*idx as u32));
}
}
_ => {}
}
if frame_idx + 1 < frames.len() && frames[frame_idx + 1].using_custom_deserialization {
path.push(PathStep::Proxy);
}
}
path
}
}
impl<'facet, const BORROW: bool> Drop for Partial<'facet, BORROW> {
fn drop(&mut self) {
trace!("🧹 Partial is being dropped");
if let FrameMode::Deferred {
stored_frames,
stack,
..
} = &mut self.mode
{
let mut stored_frames = core::mem::take(stored_frames);
let mut paths: Vec<_> = stored_frames.keys().cloned().collect();
paths.sort_by_key(|p| core::cmp::Reverse(p.steps.len()));
for path in paths {
if let Some(mut frame) = stored_frames.remove(&path) {
let parent_path = Path {
shape: path.shape,
steps: path.steps[..path.steps.len().saturating_sub(1)].to_vec(),
};
let find_parent_frame =
|stored: &mut alloc::collections::BTreeMap<Path, Frame>,
stk: &mut [Frame],
pp: &Path|
-> Option<*mut Frame> {
if let Some(pf) = stored.get_mut(pp) {
Some(pf as *mut Frame)
} else {
let idx = pp.steps.len();
stk.get_mut(idx).map(|f| f as *mut Frame)
}
};
match path.steps.last() {
Some(PathStep::Field(field_idx)) => {
let field_idx = *field_idx as usize;
if let Some(parent_ptr) =
find_parent_frame(&mut stored_frames, stack, &parent_path)
{
let parent_frame = unsafe { &mut *parent_ptr };
match &mut parent_frame.tracker {
Tracker::Struct { iset, .. } => {
iset.unset(field_idx);
}
Tracker::Enum { data, .. } => {
data.unset(field_idx);
}
_ => {}
}
}
}
Some(PathStep::MapKey(entry_idx)) => {
let entry_idx = *entry_idx as usize;
if let Some(parent_ptr) =
find_parent_frame(&mut stored_frames, stack, &parent_path)
{
let parent_frame = unsafe { &mut *parent_ptr };
if let Tracker::Map {
insert_state,
pending_entries,
..
} = &mut parent_frame.tracker
{
if let MapInsertState::PushingKey {
key_frame_on_stack, ..
} = insert_state
{
*key_frame_on_stack = false;
}
if entry_idx < pending_entries.len() {
}
}
}
}
Some(PathStep::MapValue(entry_idx)) => {
let entry_idx = *entry_idx as usize;
if let Some(parent_ptr) =
find_parent_frame(&mut stored_frames, stack, &parent_path)
{
let parent_frame = unsafe { &mut *parent_ptr };
if let Tracker::Map {
pending_entries, ..
} = &mut parent_frame.tracker
{
if entry_idx < pending_entries.len() {
pending_entries.remove(entry_idx);
}
}
}
}
Some(PathStep::Index(_)) => {
}
_ => {}
}
frame.deinit();
frame.dealloc();
}
}
}
loop {
let stack = self.mode.stack_mut();
if stack.is_empty() {
break;
}
let mut frame = stack.pop().unwrap();
if let FrameOwnership::Field { field_idx } = frame.ownership
&& let Some(parent_frame) = stack.last_mut()
{
match &mut parent_frame.tracker {
Tracker::Struct { iset, .. } => {
iset.unset(field_idx);
}
Tracker::Enum { data, .. } => {
data.unset(field_idx);
}
Tracker::Array { iset, .. } => {
iset.unset(field_idx);
}
_ => {}
}
}
frame.deinit();
frame.dealloc();
}
}
}
#[cfg(test)]
mod size_tests {
use super::*;
use core::mem::size_of;
#[test]
fn print_type_sizes() {
eprintln!("\n=== Type Sizes ===");
eprintln!("Frame: {} bytes", size_of::<Frame>());
eprintln!("Tracker: {} bytes", size_of::<Tracker>());
eprintln!("ISet: {} bytes", size_of::<ISet>());
eprintln!("AllocatedShape: {} bytes", size_of::<AllocatedShape>());
eprintln!("FrameOwnership: {} bytes", size_of::<FrameOwnership>());
eprintln!("PtrUninit: {} bytes", size_of::<facet_core::PtrUninit>());
eprintln!("Option<usize>: {} bytes", size_of::<Option<usize>>());
eprintln!(
"Option<&'static facet_core::ProxyDef>: {} bytes",
size_of::<Option<&'static facet_core::ProxyDef>>()
);
eprintln!(
"TypePlanNode: {} bytes",
size_of::<typeplan::TypePlanNode>()
);
eprintln!("Vec<Frame>: {} bytes", size_of::<Vec<Frame>>());
eprintln!("MapInsertState: {} bytes", size_of::<MapInsertState>());
eprintln!(
"DynamicValueState: {} bytes",
size_of::<DynamicValueState>()
);
eprintln!("===================\n");
}
}