1use crate::{Peek, ReflectError, ValueId};
2use crate::{debug, trace};
3#[cfg(feature = "log")]
4use alloc::string::ToString;
5#[cfg(feature = "log")]
6use owo_colors::OwoColorize;
7
8use alloc::format;
9use alloc::{vec, vec::Vec};
10use bitflags::bitflags;
11use core::{fmt, marker::PhantomData};
12use facet_core::{
13 Def, DefaultInPlaceFn, EnumType, Facet, FieldError, PointerType, PrimitiveType, PtrConst,
14 PtrMut, PtrUninit, Repr, ScalarAffinity, SequenceType, Shape, StructType, Type, UserType,
15 Variant,
16};
17use flat_map::FlatMap;
18
19use alloc::string::String;
20
21mod iset;
22pub use iset::*;
23
24mod put_f64;
25mod put_shape;
26
27mod enum_;
28mod flat_map;
29
30mod heap_value;
31pub use heap_value::*;
32
33fn ty_kind(ty: &Type) -> &'static str {
34 use PointerType::*;
35 use PrimitiveType::*;
36 use SequenceType::*;
37 use Type::*;
38 use UserType::*;
39
40 match ty {
41 Primitive(Boolean) => "primitive(boolean)",
42 Primitive(Textual(_)) => "primitive(textual)",
43 Primitive(Numeric(_)) => "primitive(numeric)",
44 Primitive(Never) => "primitive(never)",
45 Sequence(Tuple(_)) => "sequence(tuple)",
46 Sequence(Array(_)) => "sequence(array)",
47 Sequence(Slice(_)) => "sequence(slice)",
48 User(Struct(_)) => "user(struct)",
49 User(Enum(_)) => "user(enum)",
50 User(Union(_)) => "user(union)",
51 User(_) => "user(other)",
52 Pointer(Reference(_)) => "pointer(reference)",
53 Pointer(Raw(_)) => "pointer(raw)",
54 Pointer(Function(_)) => "pointer(function)",
55 _ => "other",
56 }
57}
58
59fn def_kind(def: &Def) -> &'static str {
60 match def {
61 Def::Scalar(_) => "scalar",
62 Def::Map(_) => "map",
63 Def::List(_) => "list",
64 Def::Option(_) => "option",
65 Def::SmartPointer(_) => "smart_ptr",
66 _ => "other",
67 }
68}
69
70pub struct Frame {
72 data: PtrUninit<'static>,
74
75 shape: &'static Shape,
77
78 field_index_in_parent: Option<usize>,
81
82 istate: IState,
86}
87
88impl Frame {
89 fn recompose(id: ValueId, istate: IState) -> Self {
91 Frame {
92 data: PtrUninit::new(id.ptr as *mut u8),
93 shape: id.shape,
94 field_index_in_parent: None,
95 istate,
96 }
97 }
98
99 fn dealloc_if_needed(&mut self) {
101 if self.istate.flags.contains(FrameFlags::ALLOCATED) {
102 trace!(
103 "[{}] {:p} => deallocating {}",
104 self.istate.depth,
105 self.data.as_mut_byte_ptr().magenta(),
106 self.shape.green(),
107 );
108 match self.shape.layout {
109 facet_core::ShapeLayout::Sized(layout) => {
110 if layout.size() != 0 {
111 unsafe {
112 alloc::alloc::dealloc(self.data.as_mut_byte_ptr(), layout);
113 }
114 }
115 }
116 facet_core::ShapeLayout::Unsized => unimplemented!(),
117 }
118 self.istate.flags.remove(FrameFlags::ALLOCATED);
119 } else {
120 trace!(
121 "[{}] {:p} => NOT deallocating {} (not ALLOCATED)",
122 self.istate.depth,
123 self.data.as_mut_byte_ptr().magenta(),
124 self.shape.green(),
125 );
126 }
127 }
128}
129
130struct DisplayToDebug<T>(T);
131
132impl<T> fmt::Debug for DisplayToDebug<T>
133where
134 T: fmt::Display,
135{
136 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
137 fmt::Display::fmt(&self.0, f)
138 }
139}
140
141impl fmt::Debug for Frame {
142 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
143 f.debug_struct("Frame")
144 .field("shape", &DisplayToDebug(&self.shape))
145 .field("def_kind", &def_kind(&self.shape.def))
146 .field("ty_kind", &ty_kind(&self.shape.ty))
147 .field("index", &self.field_index_in_parent)
148 .field("mode", &self.istate.mode)
149 .field("id", &self.id())
150 .finish()
151 }
152}
153
154fn is_fully_initialized(shape: &'static Shape, istate: &IState) -> bool {
156 match shape.ty {
157 Type::User(UserType::Struct(sd)) => istate.fields.are_all_set(sd.fields.len()),
158 Type::User(UserType::Enum(_)) => match istate.variant.as_ref() {
159 None => false,
160 Some(v) => istate.fields.are_all_set(v.data.fields.len()),
161 },
162 _ => istate.fields.are_all_set(1),
163 }
164}
165
166impl Frame {
167 fn id(&self) -> ValueId {
169 ValueId::new(self.shape, self.data.as_byte_ptr())
170 }
171
172 fn is_fully_initialized(&self) -> bool {
174 is_fully_initialized(self.shape, &self.istate)
175 }
176
177 unsafe fn drop_and_dealloc_if_needed(mut self) {
179 trace!(
180 "[Frame::drop] Dropping frame for shape {} at {:p}",
181 self.shape.blue(),
182 self.data.as_byte_ptr()
183 );
184 if let Some(drop_in_place) = self.shape.vtable.drop_in_place {
185 unsafe {
186 trace!(
187 "[Frame::drop] Invoking drop_in_place for shape {} at {:p}",
188 self.shape.green(),
189 self.data.as_byte_ptr()
190 );
191 drop_in_place(self.data.assume_init());
192 }
193 } else {
194 trace!(
195 "[Frame::drop] No drop_in_place function for shape {}",
196 self.shape.blue(),
197 );
198 }
199 self.dealloc_if_needed();
200 }
201
202 unsafe fn mark_fully_initialized(&mut self) {
204 trace!(
205 "[{}] Marking frame as fully initialized: shape={}, type={:?}",
206 self.istate.depth,
207 self.shape.blue(),
208 self.shape.ty
209 );
210 match self.shape.ty {
211 Type::User(UserType::Struct(sd)) => {
212 trace!(
213 "[{}] Setting all {} struct fields as initialized",
214 self.istate.depth,
215 sd.fields.len()
216 );
217 self.istate.fields = ISet::all(sd.fields);
218 }
219 Type::User(UserType::Enum(_)) => {
220 if let Some(variant) = &self.istate.variant {
221 trace!(
222 "[{}] Setting all {} fields of variant '{}' as initialized",
223 self.istate.depth,
224 variant.data.fields.len(),
225 variant.name
226 );
227 self.istate.fields = ISet::all(variant.data.fields);
228 } else {
229 trace!(
230 "[{}] Trying to mark enum as initialized without variant",
231 self.istate.depth
232 );
233
234 let peek = unsafe {
236 Peek::unchecked_new(self.data.assume_init().as_const(), self.shape)
237 };
238 let enum_peek = peek.into_enum().unwrap();
239 let variant = enum_peek.active_variant().unwrap();
240 self.istate.variant = Some(*variant);
241 if variant.data.fields.is_empty() {
242 self.istate.fields.set(0);
244 } else {
245 self.istate.fields = ISet::all(variant.data.fields);
246 }
247 }
248 }
249 _ => {
250 trace!(
251 "[{}] Setting scalar field (0) as initialized",
252 self.istate.depth
253 );
254 self.istate.fields.set(0);
255 }
256 }
257 }
258}
259
260struct IState {
262 variant: Option<Variant>,
264
265 fields: ISet,
267
268 depth: usize,
270
271 mode: FrameMode,
273
274 flags: FrameFlags,
276
277 list_index: Option<usize>,
279
280 #[allow(dead_code)]
282 map_key: Option<String>,
283}
284
285bitflags! {
286 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
288 pub struct FrameFlags: u64 {
289 const EMPTY = 0;
291
292 const ALLOCATED = 1 << 0;
294
295 const MOVED = 1 << 1;
299 }
300
301 }
303
304impl IState {
305 pub fn new(depth: usize, mode: FrameMode, flags: FrameFlags) -> Self {
307 Self {
308 variant: None,
309 fields: Default::default(),
310 depth,
311 mode,
312 flags,
313 list_index: None,
314 map_key: None,
315 }
316 }
317
318 #[allow(dead_code)]
320 pub fn with_list_index(mut self, index: usize) -> Self {
321 self.list_index = Some(index);
322 self
323 }
324
325 #[allow(dead_code)]
327 pub fn with_map_key(mut self, key: String) -> Self {
328 self.map_key = Some(key);
329 self
330 }
331}
332
333#[derive(Debug, Clone, Copy, PartialEq, Eq)]
335pub enum FrameMode {
336 Root,
338 Field,
340 ListElement,
342 MapKey,
344 MapValue {
346 index: usize,
348 },
349 OptionSome,
351 OptionNone,
354}
355
356pub struct Wip<'facet_lifetime> {
358 frames: alloc::vec::Vec<Frame>,
360
361 istates: FlatMap<ValueId, IState>,
363
364 invariant: PhantomData<fn(&'facet_lifetime ()) -> &'facet_lifetime ()>,
365}
366
367impl<'facet_lifetime> Wip<'facet_lifetime> {
368 pub fn put_peek(
370 self,
371 peek: crate::Peek<'_, 'facet_lifetime>,
372 ) -> Result<Wip<'facet_lifetime>, ReflectError> {
373 self.put_shape(peek.data, peek.shape)
374 }
375
376 pub fn frames_count(&self) -> usize {
378 self.frames.len()
379 }
380
381 pub fn alloc_shape(shape: &'static Shape) -> Result<Self, ReflectError> {
383 let data = shape
384 .allocate()
385 .map_err(|_| ReflectError::Unsized { shape })?;
386 Ok(Self {
387 frames: alloc::vec![Frame {
388 data,
389 shape,
390 field_index_in_parent: None,
391 istate: IState::new(0, FrameMode::Root, FrameFlags::ALLOCATED),
392 }],
393 istates: Default::default(),
394 invariant: PhantomData,
395 })
396 }
397
398 pub fn alloc<S: Facet<'facet_lifetime>>() -> Result<Self, ReflectError> {
400 Self::alloc_shape(S::SHAPE)
401 }
402
403 fn track(&mut self, frame: Frame) {
404 if frame.istate.flags.contains(FrameFlags::MOVED) {
410 return;
412 }
413
414 self.istates.insert(frame.id(), frame.istate);
415 }
416
417 unsafe fn mark_moved_out_of(&mut self, frame: &mut Frame) {
418 unsafe fn mark_subtree_moved(wip: &mut Wip, id: ValueId) {
421 unsafe {
423 if let Some(mut istate) = wip.istates.remove(&id) {
425 istate.flags.insert(FrameFlags::MOVED);
427
428 match id.shape.ty {
430 Type::User(UserType::Struct(sd)) => {
431 let container_ptr = PtrUninit::new(id.ptr as *mut u8);
432 for field in sd.fields.iter() {
433 let field_ptr_uninit = container_ptr.field_uninit_at(field.offset);
434 let field_id =
435 ValueId::new(field.shape(), field_ptr_uninit.as_byte_ptr());
436 mark_subtree_moved(wip, field_id);
438 }
439 }
440 Type::User(UserType::Enum(_)) => {
441 if let Some(variant) = &istate.variant {
443 let container_ptr = PtrUninit::new(id.ptr as *mut u8);
444 for field in variant.data.fields.iter() {
445 let field_ptr_uninit =
446 container_ptr.field_uninit_at(field.offset);
447 let field_id =
448 ValueId::new(field.shape(), field_ptr_uninit.as_byte_ptr());
449 mark_subtree_moved(wip, field_id);
451 }
452 }
453 }
454 _ => {}
458 }
459
460 if istate.flags.contains(FrameFlags::ALLOCATED) {
463 let mut temp_frame = Frame::recompose(id, istate);
465 temp_frame.dealloc_if_needed();
466 }
467 }
468 }
470 }
471
472 unsafe {
475 let frame_id = frame.id();
477
478 let variant_opt = frame.istate.variant;
480
481 frame.istate.flags.insert(FrameFlags::MOVED);
483 ISet::clear(&mut frame.istate.fields);
484
485 match frame.shape.ty {
488 Type::User(UserType::Struct(sd)) => {
489 let container_ptr = PtrUninit::new(frame_id.ptr as *mut u8);
490 for field in sd.fields.iter() {
491 let field_ptr_uninit = container_ptr.field_uninit_at(field.offset);
492 let field_id = ValueId::new(field.shape(), field_ptr_uninit.as_byte_ptr());
493 mark_subtree_moved(self, field_id);
494 }
495 }
496 Type::User(UserType::Enum(_)) => {
497 if let Some(variant) = &variant_opt {
499 let container_ptr = PtrUninit::new(frame_id.ptr as *mut u8);
500 for field in variant.data.fields.iter() {
501 let field_ptr_uninit = container_ptr.field_uninit_at(field.offset);
502 let field_id =
503 ValueId::new(field.shape(), field_ptr_uninit.as_byte_ptr());
504 mark_subtree_moved(self, field_id);
505 }
506 }
507 }
508 _ => {}
510 }
511
512 frame.istate.variant = None;
514
515 self.istates.remove(&frame_id);
517
518 if frame.istate.flags.contains(FrameFlags::ALLOCATED) {
520 frame.dealloc_if_needed();
521 }
522 }
523 }
524
525 pub fn shape(&self) -> &'static Shape {
527 self.frames.last().expect("must have frames left").shape
528 }
529
530 pub fn innermost_shape(&self) -> &'static Shape {
534 let mut current_shape = self.shape();
535
536 while let Some(inner_fn) = current_shape.inner {
538 current_shape = inner_fn();
539 }
540
541 current_shape
542 }
543
544 pub fn in_option(&self) -> bool {
546 let Some(frame) = self.frames.last() else {
547 return false;
548 };
549 matches!(frame.istate.mode, FrameMode::OptionSome)
550 }
551
552 pub fn mode(&self) -> FrameMode {
554 self.frames.last().unwrap().istate.mode
555 }
556
557 pub fn build(mut self) -> Result<HeapValue<'facet_lifetime>, ReflectError> {
559 debug!("[{}] ⚒️ It's BUILD time", self.frames.len());
560
561 if self.frames.is_empty() {
563 panic!("No frames in WIP during build: stack is empty (you popped too much)");
564 }
565 if self.frames.len() != 1 {
566 panic!(
567 "You must pop frames so that only the root frame remains before calling build (frames left: {})",
568 self.frames.len()
569 );
570 }
571
572 let root_frame = &self.frames[0];
574
575 enum FrameRef {
576 Root,
577 ById(ValueId),
578 }
579 let mut to_check = alloc::vec![FrameRef::Root];
580
581 while let Some(fr) = to_check.pop() {
583 let (id, istate) = match fr {
584 FrameRef::Root => (root_frame.id(), &root_frame.istate),
585 FrameRef::ById(id) => {
586 let istate = self.istates.get(&id).unwrap();
588 (id, istate)
589 }
590 };
591
592 trace!(
593 "Checking shape {} at {:p}, flags={:?}, mode={:?}, fully_initialized={}",
594 id.shape.blue(),
595 id.ptr,
596 istate.flags.bright_magenta(),
597 istate.mode.yellow(),
598 if is_fully_initialized(id.shape, istate) {
599 "✅"
600 } else {
601 "❌"
602 }
603 );
604
605 if istate.flags.contains(FrameFlags::MOVED) {
607 trace!(
608 "{}",
609 "Frame was moved out of, skipping initialization check".yellow()
610 );
611 continue;
612 }
613
614 if !matches!(id.shape.def, Def::Undefined) {
620 if !istate.fields.are_all_set(1) {
621 match istate.mode {
623 FrameMode::OptionNone => {
624 debug!("Found uninitialized value (option none) — {}", id.shape);
626 return Err(ReflectError::UninitializedValue { shape: id.shape });
627 }
628 _ => {
630 debug!(
631 "Found uninitialized value (list/map/option/etc. — {})",
632 id.shape
633 );
634 return Err(ReflectError::UninitializedValue { shape: id.shape });
635 }
636 }
637 }
638 } else {
646 match id.shape.ty {
647 Type::User(UserType::Struct(sd)) => {
648 for i in 0..sd.fields.len() {
650 if !istate.fields.has(i) {
651 let field = &sd.fields[i];
652 trace!("Found uninitialized field: {}", field.name);
653 return Err(ReflectError::UninitializedField {
654 shape: id.shape,
655 field_name: field.name,
656 });
657 }
658 }
659
660 let container_ptr = PtrUninit::new(id.ptr as *mut u8);
661
662 #[allow(clippy::unused_enumerate_index)]
664 for (_i, field) in sd.fields.iter().enumerate() {
665 let field_shape = field.shape();
666 let field_ptr = unsafe { container_ptr.field_init_at(field.offset) };
667 let field_id = ValueId::new(field_shape, field_ptr.as_byte_ptr());
668
669 if self.istates.contains_key(&field_id) {
670 debug!(
671 "Queueing struct field check: #{} '{}' of {}: shape={}, ptr={:p}",
672 _i.to_string().bright_cyan(),
673 field.name.bright_blue(),
674 id.shape.blue(),
675 field_shape.green(),
676 field_ptr.as_byte_ptr()
677 );
678 to_check.push(FrameRef::ById(field_id));
679 }
680 }
681 }
682 Type::User(UserType::Enum(_ed)) => {
683 if let Some(variant) = &istate.variant {
684 for (i, field) in variant.data.fields.iter().enumerate() {
686 if !istate.fields.has(i) {
687 trace!("Found uninitialized field: {}", field.name);
688 return Err(ReflectError::UninitializedEnumField {
689 shape: id.shape,
690 variant_name: variant.name,
691 field_name: field.name,
692 });
693 }
694 }
695
696 #[allow(clippy::unused_enumerate_index)]
698 for (_i, field) in variant.data.fields.iter().enumerate() {
699 let field_shape = field.shape();
700 let container_ptr = PtrUninit::new(id.ptr as *mut u8);
701 let field_ptr =
703 unsafe { container_ptr.field_init_at(field.offset) };
704 let field_id = ValueId::new(field_shape, field_ptr.as_byte_ptr());
705
706 if self.istates.contains_key(&field_id) {
707 debug!(
708 "Queueing enum field check: #{} '{}' of variant '{}' of {}: shape={}, ptr={:p}",
709 _i.to_string().bright_cyan(),
710 field.name.bright_blue(),
711 variant.name.yellow(),
712 id.shape.blue(),
713 field_shape.green(),
714 field_ptr.as_byte_ptr()
715 );
716 to_check.push(FrameRef::ById(field_id));
717 }
718 }
719 } else {
720 debug!("Found no variant selected for enum");
722 return Err(ReflectError::NoVariantSelected { shape: id.shape });
723 }
724 }
725 _ => {
727 if !istate.fields.are_all_set(1) {
729 debug!("Found uninitialized value (other)");
730 return Err(ReflectError::UninitializedValue { shape: id.shape });
731 }
732 }
733 }
734 }
735 }
736
737 debug!("All reachable frames checked and initialized.");
739
740 let root_shape = root_frame.shape;
743 let root_data = unsafe { root_frame.data.assume_init() };
744 if let Some(invariant_fn) = root_shape.vtable.invariants {
745 debug!(
746 "Checking invariants for root shape {} at {:p}",
747 root_shape.green(),
748 root_data.as_byte_ptr()
749 );
750 if !unsafe { invariant_fn(PtrConst::new(root_data.as_byte_ptr())) } {
751 return Err(ReflectError::InvariantViolation {
752 invariant: "Custom validation function returned false",
753 });
754 }
755 } else {
756 debug!(
757 "No invariants to check for root shape {}",
758 root_shape.blue()
759 );
760 }
761
762 {
764 FlatMap::clear(&mut self.istates);
765 self.frames.clear();
766 }
767
768 let guard = Guard {
770 ptr: root_data.as_mut_byte_ptr(),
771 layout: match root_shape.layout {
772 facet_core::ShapeLayout::Sized(layout) => layout,
773 facet_core::ShapeLayout::Unsized => panic!("Unsized layout not supported"),
774 },
775 };
776
777 Ok(HeapValue {
778 guard: Some(guard),
779 shape: root_shape,
780 phantom: PhantomData,
781 })
782 }
783
784 pub fn field(mut self, index: usize) -> Result<Self, ReflectError> {
796 let frame = self.frames.last_mut().unwrap();
797 let shape = frame.shape;
798
799 let (field, field_offset) = match shape.ty {
800 Type::User(UserType::Struct(def)) => {
801 if index >= def.fields.len() {
802 return Err(ReflectError::FieldError {
803 shape,
804 field_error: FieldError::NoSuchField,
805 });
806 }
807 let field = &def.fields[index];
808 (field, field.offset)
809 }
810 Type::User(UserType::Enum(_)) => {
811 let Some(variant) = frame.istate.variant.as_ref() else {
812 return Err(ReflectError::OperationFailed {
813 shape,
814 operation: "tried to access a field but no variant was selected",
815 });
816 };
817
818 if index >= variant.data.fields.len() {
819 return Err(ReflectError::FieldError {
820 shape,
821 field_error: FieldError::NoSuchField,
822 });
823 }
824
825 let field = &variant.data.fields[index];
826 (field, field.offset)
827 }
828 _ => {
829 return Err(ReflectError::WasNotA {
830 expected: "struct or enum",
831 actual: shape,
832 });
833 }
834 };
835
836 let field_data = unsafe { frame.data.field_uninit_at(field_offset) };
837
838 let mut frame = Frame {
839 data: field_data,
840 shape: field.shape(),
841 field_index_in_parent: Some(index),
842 istate: IState::new(self.frames.len(), FrameMode::Field, FrameFlags::EMPTY),
844 };
845 debug!(
846 "[{}] Selecting field {} ({}#{}) of {}",
847 self.frames.len(),
848 field.name.blue(),
849 field.shape().green(),
850 index.yellow(),
851 shape.blue(),
852 );
853 if let Some(iset) = self.istates.remove(&frame.id()) {
854 trace!(
855 "[{}] Restoring saved state for {} (istate.mode = {:?}, istate.fields = {:?}, istate.flags = {:?}, istate.depth = {:?})",
856 self.frames.len(),
857 frame.id().shape.blue(),
858 iset.mode,
859 iset.fields,
860 iset.flags,
861 iset.depth
862 );
863 frame.istate = iset;
864 } else {
865 trace!(
866 "[{}] no saved state for field {} ({}#{}) of {}",
867 self.frames.len(),
868 field.name.blue(),
869 field.shape().green(),
870 index.yellow(),
871 shape.blue(),
872 );
873 }
874 self.frames.push(frame);
875 Ok(self)
876 }
877
878 pub fn field_index(&self, name: &str) -> Option<usize> {
890 fn find_field_index(fields: &'static [facet_core::Field], name: &str) -> Option<usize> {
891 fields.iter().position(|f| f.name == name)
892 }
893
894 let frame = self.frames.last()?;
895 match frame.shape.ty {
896 Type::User(UserType::Struct(def)) => find_field_index(def.fields, name),
897 Type::User(UserType::Enum(_)) => {
898 let variant = frame.istate.variant.as_ref()?;
899 find_field_index(variant.data.fields, name)
900 }
901 _ => None,
902 }
903 }
904
905 pub fn field_named(self, name: &str) -> Result<Self, ReflectError> {
917 let frame = self.frames.last().unwrap();
918 let shape = frame.shape;
919
920 if let Type::User(UserType::Enum(_)) = shape.ty {
922 if frame.istate.variant.is_none() {
923 return Err(ReflectError::OperationFailed {
924 shape,
925 operation: "tried to access a field by name but no variant was selected",
926 });
927 }
928 }
929
930 let index = self.field_index(name).ok_or(ReflectError::FieldError {
931 shape,
932 field_error: FieldError::NoSuchField,
933 })?;
934
935 self.field(index)
936 }
937
938 pub fn put<T: Facet<'facet_lifetime>>(
949 self,
950 t: T,
951 ) -> Result<Wip<'facet_lifetime>, ReflectError> {
952 let shape = T::SHAPE;
953 let ptr_const = PtrConst::new(&t as *const T as *const u8);
954 let res = self.put_shape(ptr_const, shape);
955 core::mem::forget(t); res
957 }
958
959 pub fn try_put<T: Facet<'facet_lifetime>>(
970 self,
971 t: T,
972 ) -> Result<Wip<'facet_lifetime>, ReflectError> {
973 let shape = T::SHAPE;
974 let ptr_const = PtrConst::new(&t as *const T as *const u8);
975 let res = self.put_shape(ptr_const, shape);
976 core::mem::forget(t); res
978 }
979
980 pub fn parse(mut self, s: &str) -> Result<Self, ReflectError> {
982 let Some(frame) = self.frames.last_mut() else {
983 return Err(ReflectError::OperationFailed {
984 shape: <()>::SHAPE,
985 operation: "tried to parse value but there was no frame",
986 });
987 };
988
989 let shape = frame.shape;
990 let index = frame.field_index_in_parent;
991
992 let Some(parse_fn) = frame.shape.vtable.parse else {
993 return Err(ReflectError::OperationFailed {
994 shape: frame.shape,
995 operation: "type does not implement Parse",
996 });
997 };
998 match unsafe { (parse_fn)(s, frame.data) } {
999 Ok(_res) => {
1000 unsafe {
1001 frame.mark_fully_initialized();
1002 }
1003
1004 self.mark_field_as_initialized(shape, index)?;
1006
1007 Ok(self)
1008 }
1009 Err(_) => Err(ReflectError::OperationFailed {
1010 shape,
1011 operation: "parsing",
1012 }),
1013 }
1014 }
1015
1016 pub fn put_from_fn(mut self, default_in_place: DefaultInPlaceFn) -> Result<Self, ReflectError> {
1018 let Some(frame) = self.frames.last_mut() else {
1019 return Err(ReflectError::OperationFailed {
1020 shape: <()>::SHAPE,
1021 operation: "tried to put value from fn but there was no frame",
1022 });
1023 };
1024
1025 unsafe {
1026 default_in_place(frame.data);
1027 trace!("Marking frame as fully initialized...");
1028 frame.mark_fully_initialized();
1029 trace!("Marking frame as fully initialized... done!");
1030 }
1031
1032 let shape = frame.shape;
1033 let index = frame.field_index_in_parent;
1034
1035 self.mark_field_as_initialized(shape, index)?;
1037
1038 Ok(self)
1039 }
1040
1041 pub fn put_default(self) -> Result<Self, ReflectError> {
1043 let Some(frame) = self.frames.last() else {
1044 return Err(ReflectError::OperationFailed {
1045 shape: <()>::SHAPE,
1046 operation: "tried to put default value but there was no frame",
1047 });
1048 };
1049
1050 let vtable = frame.shape.vtable;
1051 let Some(default_in_place) = vtable.default_in_place else {
1052 return Err(ReflectError::OperationFailed {
1053 shape: frame.shape,
1054 operation: "type does not implement Default",
1055 });
1056 };
1057
1058 self.put_from_fn(default_in_place)
1059 }
1060
1061 fn mark_field_as_initialized(
1063 &mut self,
1064 shape: &'static Shape,
1065 index: Option<usize>,
1066 ) -> Result<(), ReflectError> {
1067 if let Some(index) = index {
1068 let parent_index = self.frames.len().saturating_sub(2);
1069 #[cfg(feature = "log")]
1070 let num_frames = self.frames.len();
1071 let Some(parent) = self.frames.get_mut(parent_index) else {
1072 return Err(ReflectError::OperationFailed {
1073 shape,
1074 operation: "was supposed to mark a field as initialized, but there was no parent frame",
1075 });
1076 };
1077 #[cfg(feature = "log")]
1078 let parent_shape = parent.shape;
1079 trace!(
1080 "[{}] {}.{} initialized with {}",
1081 num_frames,
1082 parent_shape.blue(),
1083 index.yellow(),
1084 shape.green()
1085 );
1086
1087 if matches!(parent.shape.ty, Type::User(UserType::Enum(_)))
1088 && parent.istate.variant.is_none()
1089 {
1090 return Err(ReflectError::OperationFailed {
1091 shape,
1092 operation: "was supposed to mark a field as initialized, but the parent frame was an enum and didn't have a variant chosen",
1093 });
1094 }
1095
1096 if parent.istate.fields.has(index) {
1097 return Err(ReflectError::OperationFailed {
1098 shape,
1099 operation: "was supposed to mark a field as initialized, but the parent frame already had it marked as initialized",
1100 });
1101 }
1102
1103 parent.istate.fields.set(index);
1104 }
1105 Ok(())
1106 }
1107
1108 pub fn element_shape(&self) -> Result<&'static Shape, ReflectError> {
1110 let frame = self.frames.last().unwrap();
1111 let shape = frame.shape;
1112
1113 match shape.def {
1114 Def::List(list_def) => Ok(list_def.t()),
1115 _ => Err(ReflectError::WasNotA {
1116 expected: "list or array",
1117 actual: shape,
1118 }),
1119 }
1120 }
1121
1122 pub fn key_shape(&self) -> Result<&'static Shape, ReflectError> {
1124 let frame = self.frames.last().unwrap();
1125 let shape = frame.shape;
1126
1127 match shape.def {
1128 Def::Map(map_def) => Ok(map_def.k()),
1129 _ => Err(ReflectError::WasNotA {
1130 expected: "map",
1131 actual: shape,
1132 }),
1133 }
1134 }
1135
1136 pub fn put_empty_list(mut self) -> Result<Self, ReflectError> {
1138 let Some(frame) = self.frames.last_mut() else {
1139 return Err(ReflectError::OperationFailed {
1140 shape: <()>::SHAPE,
1141 operation: "tried to create empty list but there was no frame",
1142 });
1143 };
1144
1145 if !matches!(frame.shape.def, Def::List(_)) {
1146 return Err(ReflectError::WasNotA {
1147 expected: "list or array",
1148 actual: frame.shape,
1149 });
1150 }
1151
1152 let vtable = frame.shape.vtable;
1153
1154 let Some(default_in_place) = vtable.default_in_place else {
1156 return Err(ReflectError::OperationFailed {
1157 shape: frame.shape,
1158 operation: "list type does not implement Default",
1159 });
1160 };
1161
1162 unsafe {
1163 default_in_place(frame.data);
1164 frame.mark_fully_initialized();
1165 }
1166
1167 let shape = frame.shape;
1168 let index = frame.field_index_in_parent;
1169
1170 self.mark_field_as_initialized(shape, index)?;
1172
1173 Ok(self)
1174 }
1175
1176 pub fn put_empty_map(mut self) -> Result<Self, ReflectError> {
1178 let Some(frame) = self.frames.last_mut() else {
1179 return Err(ReflectError::OperationFailed {
1180 shape: <()>::SHAPE,
1181 operation: "tried to create empty map but there was no frame",
1182 });
1183 };
1184
1185 if !matches!(frame.shape.def, Def::Map(_)) {
1186 return Err(ReflectError::WasNotA {
1187 expected: "map or hash map",
1188 actual: frame.shape,
1189 });
1190 }
1191
1192 let vtable = frame.shape.vtable;
1193
1194 let Some(default_in_place) = vtable.default_in_place else {
1196 return Err(ReflectError::OperationFailed {
1197 shape: frame.shape,
1198 operation: "map type does not implement Default",
1199 });
1200 };
1201
1202 unsafe {
1203 default_in_place(frame.data);
1204 frame.mark_fully_initialized();
1205 }
1206
1207 let shape = frame.shape;
1208 let index = frame.field_index_in_parent;
1209
1210 self.mark_field_as_initialized(shape, index)?;
1212
1213 Ok(self)
1214 }
1215
1216 pub fn begin_pushback(mut self) -> Result<Self, ReflectError> {
1221 let Some(frame) = self.frames.last_mut() else {
1222 return Err(ReflectError::OperationFailed {
1223 shape: <()>::SHAPE,
1224 operation: "tried to begin pushback but there was no frame",
1225 });
1226 };
1227
1228 let is_list = matches!(frame.shape.def, Def::List(_));
1229 let is_tuple_struct_or_variant = match (frame.shape.ty, frame.shape.def) {
1230 (_, Def::Scalar(sd)) => matches!(sd.affinity, ScalarAffinity::Empty(_)),
1231 (Type::Sequence(_), _) => true,
1232 (Type::User(UserType::Struct(sd)), _) => sd.kind == facet_core::StructKind::Tuple,
1233 (Type::User(UserType::Enum(_)), _) => {
1234 if let Some(variant) = &frame.istate.variant {
1236 variant.data.kind == facet_core::StructKind::Tuple
1237 } else {
1238 false }
1247 }
1248 _ => false,
1249 };
1250
1251 if !is_list && !is_tuple_struct_or_variant {
1252 return Err(ReflectError::WasNotA {
1253 expected: "list, array, or tuple-like struct/enum variant",
1254 actual: frame.shape,
1255 });
1256 }
1257
1258 if is_list {
1260 let vtable = frame.shape.vtable;
1261 if !frame.istate.fields.has(0) {
1263 let Some(default_in_place) = vtable.default_in_place else {
1264 return Err(ReflectError::OperationFailed {
1265 shape: frame.shape,
1266 operation: "list type does not implement Default, cannot begin pushback",
1267 });
1268 };
1269
1270 unsafe {
1271 default_in_place(frame.data);
1272 frame.istate.fields.set(0);
1274 }
1275 }
1276 }
1277 Ok(self)
1280 }
1281
1282 pub fn begin_map_insert(mut self) -> Result<Self, ReflectError> {
1284 let Some(frame) = self.frames.last_mut() else {
1285 return Err(ReflectError::OperationFailed {
1286 shape: <()>::SHAPE,
1287 operation: "tried to begin map insertion but there was no frame",
1288 });
1289 };
1290
1291 if !matches!(frame.shape.def, Def::Map(_)) {
1292 return Err(ReflectError::WasNotA {
1293 expected: "map or hash map",
1294 actual: frame.shape,
1295 });
1296 }
1297
1298 let vtable = frame.shape.vtable;
1299
1300 if !frame.istate.fields.has(0) {
1302 let Some(default_in_place) = vtable.default_in_place else {
1303 return Err(ReflectError::OperationFailed {
1304 shape: frame.shape,
1305 operation: "map type does not implement Default",
1306 });
1307 };
1308
1309 unsafe {
1310 default_in_place(frame.data);
1311 frame.istate.fields.set(0);
1312 }
1313 }
1314
1315 Ok(self)
1316 }
1317
1318 pub fn push(mut self) -> Result<Self, ReflectError> {
1323 let frame_len = self.frames.len();
1325 let frame = self
1326 .frames
1327 .last_mut()
1328 .ok_or(ReflectError::OperationFailed {
1329 shape: <()>::SHAPE,
1330 operation: "tried to push but there was no frame",
1331 })?;
1332 let seq_shape = frame.shape;
1333
1334 let (element_shape, context_str): (&'static Shape, &'static str) =
1336 match (seq_shape.ty, seq_shape.def) {
1337 (_, Def::List(_)) => {
1338 if !frame.istate.fields.has(0) {
1340 return self.begin_pushback()?.push();
1343 }
1344 let shape = self.element_shape()?;
1347 (shape, "list")
1348 }
1349 (Type::Sequence(SequenceType::Tuple(tt)), _) => {
1350 let field_index = {
1352 let next_idx = frame.istate.list_index.unwrap_or(0);
1354 frame.istate.list_index = Some(next_idx + 1);
1355 next_idx
1356 };
1357 if field_index >= tt.fields.len() {
1359 return Err(ReflectError::FieldError {
1360 shape: seq_shape,
1361 field_error: FieldError::NoSuchField,
1362 });
1363 }
1364 (tt.fields[field_index].shape(), "tuple")
1366 }
1367 (Type::User(UserType::Struct(sd)), _)
1368 if sd.kind == facet_core::StructKind::Tuple =>
1369 {
1370 let field_index = {
1372 let next_idx = frame.istate.list_index.unwrap_or(0);
1374 frame.istate.list_index = Some(next_idx + 1);
1375 next_idx
1376 };
1377 if field_index >= sd.fields.len() {
1379 return Err(ReflectError::FieldError {
1380 shape: seq_shape,
1381 field_error: FieldError::NoSuchField, });
1383 }
1384 (sd.fields[field_index].shape(), "tuple struct")
1386 }
1387
1388 (Type::User(UserType::Enum(_)), _) => {
1389 let variant =
1391 frame
1392 .istate
1393 .variant
1394 .as_ref()
1395 .ok_or(ReflectError::OperationFailed {
1396 shape: seq_shape,
1397 operation: "tried to push onto enum but no variant was selected",
1398 })?;
1399 if variant.data.kind != facet_core::StructKind::Tuple {
1401 return Err(ReflectError::WasNotA {
1402 expected: "tuple-like enum variant",
1403 actual: seq_shape, });
1405 }
1406 let field_index = {
1408 let next_idx = frame.istate.list_index.unwrap_or(0);
1410 frame.istate.list_index = Some(next_idx + 1);
1411 next_idx
1412 };
1413 if field_index >= variant.data.fields.len() {
1415 return Err(ReflectError::FieldError {
1416 shape: seq_shape, field_error: FieldError::NoSuchField,
1418 });
1419 }
1420 (
1422 variant.data.fields[field_index].shape(),
1423 "tuple enum variant",
1424 )
1425 }
1426 (_, Def::Scalar(sd)) if matches!(sd.affinity, ScalarAffinity::Empty(_)) => {
1427 return Err(ReflectError::OperationFailed {
1429 shape: seq_shape,
1430 operation: "cannot push elements to unit type ()",
1431 });
1432 }
1433 _ => {
1434 return Err(ReflectError::WasNotA {
1436 expected: "list, array, tuple, tuple struct, or tuple enum variant",
1437 actual: seq_shape,
1438 });
1439 }
1440 };
1441
1442 let element_data = element_shape
1444 .allocate()
1445 .map_err(|_| ReflectError::Unsized {
1446 shape: element_shape,
1447 })?;
1448
1449 let element_frame = Frame {
1451 data: element_data,
1452 shape: element_shape,
1453 field_index_in_parent: None, istate: IState::new(
1455 frame_len, FrameMode::ListElement, FrameFlags::ALLOCATED,
1458 ),
1459 };
1460
1461 trace!(
1462 "[{}] Pushing element of type {} to {} {}",
1463 frame_len,
1464 element_shape.green(),
1465 context_str, seq_shape.blue(),
1467 );
1468 let _ = context_str;
1469
1470 self.frames.push(element_frame);
1471 Ok(self)
1472 }
1473
1474 pub fn push_some(mut self) -> Result<Self, ReflectError> {
1476 let frame = self.frames.last().unwrap();
1478 let option_shape = frame.shape;
1479
1480 let Def::Option(option_def) = option_shape.def else {
1482 return Err(ReflectError::WasNotA {
1483 expected: "option",
1484 actual: option_shape,
1485 });
1486 };
1487
1488 let inner_shape = option_def.t();
1490
1491 let inner_data = inner_shape
1493 .allocate()
1494 .map_err(|_| ReflectError::Unsized { shape: inner_shape })?;
1495
1496 let inner_frame = Frame {
1498 data: inner_data,
1499 shape: inner_shape,
1500 field_index_in_parent: None,
1502 istate: IState::new(
1503 self.frames.len(),
1504 FrameMode::OptionSome,
1505 FrameFlags::ALLOCATED,
1507 ),
1508 };
1509
1510 trace!(
1511 "[{}] Pushing option frame for {}",
1512 self.frames.len(),
1513 option_shape.blue(),
1514 );
1515
1516 self.frames.push(inner_frame);
1517 Ok(self)
1518 }
1519
1520 pub fn pop_some_push_none(mut self) -> Result<Self, ReflectError> {
1530 let Some(frame) = self.frames.last_mut() else {
1532 return Err(ReflectError::OperationFailed {
1533 shape: <()>::SHAPE,
1534 operation: "tried to pop_some_push_none but there was no frame",
1535 });
1536 };
1537
1538 if frame.istate.mode != FrameMode::OptionSome {
1540 return Err(ReflectError::OperationFailed {
1541 shape: frame.shape,
1542 operation: "pop_some_push_none called, but frame was not in Option mode",
1543 });
1544 }
1545
1546 if frame.is_fully_initialized() {
1548 return Err(ReflectError::OperationFailed {
1549 shape: frame.shape,
1550 operation: "option frame already initialized, cannot pop_some_push_none",
1551 });
1552 }
1553
1554 frame.dealloc_if_needed();
1555
1556 let _frame = self.frames.pop().expect("frame already checked");
1558
1559 let parent_frame = self
1561 .frames
1562 .last_mut()
1563 .ok_or(ReflectError::OperationFailed {
1564 shape: <()>::SHAPE,
1565 operation: "tried to pop_some_push_none but there was no parent frame",
1566 })?;
1567
1568 unsafe {
1570 if let Some(default_fn) = parent_frame.shape.vtable.default_in_place {
1571 default_fn(parent_frame.data);
1572 } else {
1573 return Err(ReflectError::OperationFailed {
1574 shape: parent_frame.shape,
1575 operation: "option type does not implement Default",
1576 });
1577 }
1578 parent_frame.mark_fully_initialized();
1579 }
1580
1581 let Def::Option(od) = parent_frame.shape.def else {
1582 return Err(ReflectError::OperationFailed {
1583 shape: parent_frame.shape,
1584 operation: "pop_some_push_none and the parent isn't of type Option???",
1585 });
1586 };
1587
1588 let data = parent_frame.data;
1590
1591 let mut frame = Frame {
1592 data,
1593 shape: od.t(),
1594 field_index_in_parent: Some(0),
1595 istate: IState::new(self.frames.len(), FrameMode::OptionNone, FrameFlags::EMPTY),
1596 };
1597 unsafe {
1598 frame.mark_fully_initialized();
1599 }
1600
1601 self.frames.push(frame);
1602
1603 Ok(self)
1604 }
1605
1606 pub fn push_map_key(mut self) -> Result<Self, ReflectError> {
1611 let frame = self.frames.last().unwrap();
1613 let map_shape = frame.shape;
1614
1615 if !matches!(map_shape.def, Def::Map(_)) {
1616 return Err(ReflectError::WasNotA {
1617 expected: "map or hash map",
1618 actual: map_shape,
1619 });
1620 }
1621
1622 if !frame.istate.fields.has(0) {
1624 self = self.begin_map_insert()?;
1625 }
1626
1627 let key_shape = self.key_shape()?;
1629
1630 let key_data = key_shape
1632 .allocate()
1633 .map_err(|_| ReflectError::Unsized { shape: key_shape })?;
1634
1635 let key_frame = Frame {
1637 data: key_data,
1638 shape: key_shape,
1639 field_index_in_parent: None,
1640 istate: IState::new(self.frames.len(), FrameMode::MapKey, FrameFlags::ALLOCATED),
1641 };
1642
1643 trace!(
1644 "[{}] Pushing key of type {} for map {}",
1645 self.frames.len(),
1646 key_shape.green(),
1647 map_shape.blue(),
1648 );
1649
1650 self.frames.push(key_frame);
1651 Ok(self)
1652 }
1653
1654 pub fn push_map_value(mut self) -> Result<Self, ReflectError> {
1659 trace!("Wants to push map value. Frames = ");
1660 #[cfg(feature = "log")]
1661 for (i, f) in self.frames.iter().enumerate() {
1662 trace!("Frame {}: {:?}", i, f);
1663 }
1664
1665 if self.frames.len() < 2 {
1667 return Err(ReflectError::OperationFailed {
1668 shape: <()>::SHAPE,
1669 operation: "tried to push map value but there was no key frame",
1670 });
1671 }
1672
1673 let key_frame_index = self.frames.len() - 1;
1675 let key_frame = &self.frames[key_frame_index];
1676
1677 match key_frame.istate.mode {
1679 FrameMode::MapKey => {} _ => {
1681 return Err(ReflectError::OperationFailed {
1682 shape: key_frame.shape,
1683 operation: "current frame is not a map key",
1684 });
1685 }
1686 }
1687
1688 if !key_frame.is_fully_initialized() {
1690 return Err(ReflectError::OperationFailed {
1691 shape: key_frame.shape,
1692 operation: "map key is not fully initialized",
1693 });
1694 }
1695
1696 let map_frame_index = self.frames.len() - 2;
1698 let map_frame = &self.frames[map_frame_index];
1699 let map_shape = map_frame.shape;
1700
1701 let Def::Map(map_def) = map_shape.def else {
1702 return Err(ReflectError::WasNotA {
1703 expected: "map",
1704 actual: map_frame.shape,
1705 });
1706 };
1707
1708 let value_shape = map_def.v();
1709
1710 let value_data = value_shape
1712 .allocate()
1713 .map_err(|_| ReflectError::Unsized { shape: value_shape })?;
1714
1715 let value_frame = Frame {
1717 data: value_data,
1718 shape: value_shape,
1719 field_index_in_parent: None,
1720 istate: IState::new(
1721 self.frames.len(),
1722 FrameMode::MapValue {
1723 index: key_frame_index,
1724 },
1725 FrameFlags::ALLOCATED,
1726 ),
1727 };
1728
1729 trace!(
1730 "[{}] Pushing value of type {} for map {} with key type {}",
1731 self.frames.len(),
1732 value_shape.green(),
1733 map_shape.blue(),
1734 key_frame.shape.yellow(),
1735 );
1736
1737 self.frames.push(value_frame);
1738 Ok(self)
1739 }
1740
1741 pub fn pop(mut self) -> Result<Self, ReflectError> {
1743 let frame = match self.pop_inner()? {
1744 Some(frame) => frame,
1745 None => {
1746 return Err(ReflectError::InvariantViolation {
1747 invariant: "No frame to pop — it was time to call build()",
1748 });
1749 }
1750 };
1751
1752 self.track(frame);
1753 Ok(self)
1754 }
1755
1756 fn pop_inner(&mut self) -> Result<Option<Frame>, ReflectError> {
1757 let mut frame = match self.frames.pop() {
1758 Some(f) => f,
1759 None => return Ok(None),
1760 };
1761 #[cfg(feature = "log")]
1762 let frame_shape = frame.shape;
1763
1764 let init = frame.is_fully_initialized();
1765 trace!(
1766 "[{}] {} popped, {} initialized",
1767 self.frames.len(),
1768 frame_shape.blue(),
1769 if init {
1770 "✅ fully".style(owo_colors::Style::new().green())
1771 } else {
1772 "🚧 partially".style(owo_colors::Style::new().red())
1773 }
1774 );
1775 if init {
1776 if let Some(parent) = self.frames.last_mut() {
1777 if let Some(index) = frame.field_index_in_parent {
1778 parent.istate.fields.set(index);
1779 }
1780 }
1781 }
1782
1783 match frame.istate.mode {
1785 FrameMode::ListElement => {
1787 if frame.is_fully_initialized() {
1788 #[cfg(feature = "log")]
1790 let frame_len = self.frames.len();
1791
1792 let parent_frame = self.frames.last_mut().unwrap();
1794 let parent_shape = parent_frame.shape;
1795
1796 match parent_shape.def {
1797 Def::List(list_def) => {
1799 let list_vtable = list_def.vtable;
1800 trace!(
1801 "[{}] Pushing element to list {}",
1802 frame_len,
1803 parent_shape.blue()
1804 );
1805 unsafe {
1806 (list_vtable.push)(
1807 PtrMut::new(parent_frame.data.as_mut_byte_ptr()),
1808 PtrMut::new(frame.data.as_mut_byte_ptr()),
1809 );
1810 self.mark_moved_out_of(&mut frame);
1811 }
1812 }
1813 Def::Scalar(s) if matches!(s.affinity, ScalarAffinity::Empty(_)) => {
1814 trace!(
1815 "[{}] Handling scalar empty unit type {}",
1816 frame_len,
1817 parent_shape.blue()
1818 );
1819 unsafe {
1821 parent_frame.mark_fully_initialized();
1822 self.mark_moved_out_of(&mut frame);
1823 }
1824 }
1825 _ => match parent_shape.ty {
1826 Type::User(UserType::Struct(sd))
1828 if sd.kind == facet_core::StructKind::Tuple
1829 && sd.fields.is_empty() =>
1830 {
1831 trace!(
1832 "[{}] Handling empty tuple struct unit type {}",
1833 frame_len,
1834 parent_shape.blue()
1835 );
1836 unsafe {
1838 parent_frame.mark_fully_initialized();
1839 }
1840 unsafe { self.mark_moved_out_of(&mut frame) };
1842 }
1843
1844 Type::Sequence(SequenceType::Tuple(tt)) => {
1846 let previous_index = parent_frame.istate.list_index.unwrap_or(1);
1848 let field_index = previous_index - 1; if field_index >= tt.fields.len() {
1851 panic!(
1852 "Field index {} out of bounds for tuple {} with {} fields",
1853 field_index,
1854 parent_shape,
1855 tt.fields.len()
1856 );
1857 }
1858
1859 let field = &tt.fields[field_index];
1860 trace!(
1861 "[{}] Setting tuple field {} ({}) of {}",
1862 frame_len,
1863 field_index.to_string().yellow(),
1864 field.name.bright_blue(),
1865 parent_shape.blue()
1866 );
1867
1868 unsafe {
1869 let field_ptr = parent_frame.data.field_uninit_at(field.offset);
1871 field_ptr
1872 .copy_from(
1873 PtrConst::new(frame.data.as_byte_ptr()),
1874 field.shape(),
1875 )
1876 .map_err(|_| ReflectError::Unsized {
1877 shape: field.shape(),
1878 })?; parent_frame.istate.fields.set(field_index);
1882
1883 self.mark_moved_out_of(&mut frame);
1885 }
1886 }
1887
1888 Type::User(UserType::Struct(sd))
1890 if sd.kind == facet_core::StructKind::Tuple =>
1891 {
1892 let previous_index = parent_frame.istate.list_index.unwrap_or(1);
1894 let field_index = previous_index - 1; if field_index >= sd.fields.len() {
1897 panic!(
1898 "Field index {} out of bounds for tuple struct {} with {} fields",
1899 field_index,
1900 parent_shape,
1901 sd.fields.len()
1902 );
1903 }
1904
1905 let field = &sd.fields[field_index];
1906 trace!(
1907 "[{}] Setting tuple struct field {} ({}) of {}",
1908 frame_len,
1909 field_index.to_string().yellow(),
1910 field.name.bright_blue(),
1911 parent_shape.blue()
1912 );
1913
1914 unsafe {
1915 let field_ptr = parent_frame.data.field_uninit_at(field.offset);
1917 field_ptr
1918 .copy_from(
1919 PtrConst::new(frame.data.as_byte_ptr()),
1920 field.shape(),
1921 )
1922 .map_err(|_| ReflectError::Unsized {
1923 shape: field.shape(),
1924 })?; parent_frame.istate.fields.set(field_index);
1928
1929 self.mark_moved_out_of(&mut frame);
1931 }
1932 }
1933
1934 Type::User(UserType::Enum(_)) => {
1936 let variant =
1938 parent_frame.istate.variant.as_ref().unwrap_or_else(|| {
1939 panic!(
1940 "Popping element for enum {} but no variant was selected",
1941 parent_shape
1942 )
1943 });
1944
1945 if variant.data.kind != facet_core::StructKind::Tuple {
1946 panic!(
1947 "Popping element for enum {}, but selected variant '{}' is not a tuple variant",
1948 parent_shape, variant.name
1949 );
1950 }
1951
1952 let previous_index = parent_frame.istate.list_index.unwrap_or(1);
1954 let field_index = previous_index - 1; if field_index >= variant.data.fields.len() {
1957 panic!(
1958 "Field index {} out of bounds for tuple enum variant '{}' of {} with {} fields",
1959 field_index,
1960 variant.name,
1961 parent_shape,
1962 variant.data.fields.len()
1963 );
1964 }
1965
1966 let field = &variant.data.fields[field_index];
1967 trace!(
1968 "[{}] Setting tuple enum variant field {} ({}) of variant '{}' in {}",
1969 frame_len,
1970 field_index.to_string().yellow(),
1971 field.name.bright_blue(),
1972 variant.name.yellow(),
1973 parent_shape.blue()
1974 );
1975
1976 unsafe {
1977 let field_ptr = parent_frame.data.field_uninit_at(field.offset);
1979 field_ptr
1980 .copy_from(
1981 PtrConst::new(frame.data.as_byte_ptr()),
1982 field.shape(),
1983 )
1984 .map_err(|_| ReflectError::Unsized {
1985 shape: field.shape(),
1986 })?; parent_frame.istate.fields.set(field_index);
1990
1991 self.mark_moved_out_of(&mut frame);
1993 }
1994 }
1995
1996 _ => {
1998 panic!(
1999 "FrameMode::ListElement pop expected parent to be List, Tuple, Tuple Struct, or Tuple Enum Variant, but got {}",
2000 parent_shape
2001 );
2002 }
2003 },
2004 }
2005 } else {
2006 trace!(
2008 "Popping uninitialized ListElement frame ({}), potential leak if allocated resources are not managed",
2009 frame.shape.yellow()
2010 );
2011 }
2012 }
2013
2014 FrameMode::MapValue {
2016 index: key_frame_index,
2017 } if frame.is_fully_initialized() => {
2018 let mut key_frame = self.frames.remove(key_frame_index);
2022
2023 if !key_frame.istate.fields.is_any_set() {
2025 panic!("key is not initialized when popping value frame");
2026 }
2027
2028 #[cfg(feature = "log")]
2030 let frame_len = self.frames.len();
2031 let parent_frame = self.frames.last_mut().unwrap();
2032 let parent_shape = parent_frame.shape;
2033
2034 match parent_shape.def {
2036 Def::Map(_) => {
2037 if let Def::Map(map_def) = parent_shape.def {
2039 trace!(
2040 "[{}] Inserting key-value pair into map {}",
2041 frame_len,
2042 parent_shape.blue()
2043 );
2044 unsafe {
2045 (map_def.vtable.insert_fn)(
2047 parent_frame.data.assume_init(),
2048 key_frame.data.assume_init(),
2049 PtrMut::new(frame.data.as_mut_byte_ptr()),
2050 );
2051 self.mark_moved_out_of(&mut key_frame);
2052 self.mark_moved_out_of(&mut frame);
2053 }
2054 } else {
2055 panic!("parent frame is not a map type");
2056 }
2057 }
2058 _ => {
2059 panic!("Expected map or hash map, got {}", frame.shape);
2060 }
2061 }
2062 }
2063
2064 FrameMode::OptionSome => {
2066 if frame.is_fully_initialized() {
2067 trace!("Popping OptionSome (fully init'd)");
2068
2069 #[cfg(feature = "log")]
2071 let frames_len = self.frames.len();
2072 let parent_frame = self.frames.last_mut().unwrap();
2073 let parent_shape = parent_frame.shape;
2074
2075 match parent_shape.def {
2077 Def::Option(option_def) => {
2078 trace!(
2079 "[{}] Setting Some value in option {}",
2080 frames_len,
2081 parent_shape.blue()
2082 );
2083 unsafe {
2084 (option_def.vtable.init_some_fn)(
2086 parent_frame.data,
2087 PtrConst::new(frame.data.as_byte_ptr()),
2088 );
2089 trace!(
2090 "Marking parent frame as fully initialized — its shape is {}",
2091 parent_frame.shape
2092 );
2093 let variant = match parent_frame.shape.ty {
2094 Type::User(UserType::Enum(EnumType { variants, .. })) => {
2095 variants[1]
2096 }
2097 _ => Variant::builder()
2098 .name("Some")
2099 .discriminant(1)
2100 .data(
2101 StructType::builder()
2102 .tuple()
2103 .repr(Repr::default())
2104 .build(),
2105 )
2106 .build(),
2107 };
2108 parent_frame.istate.variant = Some(variant); parent_frame.mark_fully_initialized();
2110 trace!(
2111 "After marking: shape={} at {:p}, flags={:?}, mode={:?}, fully_initialized={}",
2112 parent_frame.shape.blue(),
2113 parent_frame.data.as_byte_ptr(),
2114 parent_frame.istate.flags.bright_magenta(),
2115 parent_frame.istate.mode.yellow(),
2116 if parent_frame.is_fully_initialized() {
2117 "✅"
2118 } else {
2119 "❌"
2120 }
2121 );
2122
2123 self.mark_moved_out_of(&mut frame);
2124 }
2125 }
2126 _ => {
2127 panic!(
2128 "Expected parent frame to be an option type, got {}",
2129 frame.shape
2130 );
2131 }
2132 }
2133 } else {
2134 trace!("Popping OptionSome (not fully init'd)");
2135 }
2136 }
2137
2138 FrameMode::MapKey => {}
2141
2142 FrameMode::Field => {}
2144
2145 _ => {}
2147 }
2148
2149 Ok(Some(frame))
2150 }
2151
2152 pub fn evict_tree(&mut self, frame: Frame) -> Frame {
2156 match frame.shape.ty {
2157 Type::User(UserType::Struct(sd)) => {
2158 for f in sd.fields {
2159 let id = ValueId {
2160 shape: f.shape(),
2161 ptr: unsafe { frame.data.field_uninit_at(f.offset) }.as_byte_ptr(),
2162 };
2163 if let Some(istate) = self.istates.remove(&id) {
2164 let frame = Frame::recompose(id, istate);
2165 self.evict_tree(frame);
2166 } else {
2167 trace!("No istate found for field {}", f.name);
2168 }
2169 }
2170 }
2171 Type::User(UserType::Enum(_ed)) => {
2172 if let Some(variant) = &frame.istate.variant {
2174 trace!(
2175 "Evicting enum {} variant '{}' fields",
2176 frame.shape.blue(),
2177 variant.name.yellow()
2178 );
2179 for field in variant.data.fields {
2181 let field_ptr = unsafe { frame.data.field_uninit_at(field.offset) };
2183 let field_shape = field.shape();
2184 let field_id = ValueId::new(field_shape, field_ptr.as_byte_ptr());
2185
2186 if let Some(field_istate) = self.istates.remove(&field_id) {
2188 trace!(
2189 "Evicting field '{}' (shape {}) of enum variant '{}'",
2190 field.name.bright_blue(),
2191 field_shape.green(),
2192 variant.name.yellow()
2193 );
2194 let field_frame = Frame::recompose(field_id, field_istate);
2196 self.evict_tree(field_frame);
2198 } else {
2199 trace!(
2200 "Field '{}' (shape {}) of enum variant '{}' not found in istates, skipping eviction",
2201 field.name.red(),
2202 field_shape.red(),
2203 variant.name.yellow()
2204 );
2205 }
2206 }
2207 } else {
2208 trace!(
2210 "Enum {} has no variant selected, no fields to evict.",
2211 frame.shape.blue()
2212 );
2213 }
2214 }
2215 _ => {}
2216 }
2217 frame
2218 }
2219
2220 #[allow(rustdoc::broken_intra_doc_links)]
2221 pub fn path(&self) -> String {
2224 let mut path = String::from("$");
2225
2226 for (i, frame) in self.frames.iter().enumerate() {
2227 if i == 0 {
2229 continue;
2230 }
2231
2232 match frame.istate.mode {
2233 FrameMode::ListElement => {
2234 if let Some(index) = frame.istate.list_index {
2236 path.push_str(&format!("[{}]", index));
2237 } else {
2238 path.push_str("[?]");
2239 }
2240 }
2241 FrameMode::MapKey => {
2242 path.push_str(".key");
2243 }
2244 FrameMode::MapValue { index: _ } => {
2245 path.push_str(".value");
2246 }
2247 FrameMode::OptionSome => {
2248 path.push_str(".some");
2249 }
2250 FrameMode::OptionNone => {
2251 path.push_str(".none");
2252 }
2253 FrameMode::Root => {
2254 }
2256 FrameMode::Field => {
2257 if let Some(index) = frame.field_index_in_parent {
2259 if let Some(parent) = self.frames.get(i - 1) {
2261 if let Type::User(UserType::Struct(sd)) = parent.shape.ty {
2262 if index < sd.fields.len() {
2263 let field_name = sd.fields[index].name;
2264 path.push('.');
2265 path.push_str(field_name);
2266 }
2267 } else if let Type::User(UserType::Enum(_)) = parent.shape.ty {
2268 if let Some(variant) = &parent.istate.variant {
2269 if index < variant.data.fields.len() {
2270 let field_name = variant.data.fields[index].name;
2271 path.push('.');
2272 path.push_str(field_name);
2273 }
2274 }
2275 }
2276 }
2277 }
2278 }
2279 }
2280 }
2281
2282 path
2283 }
2284
2285 pub fn is_field_set(&self, index: usize) -> Result<bool, ReflectError> {
2287 let frame = self.frames.last().ok_or(ReflectError::OperationFailed {
2288 shape: <()>::SHAPE,
2289 operation: "tried to check if field is set, but there was no frame",
2290 })?;
2291
2292 match frame.shape.ty {
2293 Type::User(UserType::Struct(ref sd)) => {
2294 if index >= sd.fields.len() {
2295 return Err(ReflectError::FieldError {
2296 shape: frame.shape,
2297 field_error: FieldError::NoSuchField,
2298 });
2299 }
2300 Ok(frame.istate.fields.has(index))
2301 }
2302 Type::User(UserType::Enum(_)) => {
2303 let variant = frame.istate.variant.as_ref().ok_or(
2304 ReflectError::OperationFailed {
2305 shape: frame.shape,
2306 operation: "tried to check if field is set, but no variant was selected",
2307 },
2308 )?;
2309 if index >= variant.data.fields.len() {
2310 return Err(ReflectError::FieldError {
2311 shape: frame.shape,
2312 field_error: FieldError::NoSuchField,
2313 });
2314 }
2315 Ok(frame.istate.fields.has(index))
2316 }
2317 _ => Err(ReflectError::WasNotA {
2318 expected: "struct or enum",
2319 actual: frame.shape,
2320 }),
2321 }
2322 }
2323}
2324
2325impl Drop for Wip<'_> {
2326 fn drop(&mut self) {
2327 trace!("🧹🧹🧹 WIP is dropping");
2328
2329 while let Some(frame) = self.frames.pop() {
2330 self.track(frame);
2331 }
2332
2333 let Some((root_id, _)) = self.istates.iter().find(|(_k, istate)| istate.depth == 0) else {
2334 trace!("No root found, we probably built already");
2335 return;
2336 };
2337
2338 let root_id = *root_id;
2339 let root_istate = self.istates.remove(&root_id).unwrap();
2340 let root = Frame::recompose(root_id, root_istate);
2341 let mut to_clean = vec![root];
2342
2343 let mut _root_guard: Option<Guard> = None;
2344
2345 while let Some(mut frame) = to_clean.pop() {
2346 trace!(
2347 "Cleaning frame: shape={} at {:p}, flags={:?}, mode={:?}, fully_initialized={}",
2348 frame.shape.blue(),
2349 frame.data.as_byte_ptr(),
2350 frame.istate.flags.bright_magenta(),
2351 frame.istate.mode.yellow(),
2352 if frame.is_fully_initialized() {
2353 "✅"
2354 } else {
2355 "❌"
2356 }
2357 );
2358
2359 if frame.istate.flags.contains(FrameFlags::MOVED) {
2360 trace!(
2361 "{}",
2362 "Frame was moved out of, nothing to dealloc/drop_in_place".yellow()
2363 );
2364 continue;
2365 }
2366
2367 match frame.shape.ty {
2368 Type::User(UserType::Struct(sd)) => {
2369 if frame.is_fully_initialized() {
2370 trace!(
2371 "Dropping fully initialized struct: {} at {:p}",
2372 frame.shape.green(),
2373 frame.data.as_byte_ptr()
2374 );
2375 let frame = self.evict_tree(frame);
2376 unsafe { frame.drop_and_dealloc_if_needed() };
2377 } else {
2378 let num_fields = sd.fields.len();
2379 trace!(
2380 "De-initializing struct {} at {:p} field-by-field ({} fields)",
2381 frame.shape.yellow(),
2382 frame.data.as_byte_ptr(),
2383 num_fields.to_string().bright_cyan()
2384 );
2385 for i in 0..num_fields {
2386 if frame.istate.fields.has(i) {
2387 let field = sd.fields[i];
2388 let field_shape = field.shape();
2389 let field_ptr = unsafe { frame.data.field_init_at(field.offset) };
2390 let field_id = ValueId::new(field_shape, field_ptr.as_byte_ptr());
2391 trace!(
2392 "Recursively cleaning field #{} '{}' of {}: field_shape={}, field_ptr={:p}",
2393 i.to_string().bright_cyan(),
2394 field.name.bright_blue(),
2395 frame.shape.blue(),
2396 field_shape.green(),
2397 field_ptr.as_byte_ptr()
2398 );
2399 let istate = self.istates.remove(&field_id).unwrap();
2400 let field_frame = Frame::recompose(field_id, istate);
2401 to_clean.push(field_frame);
2402 } else {
2403 trace!(
2404 "Field #{} '{}' of {} was NOT initialized, skipping",
2405 i.to_string().bright_cyan(),
2406 sd.fields[i].name.bright_red(),
2407 frame.shape.red()
2408 );
2409 }
2410 }
2411
2412 if frame.istate.mode == FrameMode::Root {
2414 if let Ok(layout) = frame.shape.layout.sized_layout() {
2415 _root_guard = Some(Guard {
2416 ptr: frame.data.as_mut_byte_ptr(),
2417 layout,
2418 });
2419 }
2420 }
2421 }
2422 }
2423 Type::User(UserType::Enum(_ed)) => {
2424 trace!(
2425 "Handling enum deallocation for {} at {:p}",
2426 frame.shape.yellow(),
2427 frame.data.as_byte_ptr()
2428 );
2429
2430 if let Some(variant) = &frame.istate.variant {
2432 trace!(
2433 "Dropping enum variant {} of {} with {} fields",
2434 variant.name.bright_yellow(),
2435 frame.shape.yellow(),
2436 variant.data.fields.len()
2437 );
2438
2439 for (i, field) in variant.data.fields.iter().enumerate() {
2441 if frame.istate.fields.has(i) {
2442 let field_shape = field.shape();
2443 let field_ptr = unsafe { frame.data.field_init_at(field.offset) };
2444 let field_id = ValueId::new(field_shape, field_ptr.as_byte_ptr());
2445 trace!(
2446 "Recursively cleaning field #{} '{}' of variant {}: field_shape={}, field_ptr={:p}",
2447 i.to_string().bright_cyan(),
2448 field.name.bright_blue(),
2449 variant.name.yellow(),
2450 field_shape.green(),
2451 field_ptr.as_byte_ptr()
2452 );
2453 if let Some(istate) = self.istates.remove(&field_id) {
2454 let field_frame = Frame::recompose(field_id, istate);
2455 to_clean.push(field_frame);
2456 } else {
2457 trace!(
2458 "Field not found in istates: #{} '{}' of variant {}",
2459 i.to_string().bright_cyan(),
2460 field.name.bright_blue(),
2461 variant.name.yellow()
2462 );
2463 unsafe {
2465 if let Some(drop_in_place) =
2466 field_shape.vtable.drop_in_place
2467 {
2468 drop_in_place(field_ptr);
2469 }
2470 }
2471 }
2472 } else {
2473 trace!(
2474 "Field #{} '{}' of variant {} was NOT initialized, skipping",
2475 i.to_string().bright_cyan(),
2476 field.name.bright_red(),
2477 variant.name.yellow()
2478 );
2479 }
2480 }
2481 } else {
2482 trace!(
2483 "Enum {} has no variant selected, nothing to drop for fields",
2484 frame.shape.yellow()
2485 );
2486 }
2487
2488 if frame.istate.mode == FrameMode::Root {
2490 if let Ok(layout) = frame.shape.layout.sized_layout() {
2491 _root_guard = Some(Guard {
2492 ptr: frame.data.as_mut_byte_ptr(),
2493 layout,
2494 });
2495 }
2496 }
2497 }
2498 _ => {
2499 trace!(
2500 "Can drop all at once for shape {} (def variant: {:?}, frame mode {:?}) at {:p}",
2501 frame.shape.cyan(),
2502 frame.shape.def,
2503 frame.istate.mode.yellow(),
2504 frame.data.as_byte_ptr(),
2505 );
2506
2507 if frame.is_fully_initialized() {
2508 unsafe { frame.drop_and_dealloc_if_needed() }
2509 } else {
2510 frame.dealloc_if_needed();
2511 }
2512 }
2513 }
2514 }
2515
2516 let mut all_ids = self.istates.keys().copied().collect::<Vec<_>>();
2518 for frame_id in all_ids.drain(..) {
2519 let frame_istate = self.istates.remove(&frame_id).unwrap();
2520
2521 trace!(
2522 "Checking leftover istate: id.shape={} id.ptr={:p} mode={:?}",
2523 frame_id.shape.cyan(),
2524 frame_id.ptr,
2525 frame_istate.mode.yellow()
2526 );
2527 let mut frame = Frame::recompose(frame_id, frame_istate);
2528
2529 if frame.is_fully_initialized() {
2530 trace!("It's fully initialized, we can drop it");
2531 unsafe { frame.drop_and_dealloc_if_needed() };
2532 } else if frame.istate.flags.contains(FrameFlags::ALLOCATED) {
2533 trace!("Not initialized but allocated, let's free it");
2534 frame.dealloc_if_needed();
2535 }
2536 }
2537 }
2538}