facet_reflect/wip/
mod.rs

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
70/// Represents a frame in the initialization stack
71pub struct Frame {
72    /// The value we're initializing
73    data: PtrUninit<'static>,
74
75    /// The shape of the value
76    shape: &'static Shape,
77
78    /// If set, when we're initialized, we must mark the
79    /// parent's indexth field as initialized.
80    field_index_in_parent: Option<usize>,
81
82    /// Tracking which of our fields are initialized
83    /// TODO: I'm not sure we should track "ourselves" as initialized — we always have the
84    /// parent to look out for, right now we're tracking children in two states, which isn't ideal
85    istate: IState,
86}
87
88impl Frame {
89    /// Given a ValueId and an IState, recompose a Frame suitable for tracking
90    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    /// Deallocates the memory used by this frame if it was heap-allocated.
100    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
154/// Returns true if the frame is fully initialized
155fn 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    /// Returns the value ID for a frame
168    fn id(&self) -> ValueId {
169        ValueId::new(self.shape, self.data.as_byte_ptr())
170    }
171
172    /// Returns true if the frame is fully initialized
173    fn is_fully_initialized(&self) -> bool {
174        is_fully_initialized(self.shape, &self.istate)
175    }
176
177    // Safety: only call if is fully initialized
178    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    /// Marks the frame as fully initialized
203    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                    // now let's find which variant was set with a Peek
235                    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                        // for unit variants, we mark "fields zero" as initialized
243                        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
260/// Initialization state
261struct IState {
262    /// Variant chosen — for everything except enums, this stays None
263    variant: Option<Variant>,
264
265    /// Fields that were initialized. For scalars, we only track 0
266    fields: ISet,
267
268    /// The depth of the frame in the stack
269    depth: usize,
270
271    /// The special mode of this frame (if any)
272    mode: FrameMode,
273
274    /// If true, must be freed when dropped
275    flags: FrameFlags,
276
277    /// The current index for list elements
278    list_index: Option<usize>,
279
280    /// The current key for map elements
281    #[allow(dead_code)]
282    map_key: Option<String>,
283}
284
285bitflags! {
286    /// Flags that can be applied to frames
287    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
288    pub struct FrameFlags: u64 {
289        /// An empty set of flags
290        const EMPTY = 0;
291
292        /// We allocated this frame on the heap, we need to deallocated it when popping
293        const ALLOCATED = 1 << 0;
294
295        /// This value was moved out of — it's not part of the value we're building and
296        /// we shouldn't error out when we build and we notice it's not initialized.
297        /// In fact, it should not be tracked at all.
298        const MOVED = 1 << 1;
299    }
300
301    // Note: there is no 'initialized' flag because initialization can be partial — it's tracked via `ISet`
302}
303
304impl IState {
305    /// Creates a new `IState` with the given depth.
306    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    /// Sets the list index and returns self for method chaining
319    #[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    /// Sets the map key and returns self for method chaining
326    #[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/// Represents the special mode a frame can be in
334#[derive(Debug, Clone, Copy, PartialEq, Eq)]
335pub enum FrameMode {
336    /// Root frame
337    Root,
338    /// Struct field
339    Field,
340    /// Frame represents a list element
341    ListElement,
342    /// Frame represents a map key
343    MapKey,
344    /// Frame represents a map value with the given key frame index
345    MapValue {
346        /// The index of the key frame associated with this map value
347        index: usize,
348    },
349    /// Frame represents the Some variant of an option (that we allocated)
350    OptionSome,
351    /// Frame represents the None variant of an option (no allocation needed)
352    /// Any `put` should fail
353    OptionNone,
354}
355
356/// A work-in-progress heap-allocated value
357pub struct Wip<'facet_lifetime> {
358    /// stack of frames to keep track of deeply nested initialization
359    frames: alloc::vec::Vec<Frame>,
360
361    /// keeps track of initialization of out-of-tree frames
362    istates: FlatMap<ValueId, IState>,
363
364    invariant: PhantomData<fn(&'facet_lifetime ()) -> &'facet_lifetime ()>,
365}
366
367impl<'facet_lifetime> Wip<'facet_lifetime> {
368    /// Puts the value from a Peek into the current frame.
369    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    /// Returns the number of frames on the stack
377    pub fn frames_count(&self) -> usize {
378        self.frames.len()
379    }
380
381    /// Allocates a new value of the given shape
382    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    /// Allocates a new value of type `S`
399    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        // fields might be partially initialized (in-place) and then
405        // we might come back to them, so because they're popped off
406        // the stack, we still need to track them _somewhere_
407        //
408        // the root also relies on being tracked in the drop impl
409        if frame.istate.flags.contains(FrameFlags::MOVED) {
410            // don't track those
411            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        // Recursively mark `istates` entries as MOVED and deallocate. Needed because
419        // descendant values might be tracked separately in `istates`.
420        unsafe fn mark_subtree_moved(wip: &mut Wip, id: ValueId) {
421            // Function requires unsafe due to pointer manipulation and potential deallocation.
422            unsafe {
423                // Process only if the value is still tracked off-stack.
424                if let Some(mut istate) = wip.istates.remove(&id) {
425                    // Ensure value is marked as MOVED.
426                    istate.flags.insert(FrameFlags::MOVED);
427
428                    // Ensure all owned fields within structs/enums are also marked.
429                    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                                // Recurse.
437                                mark_subtree_moved(wip, field_id);
438                            }
439                        }
440                        Type::User(UserType::Enum(_)) => {
441                            // Use the variant info from the processed istate.
442                            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                                    // Recurse.
450                                    mark_subtree_moved(wip, field_id);
451                                }
452                            }
453                        }
454                        // Only recurse for direct fields (struct/enum). Other owned values
455                        // (list elements, map entries, option Some payload) are handled
456                        // individually when *their* ValueId is processed, if tracked.
457                        _ => {}
458                    }
459
460                    // Prevent memory leaks for heap-allocated values that are now moved.
461                    // Only deallocate AFTER recursively processing child fields to prevent use-after-free.
462                    if istate.flags.contains(FrameFlags::ALLOCATED) {
463                        // `dealloc_if_needed` needs a `Frame`.
464                        let mut temp_frame = Frame::recompose(id, istate);
465                        temp_frame.dealloc_if_needed();
466                    }
467                }
468                // If istate wasn't found, value was already handled or not tracked off-stack.
469            }
470        }
471
472        // Function requires unsafe due to pointer manipulation, potential deallocation,
473        // and calling other unsafe functions/methods.
474        unsafe {
475            // 1. Process the primary frame being moved: mark MOVED, clear state
476            let frame_id = frame.id();
477
478            // Save variant information for recursive processing before we clear it
479            let variant_opt = frame.istate.variant;
480
481            // Mark as MOVED and clear any initialization progress.
482            frame.istate.flags.insert(FrameFlags::MOVED);
483            ISet::clear(&mut frame.istate.fields);
484
485            // 2. Recursively mark descendants (struct/enum fields) in `istates` as MOVED.
486            // This ensures consistency if fields were pushed/popped and stored in `istates`.
487            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                    // Use the saved variant information for recursion
498                    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                // Other types don't have direct fields requiring recursive marking here.
509                _ => {}
510            }
511
512            // Now clear the variant after processing is done
513            frame.istate.variant = None;
514
515            // Untrack the frame in `istates`
516            self.istates.remove(&frame_id);
517
518            // Deallocate AFTER all processing is complete to prevent use-after-free
519            if frame.istate.flags.contains(FrameFlags::ALLOCATED) {
520                frame.dealloc_if_needed();
521            }
522        }
523    }
524
525    /// Returns the shape of the current frame
526    pub fn shape(&self) -> &'static Shape {
527        self.frames.last().expect("must have frames left").shape
528    }
529
530    /// Returns the innermost shape for the current frame
531    /// If the current shape is a transparent wrapper, this returns the shape of the wrapped type
532    /// Otherwise, returns the current shape
533    pub fn innermost_shape(&self) -> &'static Shape {
534        let mut current_shape = self.shape();
535
536        // Keep unwrapping as long as we find inner shapes
537        while let Some(inner_fn) = current_shape.inner {
538            current_shape = inner_fn();
539        }
540
541        current_shape
542    }
543
544    /// Return true if the last frame is in option mode
545    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    /// Returns the mode of the current frame
553    pub fn mode(&self) -> FrameMode {
554        self.frames.last().unwrap().istate.mode
555    }
556
557    /// Asserts everything is initialized and that invariants are upheld (if any)
558    pub fn build(mut self) -> Result<HeapValue<'facet_lifetime>, ReflectError> {
559        debug!("[{}] ⚒️ It's BUILD time", self.frames.len());
560
561        // 1. Require that there is exactly one frame on the stack (the root frame)
562        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        // now the root frame is at index 0
573        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        // 4. Traverse the tree
582        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                    // Look up the istate for the frame with this ValueId.
587                    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            // Skip moved frames
606            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            // Check initialization for the current frame
615
616            // For types that manage their own contents (List, Map, Option, Scalar, etc.),
617            // we just need to check if the *container* itself is marked as initialized.
618            // The recursive check handles struct/enum *elements* within these containers if they exist.
619            if !matches!(id.shape.def, Def::Undefined) {
620                if !istate.fields.are_all_set(1) {
621                    // Check specific modes for better errors
622                    match istate.mode {
623                        FrameMode::OptionNone => {
624                            // This should technically be marked initialized, but if not, treat as uninit Option
625                            debug!("Found uninitialized value (option none) — {}", id.shape);
626                            return Err(ReflectError::UninitializedValue { shape: id.shape });
627                        }
628                        // Add more specific checks if needed, e.g., for lists/maps that started but weren't finished?
629                        _ => {
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                // No children to push onto `to_check` from the perspective of the *container* frame itself.
639                // If a List contains Structs, those struct frames would have been pushed/popped
640                // and their states tracked individually in `istates`, and checked when encountered via
641                // `to_check` if they were fields of another struct/enum.
642                // The `Drop` logic handles cleaning these contained items based on the container's drop_in_place.
643                // For `build`, we trust that if the container is marked initialized, its contents are valid
644                // according to its type's rules.
645            } else {
646                match id.shape.ty {
647                    Type::User(UserType::Struct(sd)) => {
648                        // find the field that's not initialized
649                        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                        // If initialized, push children to check stack
663                        #[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                            // Check each field, just like for structs
685                            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                            // All fields initialized, push children to check stack
697                            #[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                                // We're in an enum, so get the field ptr out of the variant's payload
702                                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                            // No variant selected is an error during build
721                            debug!("Found no variant selected for enum");
722                            return Err(ReflectError::NoVariantSelected { shape: id.shape });
723                        }
724                    }
725                    // Handle other Def variants if necessary
726                    _ => {
727                        // Default: Check if initialized using the standard method
728                        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        // If we finished the loop, all reachable and non-moved frames are initialized.
738        debug!("All reachable frames checked and initialized.");
739
740        // 5. Check invariants on the root
741        // We have already checked root is fully initialized above, so we only need to check its invariants.
742        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        // Prevent Drop from running on the successfully built value.
763        {
764            FlatMap::clear(&mut self.istates);
765            self.frames.clear();
766        }
767
768        // Build the guard from the root data.
769        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    /// Selects a field of a struct or enum variant by index and pushes it onto the frame stack.
785    ///
786    /// # Arguments
787    ///
788    /// * `index` - The index of the field to select.
789    ///
790    /// # Returns
791    ///
792    /// * `Ok(Self)` if the field was successfully selected and pushed.
793    /// * `Err(ReflectError)` if the current frame is not a struct or an enum with a selected variant,
794    ///   or if the field doesn't exist.
795    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            // we didn't have to allocate that field, it's a struct field, so it's not allocated
843            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    /// Finds the index of a field in a struct or enum variant by name.
879    ///
880    /// # Arguments
881    ///
882    /// * `name` - The name of the field to find.
883    ///
884    /// # Returns
885    ///
886    /// * `Some(usize)` if the field was found.
887    /// * `None` if the current frame is not a struct or an enum with a selected variant,
888    ///   or if the field doesn't exist.
889    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    /// Selects a field of a struct or enum variant by name and pushes it onto the frame stack.
906    ///
907    /// # Arguments
908    ///
909    /// * `name` - The name of the field to select.
910    ///
911    /// # Returns
912    ///
913    /// * `Ok(Self)` if the field was successfully selected and pushed.
914    /// * `Err(ReflectError)` if the current frame is not a struct or an enum with a selected variant,
915    ///   or if the field doesn't exist.
916    pub fn field_named(self, name: &str) -> Result<Self, ReflectError> {
917        let frame = self.frames.last().unwrap();
918        let shape = frame.shape;
919
920        // For enums, ensure a variant is selected
921        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    /// Puts a value of type `T` into the current frame.
939    ///
940    /// # Arguments
941    ///
942    /// * `t` - The value to put into the frame.
943    ///
944    /// # Returns
945    ///
946    /// * `Ok(Self)` if the value was successfully put into the frame.
947    /// * `Err(ReflectError)` if there was an error putting the value into the frame.
948    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); // avoid double drop; ownership moved into Wip
956        res
957    }
958
959    /// Puts a value of type `T` into the current frame.
960    ///
961    /// # Arguments
962    ///
963    /// * `t` - The value to put into the frame.
964    ///
965    /// # Returns
966    ///
967    /// * `Ok(Self)` if the value was successfully put into the frame.
968    /// * `Err(ReflectError)` if there was an error putting the value into the frame.
969    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); // avoid double drop; ownership moved into Wip
977        res
978    }
979
980    /// Tries to parse the current frame's value from a string
981    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                // mark the field as initialized
1005                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    /// Puts a value using a provided DefaultInPlaceFn in the current frame.
1017    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        // mark the field as initialized
1036        self.mark_field_as_initialized(shape, index)?;
1037
1038        Ok(self)
1039    }
1040
1041    /// Puts the default value in the current frame.
1042    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    /// Marks a field as initialized in the parent frame.
1062    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    /// Returns the shape of the element type for a list/array
1109    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    /// Returns the shape of the key type for a map
1123    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    /// Creates an empty list without pushing any elements
1137    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        // Initialize an empty list
1155        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        // Mark the field as initialized
1171        self.mark_field_as_initialized(shape, index)?;
1172
1173        Ok(self)
1174    }
1175
1176    /// Creates an empty map without pushing any entries
1177    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        // Initialize an empty map
1195        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        // Mark the field as initialized
1211        self.mark_field_as_initialized(shape, index)?;
1212
1213        Ok(self)
1214    }
1215
1216    /// Begins pushback mode for a list, array, tuple struct, or enum variant tuple struct,
1217    /// allowing elements to be added one by one.
1218    /// For lists/arrays, initializes an empty container if needed.
1219    /// For tuple structs/variants, does nothing (expects subsequent `push` calls).
1220    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                // Check if a variant is selected and if that variant is a tuple-like struct
1235                if let Some(variant) = &frame.istate.variant {
1236                    variant.data.kind == facet_core::StructKind::Tuple
1237                } else {
1238                    // If no variant is selected yet, we can't determine if it's tuple-like.
1239                    // We allow beginning pushback here, assuming a tuple variant *will* be selected
1240                    // before pushing actual elements. The `push` operation will handle variant selection checks.
1241                    // Alternatively, we could error here if no variant is selected. Let's allow it for now.
1242                    // However, we definitely *don't* initialize anything if no variant is selected.
1243                    // UPDATE: Decided to be stricter. If it's an enum, a variant MUST be selected
1244                    // and it MUST be a tuple struct variant.
1245                    false // Require variant to be selected *and* be a tuple.
1246                }
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        // Only initialize for lists/arrays (which fall under Def::List)
1259        if is_list {
1260            let vtable = frame.shape.vtable;
1261            // Initialize an empty list if it's not already marked as initialized (field 0)
1262            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                    // Mark the list itself as initialized (representing the container exists)
1273                    frame.istate.fields.set(0);
1274                }
1275            }
1276        }
1277        // For tuple structs/variants, do nothing here. Initialization happens field-by-field during `push`.
1278
1279        Ok(self)
1280    }
1281
1282    /// Begins insertion mode for a map, allowing key-value pairs to be added one by one
1283    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        // Initialize an empty map if it's not already initialized
1301        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    /// Pushes a new element onto the list/array/tuple struct/tuple enum variant
1319    ///
1320    /// This creates a new frame for the element. When this frame is popped,
1321    /// the element will be added to the list or the corresponding tuple field will be set.
1322    pub fn push(mut self) -> Result<Self, ReflectError> {
1323        // Get mutable access to the top frame early, we might need it for list_index
1324        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        // Determine element shape and context string based on the container type
1335        let (element_shape, context_str): (&'static Shape, &'static str) =
1336            match (seq_shape.ty, seq_shape.def) {
1337                (_, Def::List(_)) => {
1338                    // Check list initialization *before* getting element shape
1339                    if !frame.istate.fields.has(0) {
1340                        // Replicate original recursive call pattern to handle initialization
1341                        // Drop mutable borrow of frame before recursive call
1342                        return self.begin_pushback()?.push();
1343                    }
1344                    // List is initialized, get element shape (requires immutable self)
1345                    // Drop mutable borrow of frame before calling immutable method
1346                    let shape = self.element_shape()?;
1347                    (shape, "list")
1348                }
1349                (Type::Sequence(SequenceType::Tuple(tt)), _) => {
1350                    // Handle tuples - similar to tuple struct handling
1351                    let field_index = {
1352                        // Borrow frame mutably (already done) to update list_index
1353                        let next_idx = frame.istate.list_index.unwrap_or(0);
1354                        frame.istate.list_index = Some(next_idx + 1);
1355                        next_idx
1356                    };
1357                    // Check if the field index is valid
1358                    if field_index >= tt.fields.len() {
1359                        return Err(ReflectError::FieldError {
1360                            shape: seq_shape,
1361                            field_error: FieldError::NoSuchField,
1362                        });
1363                    }
1364                    // Get the shape of the field at the calculated index
1365                    (tt.fields[field_index].shape(), "tuple")
1366                }
1367                (Type::User(UserType::Struct(sd)), _)
1368                    if sd.kind == facet_core::StructKind::Tuple =>
1369                {
1370                    // Handle tuple struct (requires mutable frame for list_index)
1371                    let field_index = {
1372                        // Borrow frame mutably (already done) to update list_index
1373                        let next_idx = frame.istate.list_index.unwrap_or(0);
1374                        frame.istate.list_index = Some(next_idx + 1);
1375                        next_idx
1376                    };
1377                    // Check if the field index is valid
1378                    if field_index >= sd.fields.len() {
1379                        return Err(ReflectError::FieldError {
1380                            shape: seq_shape,
1381                            field_error: FieldError::NoSuchField, // Or maybe SequenceError::OutOfBounds?
1382                        });
1383                    }
1384                    // Get the shape of the field at the calculated index
1385                    (sd.fields[field_index].shape(), "tuple struct")
1386                }
1387
1388                (Type::User(UserType::Enum(_)), _) => {
1389                    // Handle tuple enum variant (requires mutable frame for list_index and variant check)
1390                    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                    // Ensure the selected variant is tuple-like
1400                    if variant.data.kind != facet_core::StructKind::Tuple {
1401                        return Err(ReflectError::WasNotA {
1402                            expected: "tuple-like enum variant",
1403                            actual: seq_shape, // Could provide variant name here for clarity
1404                        });
1405                    }
1406                    // Get the next field index for the tuple variant
1407                    let field_index = {
1408                        // Borrow frame mutably (already done) to update list_index
1409                        let next_idx = frame.istate.list_index.unwrap_or(0);
1410                        frame.istate.list_index = Some(next_idx + 1);
1411                        next_idx
1412                    };
1413                    // Check if the field index is valid within the variant's fields
1414                    if field_index >= variant.data.fields.len() {
1415                        return Err(ReflectError::FieldError {
1416                            shape: seq_shape, // Could provide variant name here
1417                            field_error: FieldError::NoSuchField,
1418                        });
1419                    }
1420                    // Get the shape of the field at the calculated index within the variant
1421                    (
1422                        variant.data.fields[field_index].shape(),
1423                        "tuple enum variant",
1424                    )
1425                }
1426                (_, Def::Scalar(sd)) if matches!(sd.affinity, ScalarAffinity::Empty(_)) => {
1427                    // Handle empty tuple a.k.a. unit type () - cannot push elements
1428                    return Err(ReflectError::OperationFailed {
1429                        shape: seq_shape,
1430                        operation: "cannot push elements to unit type ()",
1431                    });
1432                }
1433                _ => {
1434                    // If it's not a list, tuple struct, or enum, it's an error
1435                    return Err(ReflectError::WasNotA {
1436                        expected: "list, array, tuple, tuple struct, or tuple enum variant",
1437                        actual: seq_shape,
1438                    });
1439                }
1440            };
1441
1442        // Allocate memory for the element
1443        let element_data = element_shape
1444            .allocate()
1445            .map_err(|_| ReflectError::Unsized {
1446                shape: element_shape,
1447            })?;
1448
1449        // Create a new frame for the element
1450        let element_frame = Frame {
1451            data: element_data,
1452            shape: element_shape,
1453            field_index_in_parent: None, // Mode distinguishes it, not field index
1454            istate: IState::new(
1455                frame_len,              // Use captured length (depth of the new frame)
1456                FrameMode::ListElement, // Keep using this mode for list/tuple elements
1457                FrameFlags::ALLOCATED,
1458            ),
1459        };
1460
1461        trace!(
1462            "[{}] Pushing element of type {} to {} {}",
1463            frame_len,
1464            element_shape.green(),
1465            context_str, // Use the determined context string
1466            seq_shape.blue(),
1467        );
1468        let _ = context_str;
1469
1470        self.frames.push(element_frame);
1471        Ok(self)
1472    }
1473
1474    /// Prepare to push the `Some(T)` variant of an `Option<T>`.
1475    pub fn push_some(mut self) -> Result<Self, ReflectError> {
1476        // Make sure we're initializing an option
1477        let frame = self.frames.last().unwrap();
1478        let option_shape = frame.shape;
1479
1480        // Get the option definition
1481        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        // Get the inner type of the option
1489        let inner_shape = option_def.t();
1490
1491        // Allocate memory for the inner value
1492        let inner_data = inner_shape
1493            .allocate()
1494            .map_err(|_| ReflectError::Unsized { shape: inner_shape })?;
1495
1496        // Create a new frame for the inner value
1497        let inner_frame = Frame {
1498            data: inner_data,
1499            shape: inner_shape,
1500            // this is only set when we pop
1501            field_index_in_parent: None,
1502            istate: IState::new(
1503                self.frames.len(),
1504                FrameMode::OptionSome,
1505                // TODO: we could lazy-allocate it when something like `field` is called, tbh
1506                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    /// Pops a not-yet-initialized option frame, setting it to None in the parent
1521    ///
1522    /// This is used to set an option to None instead of Some.
1523    /// Steps:
1524    ///  1. Asserts the option frame is NOT initialized
1525    ///  2. Frees the memory for the pushed value
1526    ///  3. Pops the frame
1527    ///  4. Sets the parent option to its default value (i.e., None)
1528    ///  5. Pops the parent option (which is the actual `Option<T>`, but no longer in option mode)
1529    pub fn pop_some_push_none(mut self) -> Result<Self, ReflectError> {
1530        // 1. Option frame must exist
1531        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        // 1. Make sure the current frame is an option inner frame in "Option" mode
1539        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        // 1. Check not initialized
1547        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        // 3. Pop the frame (this discards, doesn't propagate up)
1557        let _frame = self.frames.pop().expect("frame already checked");
1558
1559        // 4. Set parent option (which we just popped into) to default (None)
1560        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        // Safety: option frames are correctly sized, and data is valid
1569        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        // Now push a `None` frame
1589        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    /// Pushes a new key frame for a map entry
1607    ///
1608    /// This creates a new frame for the key. After setting the key value,
1609    /// call `push_map_value` to create a frame for the corresponding value.
1610    pub fn push_map_key(mut self) -> Result<Self, ReflectError> {
1611        // Make sure we're initializing a map
1612        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 the map isn't initialized yet, initialize it
1623        if !frame.istate.fields.has(0) {
1624            self = self.begin_map_insert()?;
1625        }
1626
1627        // Get the key type
1628        let key_shape = self.key_shape()?;
1629
1630        // Allocate memory for the key
1631        let key_data = key_shape
1632            .allocate()
1633            .map_err(|_| ReflectError::Unsized { shape: key_shape })?;
1634
1635        // Create a new frame for the key
1636        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    /// Pushes a new value frame for a map entry
1655    ///
1656    /// This should be called after pushing and initializing a key frame.
1657    /// When the value frame is popped, the key-value pair will be added to the map.
1658    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        // First, ensure we have a valid key frame
1666        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        // Check the frame before the last to ensure it's a map key
1674        let key_frame_index = self.frames.len() - 1;
1675        let key_frame = &self.frames[key_frame_index];
1676
1677        // Verify the current frame is a key frame
1678        match key_frame.istate.mode {
1679            FrameMode::MapKey => {} // Valid - continue
1680            _ => {
1681                return Err(ReflectError::OperationFailed {
1682                    shape: key_frame.shape,
1683                    operation: "current frame is not a map key",
1684                });
1685            }
1686        }
1687
1688        // Check that the key is fully initialized
1689        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        // Get the parent map frame to verify we're working with a map
1697        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        // Allocate memory for the value
1711        let value_data = value_shape
1712            .allocate()
1713            .map_err(|_| ReflectError::Unsized { shape: value_shape })?;
1714
1715        // Create a new frame for the value
1716        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    /// Pops the current frame — goes back up one level
1742    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        // Handle special frame modes
1784        match frame.istate.mode {
1785            // Handle list element frames
1786            FrameMode::ListElement => {
1787                if frame.is_fully_initialized() {
1788                    // This was a list or tuple element, so we need to push it to the parent
1789                    #[cfg(feature = "log")]
1790                    let frame_len = self.frames.len();
1791
1792                    // Get parent frame
1793                    let parent_frame = self.frames.last_mut().unwrap();
1794                    let parent_shape = parent_frame.shape;
1795
1796                    match parent_shape.def {
1797                        // Handle List/Array
1798                        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                            // Mark the parent scalar unit as fully initialized
1820                            unsafe {
1821                                parent_frame.mark_fully_initialized();
1822                                self.mark_moved_out_of(&mut frame);
1823                            }
1824                        }
1825                        _ => match parent_shape.ty {
1826                            // Handle Empty Unit Types (including empty tuple structs and tuples)
1827                            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                                // Mark the parent unit struct as fully initialized
1837                                unsafe {
1838                                    parent_frame.mark_fully_initialized();
1839                                }
1840                                // Element frame is implicitly moved/consumed, but nothing to dealloc if it was also unit
1841                                unsafe { self.mark_moved_out_of(&mut frame) };
1842                            }
1843
1844                            // Handle tuples (Type::Sequence(SequenceType::Tuple))
1845                            Type::Sequence(SequenceType::Tuple(tt)) => {
1846                                // Get the field index from list_index saved during push
1847                                let previous_index = parent_frame.istate.list_index.unwrap_or(1);
1848                                let field_index = previous_index - 1; // -1 because we incremented *after* using the index in push
1849
1850                                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                                    // Copy the element data to the tuple field
1870                                    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                                        })?; // Use ? to propagate potential unsized error
1879
1880                                    // Mark the specific field as initialized using its index
1881                                    parent_frame.istate.fields.set(field_index);
1882
1883                                    // Mark the element as moved
1884                                    self.mark_moved_out_of(&mut frame);
1885                                }
1886                            }
1887
1888                            // Handle Tuple Structs
1889                            Type::User(UserType::Struct(sd))
1890                                if sd.kind == facet_core::StructKind::Tuple =>
1891                            {
1892                                // Get the field index from list_index saved during push
1893                                let previous_index = parent_frame.istate.list_index.unwrap_or(1);
1894                                let field_index = previous_index - 1; // -1 because we incremented *after* using the index in push
1895
1896                                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                                    // Copy the element data to the tuple field
1916                                    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                                        })?; // Use ? to propagate potential unsized error
1925
1926                                    // Mark the specific field as initialized using its index
1927                                    parent_frame.istate.fields.set(field_index);
1928
1929                                    // Mark the element as moved
1930                                    self.mark_moved_out_of(&mut frame);
1931                                }
1932                            }
1933
1934                            // Handle Tuple Enum Variants
1935                            Type::User(UserType::Enum(_)) => {
1936                                // Ensure a variant is selected and it's a tuple variant
1937                                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                                // Get the field index from list_index saved during push
1953                                let previous_index = parent_frame.istate.list_index.unwrap_or(1);
1954                                let field_index = previous_index - 1; // -1 because we incremented *after* using the index in push
1955
1956                                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                                    // Copy the element data to the tuple field within the enum's data payload
1978                                    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                                        })?; // Use ? to propagate potential unsized error
1987
1988                                    // Mark the specific field as initialized using its index
1989                                    parent_frame.istate.fields.set(field_index);
1990
1991                                    // Mark the element as moved
1992                                    self.mark_moved_out_of(&mut frame);
1993                                }
1994                            }
1995
1996                            // Unexpected parent type
1997                            _ => {
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                    // Frame not fully initialized, just deallocate if needed (handled by Frame drop later)
2007                    trace!(
2008                        "Popping uninitialized ListElement frame ({}), potential leak if allocated resources are not managed",
2009                        frame.shape.yellow()
2010                    );
2011                }
2012            }
2013
2014            // Handle map value frames
2015            FrameMode::MapValue {
2016                index: key_frame_index,
2017            } if frame.is_fully_initialized() => {
2018                // This was a map value, so we need to insert the key-value pair into the map
2019
2020                // Now let's remove the key frame from the frames array
2021                let mut key_frame = self.frames.remove(key_frame_index);
2022
2023                // Make sure the key is fully initialized
2024                if !key_frame.istate.fields.is_any_set() {
2025                    panic!("key is not initialized when popping value frame");
2026                }
2027
2028                // Get parent map frame
2029                #[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                // Make sure the parent is a map
2035                match parent_shape.def {
2036                    Def::Map(_) => {
2037                        // Get the map vtable from the MapDef
2038                        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                                // Call the map's insert function with the key and value
2046                                (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            // Handle option frames
2065            FrameMode::OptionSome => {
2066                if frame.is_fully_initialized() {
2067                    trace!("Popping OptionSome (fully init'd)");
2068
2069                    // Get parent frame
2070                    #[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                    // Make sure the parent is an option
2076                    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                                // Call the option's init_some function
2085                                (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); // the `Some` variant
2109                                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            // Map keys are just tracked, they don't need special handling when popped
2139            // FIXME: that's not true, we need to deallocate them at least??
2140            FrameMode::MapKey => {}
2141
2142            // Field frame
2143            FrameMode::Field => {}
2144
2145            // Uninitialized special frames
2146            _ => {}
2147        }
2148
2149        Ok(Some(frame))
2150    }
2151
2152    /// Evict a frame from istates, along with all its children
2153    /// (because we're about to use `drop_in_place` on it — not
2154    /// yet though, we need to know the variant for enums, etc.)
2155    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                // Check if a variant is selected in the istate
2173                if let Some(variant) = &frame.istate.variant {
2174                    trace!(
2175                        "Evicting enum {} variant '{}' fields",
2176                        frame.shape.blue(),
2177                        variant.name.yellow()
2178                    );
2179                    // Iterate over the fields of the selected variant
2180                    for field in variant.data.fields {
2181                        // Calculate the pointer to the field within the enum's data payload
2182                        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                        // Try to remove the field's state from istates
2187                        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                            // Recompose the frame for the field
2195                            let field_frame = Frame::recompose(field_id, field_istate);
2196                            // Recursively evict the field's subtree
2197                            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                    // No variant selected, nothing to evict within the enum
2209                    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    /// Returns the current path in the JSON document as a string.
2222    /// For example: "$.users[0].name"
2223    pub fn path(&self) -> String {
2224        let mut path = String::from("$");
2225
2226        for (i, frame) in self.frames.iter().enumerate() {
2227            // Skip the root frame
2228            if i == 0 {
2229                continue;
2230            }
2231
2232            match frame.istate.mode {
2233                FrameMode::ListElement => {
2234                    // For arrays, we use bracket notation with index
2235                    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                    // Root doesn't add to the path
2255                }
2256                FrameMode::Field => {
2257                    // For struct fields, we use dot notation with field name
2258                    if let Some(index) = frame.field_index_in_parent {
2259                        // Find the parent frame to get the field name
2260                        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    /// Returns true if the field at the given index is set (initialized) in the current frame.
2286    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                        // we'll also need to clean up if we're root
2413                        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                    // Check if a variant is selected
2431                    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                        // Recursively clean fields of the variant that are initialized
2440                        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                                    // that means it's fully initialized and we need to drop it
2464                                    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                    // we'll also need to clean up if we're root
2489                    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        // We might have some frames left over to deallocate for temporary allocations for keymap insertion etc.
2517        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}