facet_reflect/wip/
mod.rs

1use crate::{ReflectError, ValueId};
2use alloc::{format, string::ToString};
3use alloc::{vec, vec::Vec};
4use bitflags::bitflags;
5use core::{fmt, marker::PhantomData};
6use facet_core::{Def, Facet, FieldError, PtrConst, PtrMut, PtrUninit, Shape, Variant};
7use flat_map::FlatMap;
8use log::trace;
9use yansi::Paint as _;
10
11use alloc::string::String;
12
13mod iset;
14pub use iset::*;
15
16mod enum_;
17mod flat_map;
18
19mod heap_value;
20pub use heap_value::*;
21
22fn def_kind(def: &Def) -> &'static str {
23    match def {
24        Def::Scalar(_) => "scalar",
25        Def::Struct(_) => "struct",
26        Def::Map(_) => "map",
27        Def::List(_) => "list",
28        Def::Enum(_) => "enum",
29        Def::Option(_) => "option",
30        Def::SmartPointer(_) => "smart_ptr",
31        _ => "other",
32    }
33}
34
35/// Represents a frame in the initialization stack
36pub struct Frame {
37    /// The value we're initializing
38    data: PtrUninit<'static>,
39
40    /// The shape of the value
41    shape: &'static Shape,
42
43    /// If set, when we're initialized, we must mark the
44    /// parent's indexth field as initialized.
45    field_index_in_parent: Option<usize>,
46
47    /// Tracking which of our fields are initialized
48    /// TODO: I'm not sure we should track "ourselves" as initialized — we always have the
49    /// parent to look out for, right now we're tracking children in two states, which isn't ideal
50    istate: IState,
51}
52
53impl Frame {
54    /// Given a ValueId and an IState, recompose a Frame suitable for tracking
55    fn recompose(id: ValueId, istate: IState) -> Self {
56        Frame {
57            data: PtrUninit::new(id.ptr as *mut u8),
58            shape: id.shape,
59            field_index_in_parent: None,
60            istate,
61        }
62    }
63
64    /// Deallocates the memory used by this frame if it was heap-allocated.
65    fn dealloc_if_needed(&mut self) {
66        if self.istate.flags.contains(FrameFlags::ALLOCATED) {
67            trace!(
68                "[{}] {:p} => deallocating {}",
69                self.istate.depth,
70                self.data.as_mut_byte_ptr().magenta(),
71                self.shape.green(),
72            );
73            if self.shape.layout.size() != 0 {
74                trace!("Ok I swear we're deallocating it");
75                unsafe {
76                    alloc::alloc::dealloc(self.data.as_mut_byte_ptr(), self.shape.layout);
77                }
78            }
79            self.istate.flags.remove(FrameFlags::ALLOCATED);
80        } else {
81            trace!(
82                "[{}] {:p} => NOT deallocating {} (not ALLOCATED)",
83                self.istate.depth,
84                self.data.as_mut_byte_ptr().magenta(),
85                self.shape.green(),
86            );
87        }
88    }
89}
90
91struct DebugToDisplay<T>(T);
92
93impl<T> fmt::Debug for DebugToDisplay<T>
94where
95    T: fmt::Display,
96{
97    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
98        fmt::Display::fmt(&self.0, f)
99    }
100}
101
102impl fmt::Debug for Frame {
103    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
104        f.debug_struct("Frame")
105            .field("shape", &DebugToDisplay(&self.shape))
106            .field("kind", &def_kind(&self.shape.def))
107            .field("index", &self.field_index_in_parent)
108            .field("mode", &self.istate.mode)
109            .finish()
110    }
111}
112
113impl Frame {
114    /// Returns the value ID for a frame
115    fn id(&self) -> ValueId {
116        ValueId::new(self.shape, self.data.as_byte_ptr())
117    }
118
119    /// Returns true if the frame is fully initialized
120    fn is_fully_initialized(&self) -> bool {
121        match self.shape.def {
122            Def::Struct(sd) => self.istate.fields.are_all_set(sd.fields.len()),
123            Def::Enum(_) => match self.istate.variant.as_ref() {
124                None => false,
125                Some(v) => self.istate.fields.are_all_set(v.data.fields.len()),
126            },
127            _ => self.istate.fields.are_all_set(1),
128        }
129    }
130
131    // Safety: only call if is fully initialized
132    unsafe fn drop_and_dealloc_if_needed(mut self) {
133        trace!(
134            "[Frame::drop] Dropping frame for shape {} at {:p}",
135            self.shape.blue(),
136            self.data.as_byte_ptr()
137        );
138        if let Some(drop_in_place) = self.shape.vtable.drop_in_place {
139            unsafe {
140                trace!(
141                    "[Frame::drop] Invoking drop_in_place for shape {} at {:p}",
142                    self.shape.green(),
143                    self.data.as_byte_ptr()
144                );
145                drop_in_place(self.data.assume_init());
146            }
147        } else {
148            trace!(
149                "[Frame::drop] No drop_in_place function for shape {}",
150                self.shape.blue(),
151            );
152        }
153        self.dealloc_if_needed();
154    }
155
156    /// Marks the frame as fully initialized
157    unsafe fn mark_fully_initialized(&mut self) {
158        match self.shape.def {
159            Def::Struct(sd) => {
160                self.istate.fields = ISet::all(sd.fields);
161            }
162            Def::Enum(_) => {
163                if let Some(variant) = &self.istate.variant {
164                    self.istate.fields = ISet::all(variant.data.fields);
165                }
166            }
167            _ => {
168                self.istate.fields.set(0);
169            }
170        }
171    }
172
173    /// Marks the frame as uninitialized (all fields unset and variant reset)
174    unsafe fn mark_uninitialized(&mut self) {
175        ISet::clear(&mut self.istate.fields);
176        self.istate.variant = None;
177    }
178
179    unsafe fn mark_moved_out_of(&mut self) {
180        self.dealloc_if_needed();
181        unsafe { self.mark_uninitialized() };
182        self.istate.flags.insert(FrameFlags::MOVED);
183    }
184}
185
186/// Initialization state
187struct IState {
188    /// Variant chosen — for everything except enums, this stays None
189    variant: Option<Variant>,
190
191    /// Fields that were initialized. For scalars, we only track 0
192    fields: ISet,
193
194    /// The depth of the frame in the stack
195    depth: usize,
196
197    /// The special mode of this frame (if any)
198    mode: FrameMode,
199
200    /// If true, must be freed when dropped
201    flags: FrameFlags,
202
203    /// The current index for list elements
204    list_index: Option<usize>,
205
206    /// The current key for map elements
207    #[allow(dead_code)]
208    map_key: Option<String>,
209}
210
211bitflags! {
212    /// Flags that can be applied to frames
213    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
214    pub struct FrameFlags: u64 {
215        /// An empty set of flags
216        const EMPTY = 0;
217
218        /// We allocated this frame on the heap, we need to deallocated it when popping
219        const ALLOCATED = 1 << 0;
220
221        /// This value was moved out of — it's not part of the value we're building and
222        /// we shouldn't error out when we build and we notice it's not initialized.
223        /// In fact, it should not be tracked at all.
224        const MOVED = 1 << 1;
225    }
226
227    // Note: there is no 'initialized' flag because initialization can be partial — it's tracked via `ISet`
228}
229
230impl IState {
231    /// Creates a new `IState` with the given depth.
232    pub fn new(depth: usize, mode: FrameMode, flags: FrameFlags) -> Self {
233        Self {
234            variant: None,
235            fields: Default::default(),
236            depth,
237            mode,
238            flags,
239            list_index: None,
240            map_key: None,
241        }
242    }
243
244    /// Sets the list index and returns self for method chaining
245    #[allow(dead_code)]
246    pub fn with_list_index(mut self, index: usize) -> Self {
247        self.list_index = Some(index);
248        self
249    }
250
251    /// Sets the map key and returns self for method chaining
252    #[allow(dead_code)]
253    pub fn with_map_key(mut self, key: String) -> Self {
254        self.map_key = Some(key);
255        self
256    }
257}
258
259/// Represents the special mode a frame can be in
260#[derive(Debug, Clone, Copy, PartialEq, Eq)]
261pub enum FrameMode {
262    /// Root frame
263    Root,
264    /// Normal frame
265    Normal,
266    /// Frame represents a list element
267    ListElement,
268    /// Frame represents a map key
269    MapKey,
270    /// Frame represents a map value with the given key frame index
271    MapValue {
272        /// The index of the key frame associated with this map value
273        index: usize,
274    },
275    /// Frame represents the Some variant of an option (that we allocated)
276    OptionSome,
277    /// Frame represents the None variant of an option (no allocation needed)
278    /// Any `put` should fail
279    OptionNone,
280}
281
282/// A work-in-progress heap-allocated value
283pub struct Wip<'a> {
284    /// stack of frames to keep track of deeply nested initialization
285    frames: alloc::vec::Vec<Frame>,
286
287    /// keeps track of initialization of out-of-tree frames
288    istates: FlatMap<ValueId, IState>,
289
290    /// lifetime of the shortest reference we hold
291    phantom: PhantomData<&'a ()>,
292}
293
294impl<'a> Wip<'a> {
295    /// Returns the number of frames on the stack
296    pub fn frames_count(&self) -> usize {
297        self.frames.len()
298    }
299
300    /// Allocates a new value of the given shape
301    pub fn alloc_shape(shape: &'static Shape) -> Self {
302        let data = shape.allocate();
303        Self {
304            frames: alloc::vec![Frame {
305                data,
306                shape,
307                field_index_in_parent: None,
308                istate: IState::new(0, FrameMode::Root, FrameFlags::ALLOCATED),
309            }],
310            istates: Default::default(),
311            phantom: PhantomData,
312        }
313    }
314
315    /// Allocates a new value of type `S`
316    pub fn alloc<S: Facet>() -> Self {
317        Self::alloc_shape(S::SHAPE)
318    }
319
320    fn track(&mut self, frame: Frame) {
321        if frame.istate.flags.contains(FrameFlags::MOVED) {
322            // In fact, it should not be tracked at all.
323            return;
324        }
325        self.istates.insert(frame.id(), frame.istate);
326    }
327
328    /// Returns the shape of the current frame
329    pub fn shape(&self) -> &'static Shape {
330        self.frames.last().unwrap().shape
331    }
332
333    /// Return true if the last frame is in option mode
334    pub fn in_option(&self) -> bool {
335        let Some(frame) = self.frames.last() else {
336            return false;
337        };
338        matches!(frame.istate.mode, FrameMode::OptionSome)
339    }
340
341    /// Returns the mode of the current frame
342    pub fn mode(&self) -> FrameMode {
343        self.frames.last().unwrap().istate.mode
344    }
345
346    /// Asserts everything is initialized and that invariants are upheld (if any)
347    pub fn build(mut self) -> Result<HeapValue<'a>, ReflectError> {
348        trace!("[{}] ⚒️ It's BUILD time", self.frames.len());
349
350        // 1. Track all frames currently on the stack into istates
351        while let Some(frame) = self.pop_inner() {
352            self.track(frame);
353        }
354
355        // 2. Find the root frame
356        let Some((root_id, _)) = self.istates.iter().find(|(_k, istate)| istate.depth == 0) else {
357            trace!("No root found, possibly already built or empty WIP");
358            return Err(ReflectError::OperationFailed {
359                shape: <()>::SHAPE,
360                operation: "tried to build a value but there was no root frame tracked",
361            });
362        };
363
364        let root_id = *root_id;
365        // We need to *keep* the root istate for the check, so we clone it or get it immutably.
366        // Let's retrieve it immutably first. The `istates` map will be dropped with `Wip` anyway.
367        let root_istate = self
368            .istates
369            .remove(&root_id)
370            .expect("Root ID found but not present in istates, this is a bug"); // Clone needed to avoid borrowing issues later potentially
371
372        let root_frame = Frame::recompose(root_id, root_istate);
373        let root_shape = root_frame.shape;
374        let root_data_ptr = root_frame.data; // Keep the root pointer for the final HeapValue
375
376        // 6. Transfer ownership of the root data to the HeapValue
377        // The root frame should have had the ALLOCATED flag if it was heap allocated.
378        // We need to ensure the Guard takes ownership correctly.
379        // Find the original root istate again to check the flag.
380        let guard = Guard {
381            ptr: root_data_ptr.as_mut_byte_ptr(),
382            layout: root_shape.layout,
383        };
384
385        // 3. Initialize `to_check`
386        let mut to_check = alloc::vec![root_frame];
387
388        // 4. Traverse the tree
389        while let Some(frame) = to_check.pop() {
390            trace!(
391                "Checking frame: shape={} at {:p}, flags={:?}, mode={:?}",
392                frame.shape.blue(),
393                frame.data.as_byte_ptr(),
394                frame.istate.flags.bright_magenta(),
395                frame.istate.mode,
396            );
397
398            // Skip moved frames
399            if frame.istate.flags.contains(FrameFlags::MOVED) {
400                trace!(
401                    "{}",
402                    "Frame was moved out of, skipping initialization check".yellow()
403                );
404                continue;
405            }
406
407            // Check initialization for the current frame
408            match frame.shape.def {
409                Def::Struct(sd) => {
410                    if !frame.is_fully_initialized() {
411                        // find the field that's not initialized
412                        for i in 0..sd.fields.len() {
413                            if !frame.istate.fields.has(i) {
414                                let field = &sd.fields[i];
415                                return Err(ReflectError::UninitializedField {
416                                    shape: frame.shape,
417                                    field_name: field.name,
418                                });
419                            }
420                        }
421                        // Should be unreachable
422                        unreachable!(
423                            "Enum variant not fully initialized but couldn't find which field"
424                        );
425                    }
426
427                    // If initialized, push children to check stack
428                    for (i, field) in sd.fields.iter().enumerate() {
429                        let field_shape = field.shape();
430                        let field_ptr = unsafe { frame.data.field_init_at(field.offset) };
431                        let field_id = ValueId::new(field_shape, field_ptr.as_byte_ptr());
432
433                        if let Some(field_istate) = self.istates.remove(&field_id) {
434                            trace!(
435                                "Queueing struct field check: #{} '{}' of {}: shape={}, ptr={:p}",
436                                i.to_string().bright_cyan(),
437                                field.name.bright_blue(),
438                                frame.shape.blue(),
439                                field_shape.green(),
440                                field_ptr.as_byte_ptr()
441                            );
442                            let field_frame = Frame::recompose(field_id, field_istate);
443                            to_check.push(field_frame);
444                        }
445                    }
446                }
447                Def::Enum(_ed) => {
448                    if let Some(variant) = &frame.istate.variant {
449                        if !frame.istate.fields.are_all_set(variant.data.fields.len()) {
450                            // Find the uninitialized field
451                            for (i, field) in variant.data.fields.iter().enumerate() {
452                                if !frame.istate.fields.has(i) {
453                                    return Err(ReflectError::UninitializedEnumField {
454                                        shape: frame.shape,
455                                        variant_name: variant.name,
456                                        field_name: field.name,
457                                    });
458                                }
459                            }
460                            // Should be unreachable
461                            unreachable!(
462                                "Enum variant not fully initialized but couldn't find which field"
463                            );
464                        }
465
466                        // If initialized, push children to check stack
467                        for (i, field) in variant.data.fields.iter().enumerate() {
468                            let field_shape = field.shape();
469                            // Enum fields are potentially at different offsets depending on the variant layout.
470                            // We assume the `frame.data` points to the start of the enum's data payload
471                            // (after the discriminant if applicable and handled by layout).
472                            let field_ptr = unsafe { frame.data.field_init_at(field.offset) };
473                            let field_id = ValueId::new(field_shape, field_ptr.as_byte_ptr());
474
475                            if let Some(field_istate) = self.istates.remove(&field_id) {
476                                trace!(
477                                    "Queueing enum field check: #{} '{}' of variant '{}' of {}: shape={}, ptr={:p}",
478                                    i.to_string().bright_cyan(),
479                                    field.name.bright_blue(),
480                                    variant.name.yellow(),
481                                    frame.shape.blue(),
482                                    field_shape.green(),
483                                    field_ptr.as_byte_ptr()
484                                );
485                                let field_frame = Frame::recompose(field_id, field_istate);
486                                to_check.push(field_frame);
487                            }
488                        }
489                    } else {
490                        // No variant selected is an error during build
491                        return Err(ReflectError::NoVariantSelected { shape: frame.shape });
492                    }
493                }
494                // For types that manage their own contents (List, Map, Option, Scalar, etc.),
495                // we just need to check if the *container* itself is marked as initialized.
496                // The recursive check handles struct/enum *elements* within these containers if they exist.
497                Def::List(_)
498                | Def::Map(_)
499                | Def::Option(_)
500                | Def::Scalar(_)
501                | Def::SmartPointer(_)
502                | Def::Array(_)
503                | Def::Slice(_) => {
504                    if !frame.istate.fields.are_all_set(1) {
505                        // Check specific modes for better errors
506                        match frame.istate.mode {
507                            FrameMode::OptionNone => {
508                                // This should technically be marked initialized, but if not, treat as uninit Option
509                                return Err(ReflectError::UninitializedValue {
510                                    shape: frame.shape,
511                                });
512                            }
513                            // Add more specific checks if needed, e.g., for lists/maps that started but weren't finished?
514                            _ => {
515                                return Err(ReflectError::UninitializedValue {
516                                    shape: frame.shape,
517                                });
518                            }
519                        }
520                    }
521                    // No children to push onto `to_check` from the perspective of the *container* frame itself.
522                    // If a List contains Structs, those struct frames would have been pushed/popped
523                    // and their states tracked individually in `istates`, and checked when encountered via
524                    // `to_check` if they were fields of another struct/enum.
525                    // The `Drop` logic handles cleaning these contained items based on the container's drop_in_place.
526                    // For `build`, we trust that if the container is marked initialized, its contents are valid
527                    // according to its type's rules.
528                }
529                // Handle other Def variants if necessary
530                _ => {
531                    // Default: Check if initialized using the standard method
532                    if !frame.istate.fields.are_all_set(1) {
533                        return Err(ReflectError::UninitializedValue { shape: frame.shape });
534                    }
535                }
536            }
537        }
538
539        // If we finished the loop, all reachable and non-moved frames are initialized.
540        trace!("All reachable frames checked and initialized.");
541
542        // 5. Check invariants on the root
543        let data = unsafe { root_data_ptr.assume_init() };
544        if let Some(invariant_fn) = root_shape.vtable.invariants {
545            trace!(
546                "Checking invariants for root shape {} at {:p}",
547                root_shape.green(),
548                data.as_byte_ptr()
549            );
550            if !unsafe { invariant_fn(PtrConst::new(data.as_byte_ptr())) } {
551                return Err(ReflectError::InvariantViolation {
552                    invariant: "Custom validation function returned false",
553                });
554            }
555        } else {
556            trace!(
557                "No invariants to check for root shape {}",
558                root_shape.blue()
559            );
560        }
561
562        FlatMap::clear(&mut self.istates); // Prevent Drop from running on the successfully built value.
563
564        Ok(HeapValue {
565            guard: Some(guard),
566            shape: root_shape,
567            phantom: PhantomData,
568        })
569    }
570
571    /// Selects a field of a struct or enum variant by index and pushes it onto the frame stack.
572    ///
573    /// # Arguments
574    ///
575    /// * `index` - The index of the field to select.
576    ///
577    /// # Returns
578    ///
579    /// * `Ok(Self)` if the field was successfully selected and pushed.
580    /// * `Err(ReflectError)` if the current frame is not a struct or an enum with a selected variant,
581    ///   or if the field doesn't exist.
582    pub fn field(mut self, index: usize) -> Result<Self, ReflectError> {
583        let frame = self.frames.last_mut().unwrap();
584        let shape = frame.shape;
585
586        let (field, field_offset) = match shape.def {
587            Def::Struct(def) => {
588                if index >= def.fields.len() {
589                    return Err(ReflectError::FieldError {
590                        shape,
591                        field_error: FieldError::NoSuchField,
592                    });
593                }
594                let field = &def.fields[index];
595                (field, field.offset)
596            }
597            Def::Enum(_) => {
598                let Some(variant) = frame.istate.variant.as_ref() else {
599                    return Err(ReflectError::OperationFailed {
600                        shape,
601                        operation: "tried to access a field but no variant was selected",
602                    });
603                };
604
605                if index >= variant.data.fields.len() {
606                    return Err(ReflectError::FieldError {
607                        shape,
608                        field_error: FieldError::NoSuchField,
609                    });
610                }
611
612                let field = &variant.data.fields[index];
613                (field, field.offset)
614            }
615            _ => {
616                return Err(ReflectError::WasNotA {
617                    expected: "struct or enum",
618                    actual: shape,
619                });
620            }
621        };
622
623        let field_data = unsafe { frame.data.field_uninit_at(field_offset) };
624
625        let mut frame = Frame {
626            data: field_data,
627            shape: field.shape(),
628            field_index_in_parent: Some(index),
629            // we didn't have to allocate that field, it's a struct field, so it's not allocated
630            istate: IState::new(self.frames.len(), FrameMode::Normal, FrameFlags::EMPTY),
631        };
632        trace!(
633            "[{}] Selecting field {} ({}#{}) of {}",
634            self.frames.len(),
635            field.name.blue(),
636            field.shape().green(),
637            index.yellow(),
638            shape.blue(),
639        );
640        if let Some(iset) = self.istates.remove(&frame.id()) {
641            trace!(
642                "[{}] Restoring saved state for {}",
643                self.frames.len(),
644                frame.id().shape.blue()
645            );
646            frame.istate = iset;
647        }
648        self.frames.push(frame);
649        Ok(self)
650    }
651
652    /// Finds the index of a field in a struct or enum variant by name.
653    ///
654    /// # Arguments
655    ///
656    /// * `name` - The name of the field to find.
657    ///
658    /// # Returns
659    ///
660    /// * `Some(usize)` if the field was found.
661    /// * `None` if the current frame is not a struct or an enum with a selected variant,
662    ///   or if the field doesn't exist.
663    pub fn field_index(&self, name: &str) -> Option<usize> {
664        let frame = self.frames.last()?;
665        match frame.shape.def {
666            Def::Struct(def) => def.fields.iter().position(|f| f.name == name),
667            Def::Enum(_) => {
668                // Get the selected variant
669                let variant = frame.istate.variant.as_ref()?;
670                variant.data.fields.iter().position(|f| f.name == name)
671            }
672            _ => None,
673        }
674    }
675
676    /// Selects a field of a struct or enum variant by name and pushes it onto the frame stack.
677    ///
678    /// # Arguments
679    ///
680    /// * `name` - The name of the field to select.
681    ///
682    /// # Returns
683    ///
684    /// * `Ok(Self)` if the field was successfully selected and pushed.
685    /// * `Err(ReflectError)` if the current frame is not a struct or an enum with a selected variant,
686    ///   or if the field doesn't exist.
687    pub fn field_named(self, name: &str) -> Result<Self, ReflectError> {
688        let frame = self.frames.last().unwrap();
689        let shape = frame.shape;
690
691        // For enums, ensure a variant is selected
692        if let Def::Enum(_) = shape.def {
693            if frame.istate.variant.is_none() {
694                return Err(ReflectError::OperationFailed {
695                    shape,
696                    operation: "tried to access a field by name but no variant was selected",
697                });
698            }
699        }
700
701        let index = self.field_index(name).ok_or(ReflectError::FieldError {
702            shape,
703            field_error: FieldError::NoSuchField,
704        })?;
705
706        self.field(index)
707    }
708
709    /// Puts a value of type `T` into the current frame.
710    ///
711    /// # Arguments
712    ///
713    /// * `t` - The value to put into the frame.
714    ///
715    /// # Returns
716    ///
717    /// * `Ok(Self)` if the value was successfully put into the frame.
718    /// * `Err(ReflectError)` if there was an error putting the value into the frame.
719    pub fn put<'val, T: Facet + 'val>(mut self, t: T) -> Result<Wip<'val>, ReflectError>
720    where
721        'a: 'val,
722    {
723        let Some(frame) = self.frames.last_mut() else {
724            return Err(ReflectError::OperationFailed {
725                shape: T::SHAPE,
726                operation: "tried to put a T but there was no frame to put T into",
727            });
728        };
729
730        // check that the type matches
731        if !frame.shape.is_type::<T>() {
732            // maybe we're putting into an Option<T> ?
733            if frame.shape.is_type::<Option<T>>() {
734                trace!("Putting into an option!");
735                let Def::Option(od) = frame.shape.def else {
736                    unreachable!()
737                };
738
739                // unfortunately this all involves copying data over
740                let src = PtrConst::new(&raw const t);
741                if frame.istate.fields.is_any_set() {
742                    let data = unsafe { frame.data.assume_init() };
743                    unsafe { (od.vtable.replace_with_fn)(data, Some(src)) };
744                } else {
745                    let data = frame.data;
746                    unsafe { (od.vtable.init_some_fn)(data, src) };
747                }
748                unsafe {
749                    frame.mark_fully_initialized();
750                }
751                // t will drop naturally at the end of this function
752
753                let shape = frame.shape;
754                let index = frame.field_index_in_parent;
755
756                // mark the field as initialized
757                self.mark_field_as_initialized(shape, index)?;
758
759                trace!("[{}] Just put a {} value", self.frames.len(), shape.green());
760
761                return Ok(self);
762            }
763
764            return Err(ReflectError::WrongShape {
765                expected: frame.shape,
766                actual: T::SHAPE,
767            });
768        }
769
770        // de-initialize partially initialized fields
771        if frame.istate.variant.is_some() || frame.istate.fields.is_any_set() {
772            trace!(
773                "De-initializing partially initialized fields for {}",
774                frame.shape
775            );
776
777            match frame.shape.def {
778                Def::Struct(sd) => {
779                    for (i, field) in sd.fields.iter().enumerate() {
780                        if frame.istate.fields.has(i) {
781                            if let Some(drop_fn) = field.shape().vtable.drop_in_place {
782                                unsafe {
783                                    let field_ptr = frame.data.as_mut_byte_ptr().add(field.offset);
784                                    drop_fn(PtrMut::new(field_ptr));
785                                }
786                            }
787                        }
788                    }
789                }
790                Def::Enum(_) => {
791                    if let Some(variant) = &frame.istate.variant {
792                        for (i, field) in variant.data.fields.iter().enumerate() {
793                            if frame.istate.fields.has(i) {
794                                if let Some(drop_fn) = field.shape().vtable.drop_in_place {
795                                    unsafe {
796                                        let field_ptr =
797                                            frame.data.as_mut_byte_ptr().add(field.offset);
798                                        drop_fn(PtrMut::new(field_ptr));
799                                    }
800                                }
801                            }
802                        }
803                    }
804                }
805                _ => {
806                    // For scalar types, nothing to do if not fully initialized
807                }
808            }
809
810            // Reset initialization state
811            frame.istate.variant = None;
812            ISet::clear(&mut frame.istate.fields);
813        }
814
815        unsafe {
816            frame.data.put(t);
817            frame.mark_fully_initialized();
818        }
819
820        let shape = frame.shape;
821        let index = frame.field_index_in_parent;
822
823        // mark the field as initialized
824        self.mark_field_as_initialized(shape, index)?;
825
826        trace!("[{}] Just put a {} value", self.frames.len(), shape.green());
827
828        Ok(self)
829    }
830
831    /// Tries to parse the current frame's value from a string
832    pub fn parse(mut self, s: &str) -> Result<Self, ReflectError> {
833        let Some(frame) = self.frames.last_mut() else {
834            return Err(ReflectError::OperationFailed {
835                shape: <()>::SHAPE,
836                operation: "tried to parse value but there was no frame",
837            });
838        };
839
840        let shape = frame.shape;
841        let index = frame.field_index_in_parent;
842
843        let Some(parse_fn) = frame.shape.vtable.parse else {
844            return Err(ReflectError::OperationFailed {
845                shape: frame.shape,
846                operation: "type does not implement Parse",
847            });
848        };
849        match unsafe { (parse_fn)(s, frame.data) } {
850            Ok(_res) => {
851                unsafe {
852                    frame.mark_fully_initialized();
853                }
854
855                // mark the field as initialized
856                self.mark_field_as_initialized(shape, index)?;
857
858                Ok(self)
859            }
860            Err(_) => Err(ReflectError::OperationFailed {
861                shape,
862                operation: "parsing",
863            }),
864        }
865    }
866
867    /// Puts the default value in the currrent frame.
868    pub fn put_default(mut self) -> Result<Self, ReflectError> {
869        let Some(frame) = self.frames.last_mut() else {
870            return Err(ReflectError::OperationFailed {
871                shape: <()>::SHAPE,
872                operation: "tried to put default value but there was no frame",
873            });
874        };
875
876        let vtable = frame.shape.vtable;
877
878        let Some(default_in_place) = vtable.default_in_place else {
879            return Err(ReflectError::OperationFailed {
880                shape: frame.shape,
881                operation: "type does not implement Default",
882            });
883        };
884        unsafe {
885            default_in_place(frame.data);
886            frame.mark_fully_initialized();
887        }
888
889        let shape = frame.shape;
890        let index = frame.field_index_in_parent;
891
892        // mark the field as initialized
893        self.mark_field_as_initialized(shape, index)?;
894
895        Ok(self)
896    }
897
898    /// Marks a field as initialized in the parent frame.
899    fn mark_field_as_initialized(
900        &mut self,
901        shape: &'static Shape,
902        index: Option<usize>,
903    ) -> Result<(), ReflectError> {
904        if let Some(index) = index {
905            let parent_index = self.frames.len().saturating_sub(2);
906            let num_frames = self.frames.len();
907            let Some(parent) = self.frames.get_mut(parent_index) else {
908                return Err(ReflectError::OperationFailed {
909                    shape,
910                    operation: "was supposed to mark a field as initialized, but there was no parent frame",
911                });
912            };
913            let parent_shape = parent.shape;
914            trace!(
915                "[{}] {}.{} initialized with {}",
916                num_frames,
917                parent_shape.blue(),
918                index.yellow(),
919                shape.green()
920            );
921
922            if matches!(parent.shape.def, Def::Enum(_)) && parent.istate.variant.is_none() {
923                return Err(ReflectError::OperationFailed {
924                    shape,
925                    operation: "was supposed to mark a field as initialized, but the parent frame was an enum and didn't have a variant chosen",
926                });
927            }
928
929            if parent.istate.fields.has(index) {
930                return Err(ReflectError::OperationFailed {
931                    shape,
932                    operation: "was supposed to mark a field as initialized, but the parent frame already had it marked as initialized",
933                });
934            }
935
936            parent.istate.fields.set(index);
937        }
938        Ok(())
939    }
940
941    /// Returns the shape of the element type for a list/array
942    pub fn element_shape(&self) -> Result<&'static Shape, ReflectError> {
943        let frame = self.frames.last().unwrap();
944        let shape = frame.shape;
945
946        match shape.def {
947            Def::List(list_def) => Ok(list_def.t()),
948            _ => Err(ReflectError::WasNotA {
949                expected: "list or array",
950                actual: shape,
951            }),
952        }
953    }
954
955    /// Returns the shape of the key type for a map
956    pub fn key_shape(&self) -> Result<&'static Shape, ReflectError> {
957        let frame = self.frames.last().unwrap();
958        let shape = frame.shape;
959
960        match shape.def {
961            Def::Map(map_def) => Ok(map_def.k),
962            _ => Err(ReflectError::WasNotA {
963                expected: "map",
964                actual: shape,
965            }),
966        }
967    }
968
969    /// Creates an empty list without pushing any elements
970    pub fn put_empty_list(mut self) -> Result<Self, ReflectError> {
971        let Some(frame) = self.frames.last_mut() else {
972            return Err(ReflectError::OperationFailed {
973                shape: <()>::SHAPE,
974                operation: "tried to create empty list but there was no frame",
975            });
976        };
977
978        if !matches!(frame.shape.def, Def::List(_)) {
979            return Err(ReflectError::WasNotA {
980                expected: "list or array",
981                actual: frame.shape,
982            });
983        }
984
985        let vtable = frame.shape.vtable;
986
987        // Initialize an empty list
988        let Some(default_in_place) = vtable.default_in_place else {
989            return Err(ReflectError::OperationFailed {
990                shape: frame.shape,
991                operation: "list type does not implement Default",
992            });
993        };
994
995        unsafe {
996            default_in_place(frame.data);
997            frame.mark_fully_initialized();
998        }
999
1000        let shape = frame.shape;
1001        let index = frame.field_index_in_parent;
1002
1003        // Mark the field as initialized
1004        self.mark_field_as_initialized(shape, index)?;
1005
1006        Ok(self)
1007    }
1008
1009    /// Creates an empty map without pushing any entries
1010    pub fn put_empty_map(mut self) -> Result<Self, ReflectError> {
1011        let Some(frame) = self.frames.last_mut() else {
1012            return Err(ReflectError::OperationFailed {
1013                shape: <()>::SHAPE,
1014                operation: "tried to create empty map but there was no frame",
1015            });
1016        };
1017
1018        if !matches!(frame.shape.def, Def::Map(_)) {
1019            return Err(ReflectError::WasNotA {
1020                expected: "map or hash map",
1021                actual: frame.shape,
1022            });
1023        }
1024
1025        let vtable = frame.shape.vtable;
1026
1027        // Initialize an empty map
1028        let Some(default_in_place) = vtable.default_in_place else {
1029            return Err(ReflectError::OperationFailed {
1030                shape: frame.shape,
1031                operation: "map type does not implement Default",
1032            });
1033        };
1034
1035        unsafe {
1036            default_in_place(frame.data);
1037            frame.mark_fully_initialized();
1038        }
1039
1040        let shape = frame.shape;
1041        let index = frame.field_index_in_parent;
1042
1043        // Mark the field as initialized
1044        self.mark_field_as_initialized(shape, index)?;
1045
1046        Ok(self)
1047    }
1048
1049    /// Begins pushback mode for a list/array, allowing elements to be added one by one
1050    pub fn begin_pushback(mut self) -> Result<Self, ReflectError> {
1051        let Some(frame) = self.frames.last_mut() else {
1052            return Err(ReflectError::OperationFailed {
1053                shape: <()>::SHAPE,
1054                operation: "tried to begin pushback but there was no frame",
1055            });
1056        };
1057
1058        if !matches!(frame.shape.def, Def::List(_)) {
1059            return Err(ReflectError::WasNotA {
1060                expected: "list or array",
1061                actual: frame.shape,
1062            });
1063        }
1064
1065        let vtable = frame.shape.vtable;
1066
1067        // Initialize an empty list if it's not already initialized
1068        if !frame.istate.fields.has(0) {
1069            let Some(default_in_place) = vtable.default_in_place else {
1070                return Err(ReflectError::OperationFailed {
1071                    shape: frame.shape,
1072                    operation: "list type does not implement Default",
1073                });
1074            };
1075
1076            unsafe {
1077                default_in_place(frame.data);
1078                frame.istate.fields.set(0);
1079            }
1080        }
1081
1082        Ok(self)
1083    }
1084
1085    /// Begins insertion mode for a map, allowing key-value pairs to be added one by one
1086    pub fn begin_map_insert(mut self) -> Result<Self, ReflectError> {
1087        let Some(frame) = self.frames.last_mut() else {
1088            return Err(ReflectError::OperationFailed {
1089                shape: <()>::SHAPE,
1090                operation: "tried to begin map insertion but there was no frame",
1091            });
1092        };
1093
1094        if !matches!(frame.shape.def, Def::Map(_)) {
1095            return Err(ReflectError::WasNotA {
1096                expected: "map or hash map",
1097                actual: frame.shape,
1098            });
1099        }
1100
1101        let vtable = frame.shape.vtable;
1102
1103        // Initialize an empty map if it's not already initialized
1104        if !frame.istate.fields.has(0) {
1105            let Some(default_in_place) = vtable.default_in_place else {
1106                return Err(ReflectError::OperationFailed {
1107                    shape: frame.shape,
1108                    operation: "map type does not implement Default",
1109                });
1110            };
1111
1112            unsafe {
1113                default_in_place(frame.data);
1114                frame.istate.fields.set(0);
1115            }
1116        }
1117
1118        Ok(self)
1119    }
1120
1121    /// Pushes a new element onto the list/array
1122    ///
1123    /// This creates a new frame for the element. When this frame is popped,
1124    /// the element will be added to the list.
1125    pub fn push(mut self) -> Result<Self, ReflectError> {
1126        // Make sure we're initializing a list
1127        let frame = self.frames.last().unwrap();
1128        let list_shape = frame.shape;
1129
1130        if !matches!(list_shape.def, Def::List(_)) {
1131            return Err(ReflectError::WasNotA {
1132                expected: "list or array",
1133                actual: list_shape,
1134            });
1135        }
1136
1137        // If the list isn't initialized yet, initialize it
1138        if !frame.istate.fields.has(0) {
1139            self = self.begin_pushback()?;
1140        }
1141
1142        // Get the element type
1143        let element_shape = self.element_shape()?;
1144
1145        // Allocate memory for the element
1146        let element_data = element_shape.allocate();
1147
1148        // Create a new frame for the element
1149        let mut element_frame = Frame {
1150            data: element_data,
1151            shape: element_shape,
1152            field_index_in_parent: None, // No need for an index since we're using mode
1153            istate: IState::new(
1154                self.frames.len(),
1155                FrameMode::ListElement,
1156                FrameFlags::ALLOCATED,
1157            ),
1158        };
1159
1160        trace!(
1161            "[{}] Pushing element of type {} to list {}",
1162            self.frames.len(),
1163            element_shape.green(),
1164            list_shape.blue(),
1165        );
1166
1167        if let Some(iset) = self.istates.remove(&element_frame.id()) {
1168            trace!(
1169                "[{}] Restoring saved state for {}",
1170                self.frames.len(),
1171                element_frame.id().shape.blue()
1172            );
1173            element_frame.istate = iset;
1174        }
1175
1176        self.frames.push(element_frame);
1177        Ok(self)
1178    }
1179
1180    /// Prepare to push an option
1181    pub fn push_some(mut self) -> Result<Self, ReflectError> {
1182        // Make sure we're initializing an option
1183        let frame = self.frames.last().unwrap();
1184        let option_shape = frame.shape;
1185
1186        if !matches!(option_shape.def, Def::Option(_)) {
1187            return Err(ReflectError::WasNotA {
1188                expected: "option",
1189                actual: option_shape,
1190            });
1191        }
1192
1193        // Get the option definition
1194        let Def::Option(option_def) = option_shape.def else {
1195            unreachable!()
1196        };
1197
1198        // Get the inner type of the option
1199        let inner_shape = option_def.t();
1200
1201        // Allocate memory for the inner value
1202        let inner_data = inner_shape.allocate();
1203
1204        // Create a new frame for the inner value
1205        let mut inner_frame = Frame {
1206            data: inner_data,
1207            shape: inner_shape,
1208            // this is only set when we pop
1209            field_index_in_parent: None,
1210            istate: IState::new(
1211                self.frames.len(),
1212                FrameMode::OptionSome,
1213                // TODO: we could lazy-allocate it when something like `field` is called, tbh
1214                FrameFlags::ALLOCATED,
1215            ),
1216        };
1217
1218        trace!(
1219            "[{}] Pushing option frame for {}",
1220            self.frames.len(),
1221            option_shape.blue(),
1222        );
1223
1224        if let Some(iset) = self.istates.remove(&inner_frame.id()) {
1225            trace!(
1226                "[{}] Restoring saved state for {}",
1227                self.frames.len(),
1228                inner_frame.id().shape.blue()
1229            );
1230            inner_frame.istate = iset;
1231        }
1232
1233        self.frames.push(inner_frame);
1234        Ok(self)
1235    }
1236
1237    /// Pops a not-yet-initialized option frame, setting it to None in the parent
1238    ///
1239    /// This is used to set an option to None instead of Some.
1240    /// Steps:
1241    ///  1. Asserts the option frame is NOT initialized
1242    ///  2. Frees the memory for the pushed value
1243    ///  3. Pops the frame
1244    ///  4. Sets the parent option to its default value (i.e., None)
1245    ///  5. Pops the parent option (which is the actual `Option<T>`, but no longer in option mode)
1246    pub fn pop_some_push_none(mut self) -> Result<Self, ReflectError> {
1247        // 1. Option frame must exist
1248        let Some(frame) = self.frames.last_mut() else {
1249            return Err(ReflectError::OperationFailed {
1250                shape: <()>::SHAPE,
1251                operation: "tried to pop_some_push_none but there was no frame",
1252            });
1253        };
1254
1255        // 1. Make sure the current frame is an option inner frame in "Option" mode
1256        if frame.istate.mode != FrameMode::OptionSome {
1257            return Err(ReflectError::OperationFailed {
1258                shape: frame.shape,
1259                operation: "pop_some_push_none called, but frame was not in Option mode",
1260            });
1261        }
1262
1263        // 1. Check not initialized
1264        if frame.is_fully_initialized() {
1265            return Err(ReflectError::OperationFailed {
1266                shape: frame.shape,
1267                operation: "option frame already initialized, cannot pop_some_push_none",
1268            });
1269        }
1270
1271        frame.dealloc_if_needed();
1272
1273        // 3. Pop the frame (this discards, doesn't propagate up)
1274        let _frame = self.frames.pop().expect("frame already checked");
1275
1276        // 4. Set parent option (which we just popped into) to default (None)
1277        let parent_frame = self
1278            .frames
1279            .last_mut()
1280            .ok_or(ReflectError::OperationFailed {
1281                shape: <()>::SHAPE,
1282                operation: "tried to pop_some_push_none but there was no parent frame",
1283            })?;
1284
1285        // Safety: option frames are correctly sized, and data is valid
1286        unsafe {
1287            if let Some(default_fn) = parent_frame.shape.vtable.default_in_place {
1288                default_fn(parent_frame.data);
1289            } else {
1290                return Err(ReflectError::OperationFailed {
1291                    shape: parent_frame.shape,
1292                    operation: "option type does not implement Default",
1293                });
1294            }
1295            parent_frame.mark_fully_initialized();
1296        }
1297
1298        let Def::Option(od) = parent_frame.shape.def else {
1299            return Err(ReflectError::OperationFailed {
1300                shape: parent_frame.shape,
1301                operation: "pop_some_push_none and the parent isn't of type Option???",
1302            });
1303        };
1304
1305        // Now push a `None` frame
1306        let data = parent_frame.data;
1307
1308        let mut frame = Frame {
1309            data,
1310            shape: od.t(),
1311            field_index_in_parent: Some(0),
1312            istate: IState::new(self.frames.len(), FrameMode::OptionNone, FrameFlags::EMPTY),
1313        };
1314        unsafe {
1315            frame.mark_fully_initialized();
1316        }
1317
1318        self.frames.push(frame);
1319
1320        Ok(self)
1321    }
1322
1323    /// Pushes a new key frame for a map entry
1324    ///
1325    /// This creates a new frame for the key. After setting the key value,
1326    /// call `push_map_value` to create a frame for the corresponding value.
1327    pub fn push_map_key(mut self) -> Result<Self, ReflectError> {
1328        // Make sure we're initializing a map
1329        let frame = self.frames.last().unwrap();
1330        let map_shape = frame.shape;
1331
1332        if !matches!(map_shape.def, Def::Map(_)) {
1333            return Err(ReflectError::WasNotA {
1334                expected: "map or hash map",
1335                actual: map_shape,
1336            });
1337        }
1338
1339        // If the map isn't initialized yet, initialize it
1340        if !frame.istate.fields.has(0) {
1341            self = self.begin_map_insert()?;
1342        }
1343
1344        // Get the key type
1345        let key_shape = self.key_shape()?;
1346
1347        // Allocate memory for the key
1348        let key_data = key_shape.allocate();
1349
1350        // Create a new frame for the key
1351        let mut key_frame = Frame {
1352            data: key_data,
1353            shape: key_shape,
1354            field_index_in_parent: None,
1355            istate: IState::new(self.frames.len(), FrameMode::MapKey, FrameFlags::ALLOCATED),
1356        };
1357
1358        trace!(
1359            "[{}] Pushing key of type {} for map {}",
1360            self.frames.len(),
1361            key_shape.green(),
1362            map_shape.blue(),
1363        );
1364
1365        if let Some(iset) = self.istates.remove(&key_frame.id()) {
1366            trace!(
1367                "[{}] Restoring saved state for {}",
1368                self.frames.len(),
1369                key_frame.id().shape.blue()
1370            );
1371            key_frame.istate = iset;
1372        }
1373
1374        self.frames.push(key_frame);
1375        Ok(self)
1376    }
1377
1378    /// Pushes a new value frame for a map entry
1379    ///
1380    /// This should be called after pushing and initializing a key frame.
1381    /// When the value frame is popped, the key-value pair will be added to the map.
1382    pub fn push_map_value(mut self) -> Result<Self, ReflectError> {
1383        trace!("Wants to push map value. Frames = ");
1384        for (i, f) in self.frames.iter().enumerate() {
1385            trace!("Frame {}: {:?}", i, f);
1386        }
1387
1388        // First, ensure we have a valid key frame
1389        if self.frames.len() < 2 {
1390            return Err(ReflectError::OperationFailed {
1391                shape: <()>::SHAPE,
1392                operation: "tried to push map value but there was no key frame",
1393            });
1394        }
1395
1396        // Check the frame before the last to ensure it's a map key
1397        let key_frame_index = self.frames.len() - 1;
1398        let key_frame = &self.frames[key_frame_index];
1399
1400        // Verify the current frame is a key frame
1401        match key_frame.istate.mode {
1402            FrameMode::MapKey => {} // Valid - continue
1403            _ => {
1404                return Err(ReflectError::OperationFailed {
1405                    shape: key_frame.shape,
1406                    operation: "current frame is not a map key",
1407                });
1408            }
1409        }
1410
1411        // Check that the key is fully initialized
1412        if !key_frame.is_fully_initialized() {
1413            return Err(ReflectError::OperationFailed {
1414                shape: key_frame.shape,
1415                operation: "map key is not fully initialized",
1416            });
1417        }
1418
1419        // Get the parent map frame to verify we're working with a map
1420        let map_frame_index = self.frames.len() - 2;
1421        let map_frame = &self.frames[map_frame_index];
1422        let map_shape = map_frame.shape;
1423
1424        let Def::Map(map_def) = map_shape.def else {
1425            return Err(ReflectError::WasNotA {
1426                expected: "map",
1427                actual: map_frame.shape,
1428            });
1429        };
1430
1431        let value_shape = map_def.v;
1432
1433        // Allocate memory for the value
1434        let value_data = value_shape.allocate();
1435
1436        // Create a new frame for the value
1437        let mut value_frame = Frame {
1438            data: value_data,
1439            shape: value_shape,
1440            field_index_in_parent: None,
1441            istate: IState::new(
1442                self.frames.len(),
1443                FrameMode::MapValue {
1444                    index: key_frame_index,
1445                },
1446                FrameFlags::ALLOCATED,
1447            ),
1448        };
1449
1450        trace!(
1451            "[{}] Pushing value of type {} for map {} with key type {}",
1452            self.frames.len(),
1453            value_shape.green(),
1454            map_shape.blue(),
1455            key_frame.shape.yellow(),
1456        );
1457
1458        if let Some(iset) = self.istates.remove(&value_frame.id()) {
1459            trace!(
1460                "[{}] Restoring saved state for {}",
1461                self.frames.len(),
1462                value_frame.id().shape.blue()
1463            );
1464            value_frame.istate = iset;
1465        }
1466
1467        self.frames.push(value_frame);
1468        Ok(self)
1469    }
1470
1471    /// Pops the current frame — goes back up one level
1472    pub fn pop(mut self) -> Result<Self, ReflectError> {
1473        let Some(frame) = self.pop_inner() else {
1474            return Err(ReflectError::InvariantViolation {
1475                invariant: "No frame to pop",
1476            });
1477        };
1478        self.track(frame);
1479        Ok(self)
1480    }
1481
1482    fn pop_inner(&mut self) -> Option<Frame> {
1483        let mut frame = self.frames.pop()?;
1484        let frame_shape = frame.shape;
1485
1486        let init = frame.is_fully_initialized();
1487        trace!(
1488            "[{}] {} popped, {} initialized",
1489            self.frames.len(),
1490            frame_shape.blue(),
1491            if init {
1492                "✅ fully".green()
1493            } else {
1494                "🚧 partially".red()
1495            }
1496        );
1497        if init {
1498            if let Some(parent) = self.frames.last_mut() {
1499                if let Some(index) = frame.field_index_in_parent {
1500                    parent.istate.fields.set(index);
1501                }
1502            }
1503        }
1504
1505        // Handle special frame modes
1506        match frame.istate.mode {
1507            // Handle list element frames
1508            FrameMode::ListElement => {
1509                if frame.is_fully_initialized() {
1510                    // This was a list element, so we need to push it to the parent list
1511                    // Capture frame length and parent shape before mutable borrow
1512                    let frame_len = self.frames.len();
1513
1514                    // Get parent frame
1515                    let parent_frame = self.frames.last_mut().unwrap();
1516                    let parent_shape = parent_frame.shape;
1517
1518                    // Make sure the parent is a list
1519                    match parent_shape.def {
1520                        Def::List(_) => {
1521                            // Get the list vtable from the ListDef
1522                            if let Def::List(list_def) = parent_shape.def {
1523                                let list_vtable = list_def.vtable;
1524                                trace!(
1525                                    "[{}] Pushing element to list {}",
1526                                    frame_len,
1527                                    parent_shape.blue()
1528                                );
1529                                unsafe {
1530                                    // Convert the frame data pointer to Opaque and call push function from vtable
1531                                    (list_vtable.push)(
1532                                        PtrMut::new(parent_frame.data.as_mut_byte_ptr()),
1533                                        PtrMut::new(frame.data.as_mut_byte_ptr()),
1534                                    );
1535                                    frame.mark_moved_out_of();
1536                                }
1537                            } else {
1538                                panic!("parent frame is not a list type");
1539                            }
1540                        }
1541                        _ => {
1542                            panic!("Expected list or array, got {}", frame.shape);
1543                        }
1544                    }
1545                }
1546            }
1547
1548            // Handle map value frames
1549            FrameMode::MapValue {
1550                index: key_frame_index,
1551            } if frame.is_fully_initialized() => {
1552                // This was a map value, so we need to insert the key-value pair into the map
1553
1554                // Now let's remove the key frame from the frames array
1555                let mut key_frame = self.frames.remove(key_frame_index);
1556
1557                // Make sure the key is fully initialized
1558                if !key_frame.istate.fields.is_any_set() {
1559                    panic!("key is not initialized when popping value frame");
1560                }
1561
1562                // Get parent map frame
1563                let frame_len = self.frames.len();
1564                let parent_frame = self.frames.last_mut().unwrap();
1565                let parent_shape = parent_frame.shape;
1566
1567                // Make sure the parent is a map
1568                match parent_shape.def {
1569                    Def::Map(_) => {
1570                        // Get the map vtable from the MapDef
1571                        if let Def::Map(map_def) = parent_shape.def {
1572                            trace!(
1573                                "[{}] Inserting key-value pair into map {}",
1574                                frame_len,
1575                                parent_shape.blue()
1576                            );
1577                            unsafe {
1578                                // Call the map's insert function with the key and value
1579                                (map_def.vtable.insert_fn)(
1580                                    parent_frame.data.assume_init(),
1581                                    key_frame.data.assume_init(),
1582                                    PtrMut::new(frame.data.as_mut_byte_ptr()),
1583                                );
1584                                key_frame.mark_moved_out_of();
1585                                frame.mark_moved_out_of();
1586                            }
1587                        } else {
1588                            panic!("parent frame is not a map type");
1589                        }
1590                    }
1591                    _ => {
1592                        panic!("Expected map or hash map, got {}", frame.shape);
1593                    }
1594                }
1595            }
1596
1597            // Handle option frames
1598            FrameMode::OptionSome => {
1599                if frame.is_fully_initialized() {
1600                    trace!("Popping OptionSome (fully init'd)");
1601
1602                    // This was an option Some value, so we need to set it in the parent option
1603                    let frame_len = self.frames.len();
1604
1605                    // Get parent frame
1606                    let parent_frame = self.frames.last_mut().unwrap();
1607                    let parent_shape = parent_frame.shape;
1608
1609                    // Make sure the parent is an option
1610                    match parent_shape.def {
1611                        Def::Option(option_def) => {
1612                            trace!(
1613                                "[{}] Setting Some value in option {}",
1614                                frame_len,
1615                                parent_shape.blue()
1616                            );
1617                            unsafe {
1618                                // Call the option's init_some function
1619                                (option_def.vtable.init_some_fn)(
1620                                    parent_frame.data,
1621                                    PtrConst::new(frame.data.as_byte_ptr()),
1622                                );
1623                                trace!("Marking parent frame as fully initialized");
1624                                parent_frame.mark_fully_initialized();
1625
1626                                frame.mark_moved_out_of();
1627                            }
1628                        }
1629                        _ => {
1630                            panic!(
1631                                "Expected parent frame to be an option type, got {}",
1632                                frame.shape
1633                            );
1634                        }
1635                    }
1636                } else {
1637                    trace!("Popping OptionSome (not fully init'd)");
1638                }
1639            }
1640
1641            // Map keys are just tracked, they don't need special handling when popped
1642            // FIXME: that's not true, we need to deallocate them at least??
1643            FrameMode::MapKey => {}
1644
1645            // Normal frame
1646            FrameMode::Normal => {}
1647
1648            // Uninitialized special frames
1649            _ => {}
1650        }
1651
1652        Some(frame)
1653    }
1654
1655    /// Evict a frame from istates, along with all its children
1656    /// (because we're about to use `drop_in_place` on it — not
1657    /// yet though, we need to know the variant for enums, etc.)
1658    pub fn evict_tree(&mut self, frame: Frame) -> Frame {
1659        match frame.shape.def {
1660            Def::Struct(sd) => {
1661                for f in sd.fields {
1662                    let id = ValueId {
1663                        shape: f.shape(),
1664                        ptr: unsafe { frame.data.field_uninit_at(f.offset) }.as_byte_ptr(),
1665                    };
1666                    if let Some(istate) = self.istates.remove(&id) {
1667                        let frame = Frame::recompose(id, istate);
1668                        self.evict_tree(frame);
1669                    } else {
1670                        trace!("No istate found for field {}", f.name);
1671                    }
1672                }
1673            }
1674            Def::Enum(_ed) => {
1675                // Check if a variant is selected in the istate
1676                if let Some(variant) = &frame.istate.variant {
1677                    trace!(
1678                        "Evicting enum {} variant '{}' fields",
1679                        frame.shape.blue(),
1680                        variant.name.yellow()
1681                    );
1682                    // Iterate over the fields of the selected variant
1683                    for field in variant.data.fields {
1684                        // Calculate the pointer to the field within the enum's data payload
1685                        let field_ptr = unsafe { frame.data.field_uninit_at(field.offset) };
1686                        let field_shape = field.shape();
1687                        let field_id = ValueId::new(field_shape, field_ptr.as_byte_ptr());
1688
1689                        // Try to remove the field's state from istates
1690                        if let Some(field_istate) = self.istates.remove(&field_id) {
1691                            trace!(
1692                                "Evicting field '{}' (shape {}) of enum variant '{}'",
1693                                field.name.bright_blue(),
1694                                field_shape.green(),
1695                                variant.name.yellow()
1696                            );
1697                            // Recompose the frame for the field
1698                            let field_frame = Frame::recompose(field_id, field_istate);
1699                            // Recursively evict the field's subtree
1700                            self.evict_tree(field_frame);
1701                        } else {
1702                            trace!(
1703                                "Field '{}' (shape {}) of enum variant '{}' not found in istates, skipping eviction",
1704                                field.name.red(),
1705                                field_shape.red(),
1706                                variant.name.yellow()
1707                            );
1708                        }
1709                    }
1710                } else {
1711                    // No variant selected, nothing to evict within the enum
1712                    trace!(
1713                        "Enum {} has no variant selected, no fields to evict.",
1714                        frame.shape.blue()
1715                    );
1716                }
1717            }
1718            _ => {}
1719        }
1720        frame
1721    }
1722
1723    #[allow(rustdoc::broken_intra_doc_links)]
1724    /// Returns the current path in the JSON document as a string.
1725    /// For example: "$.users[0].name"
1726    pub fn path(&self) -> String {
1727        let mut path = String::from("$");
1728
1729        for (i, frame) in self.frames.iter().enumerate() {
1730            // Skip the root frame
1731            if i == 0 {
1732                continue;
1733            }
1734
1735            match frame.istate.mode {
1736                FrameMode::ListElement => {
1737                    // For arrays, we use bracket notation with index
1738                    if let Some(index) = frame.istate.list_index {
1739                        path.push_str(&format!("[{}]", index));
1740                    } else {
1741                        path.push_str("[?]");
1742                    }
1743                }
1744                FrameMode::MapKey => {
1745                    path.push_str(".key");
1746                }
1747                FrameMode::MapValue { index: _ } => {
1748                    path.push_str(".value");
1749                }
1750                FrameMode::OptionSome => {
1751                    path.push_str(".some");
1752                }
1753                FrameMode::OptionNone => {
1754                    path.push_str(".none");
1755                }
1756                FrameMode::Root => {
1757                    // Root doesn't add to the path
1758                }
1759                FrameMode::Normal => {
1760                    // For struct fields, we use dot notation with field name
1761                    if let Some(index) = frame.field_index_in_parent {
1762                        // Find the parent frame to get the field name
1763                        if let Some(parent) = self.frames.get(i - 1) {
1764                            if let Def::Struct(sd) = parent.shape.def {
1765                                if index < sd.fields.len() {
1766                                    let field_name = sd.fields[index].name;
1767                                    path.push('.');
1768                                    path.push_str(field_name);
1769                                }
1770                            } else if let Def::Enum(_) = parent.shape.def {
1771                                if let Some(variant) = &parent.istate.variant {
1772                                    if index < variant.data.fields.len() {
1773                                        let field_name = variant.data.fields[index].name;
1774                                        path.push('.');
1775                                        path.push_str(field_name);
1776                                    }
1777                                }
1778                            }
1779                        }
1780                    }
1781                }
1782            }
1783        }
1784
1785        path
1786    }
1787}
1788
1789impl Drop for Wip<'_> {
1790    fn drop(&mut self) {
1791        while let Some(frame) = self.frames.pop() {
1792            self.track(frame);
1793        }
1794        trace!("🧹 Whole WIP is dropping",);
1795
1796        let Some((root_id, _)) = self.istates.iter().find(|(_k, istate)| istate.depth == 0) else {
1797            trace!("No root found, we probably built already");
1798            return;
1799        };
1800
1801        let root_id = *root_id;
1802        let root_istate = self.istates.remove(&root_id).unwrap();
1803        let root = Frame::recompose(root_id, root_istate);
1804        let mut to_clean = vec![root];
1805
1806        let mut _root_guard: Option<Guard> = None;
1807
1808        while let Some(mut frame) = to_clean.pop() {
1809            trace!(
1810                "Cleaning frame: shape={} at {:p}, flags={:?}, mode={:?}, fully_initialized={}",
1811                frame.shape.blue(),
1812                frame.data.as_byte_ptr(),
1813                frame.istate.flags.bright_magenta(),
1814                frame.istate.mode.yellow(),
1815                if frame.is_fully_initialized() {
1816                    "✅".green()
1817                } else {
1818                    "❌".red()
1819                }
1820            );
1821
1822            if frame.istate.flags.contains(FrameFlags::MOVED) {
1823                trace!(
1824                    "{}",
1825                    "Frame was moved out of, nothing to dealloc/drop_in_place".yellow()
1826                );
1827                continue;
1828            }
1829
1830            match frame.shape.def {
1831                Def::Struct(sd) => {
1832                    if frame.is_fully_initialized() {
1833                        trace!(
1834                            "Dropping fully initialized struct: {} at {:p}",
1835                            frame.shape.green(),
1836                            frame.data.as_byte_ptr()
1837                        );
1838                        let frame = self.evict_tree(frame);
1839                        unsafe { frame.drop_and_dealloc_if_needed() };
1840                    } else {
1841                        let num_fields = sd.fields.len();
1842                        trace!(
1843                            "De-initializing struct {} at {:p} field-by-field ({} fields)",
1844                            frame.shape.yellow(),
1845                            frame.data.as_byte_ptr(),
1846                            num_fields.to_string().bright_cyan()
1847                        );
1848                        for i in 0..num_fields {
1849                            if frame.istate.fields.has(i) {
1850                                let field = sd.fields[i];
1851                                let field_shape = field.shape();
1852                                let field_ptr = unsafe { frame.data.field_init_at(field.offset) };
1853                                let field_id = ValueId::new(field_shape, field_ptr.as_byte_ptr());
1854                                trace!(
1855                                    "Recursively cleaning field #{} '{}' of {}: field_shape={}, field_ptr={:p}",
1856                                    i.to_string().bright_cyan(),
1857                                    field.name.bright_blue(),
1858                                    frame.shape.blue(),
1859                                    field_shape.green(),
1860                                    field_ptr.as_byte_ptr()
1861                                );
1862                                let istate = self.istates.remove(&field_id).unwrap();
1863                                let field_frame = Frame::recompose(field_id, istate);
1864                                to_clean.push(field_frame);
1865                            } else {
1866                                trace!(
1867                                    "Field #{} '{}' of {} was NOT initialized, skipping",
1868                                    i.to_string().bright_cyan(),
1869                                    sd.fields[i].name.bright_red(),
1870                                    frame.shape.red()
1871                                );
1872                            }
1873                        }
1874
1875                        // we'll also need to clean up if we're root
1876                        if frame.istate.mode == FrameMode::Root {
1877                            _root_guard = Some(Guard {
1878                                ptr: frame.data.as_mut_byte_ptr(),
1879                                layout: frame.shape.layout,
1880                            });
1881                        }
1882                    }
1883                }
1884                Def::Enum(_ed) => {
1885                    trace!(
1886                        "{}",
1887                        format!(
1888                            "TODO: handle enum deallocation for {} at {:p}",
1889                            frame.shape.yellow(),
1890                            frame.data.as_byte_ptr()
1891                        )
1892                        .magenta()
1893                    );
1894
1895                    // we'll also need to clean up if we're root
1896                    if frame.istate.mode == FrameMode::Root {
1897                        _root_guard = Some(Guard {
1898                            ptr: frame.data.as_mut_byte_ptr(),
1899                            layout: frame.shape.layout,
1900                        });
1901                    }
1902                }
1903                Def::Array(_)
1904                | Def::Slice(_)
1905                | Def::List(_)
1906                | Def::Map(_)
1907                | Def::SmartPointer(_)
1908                | Def::Scalar(_)
1909                | Def::Option(_) => {
1910                    trace!(
1911                        "Can drop all at once for shape {} (def variant: {:?}, frame mode {:?}) at {:p}",
1912                        frame.shape.cyan(),
1913                        frame.shape.def,
1914                        frame.istate.mode.yellow(),
1915                        frame.data.as_byte_ptr(),
1916                    );
1917
1918                    if frame.is_fully_initialized() {
1919                        unsafe { frame.drop_and_dealloc_if_needed() }
1920                    } else {
1921                        frame.dealloc_if_needed();
1922                    }
1923                }
1924                _ => {}
1925            }
1926        }
1927
1928        // We might have some frames left over to deallocate for temporary allocations for keymap insertion etc.
1929        let mut all_ids = self.istates.keys().copied().collect::<Vec<_>>();
1930        for frame_id in all_ids.drain(..) {
1931            let frame_istate = self.istates.remove(&frame_id).unwrap();
1932
1933            trace!(
1934                "Checking leftover istate: id.shape={} id.ptr={:p} mode={:?}",
1935                frame_id.shape.cyan(),
1936                frame_id.ptr,
1937                frame_istate.mode.yellow()
1938            );
1939            let mut frame = Frame::recompose(frame_id, frame_istate);
1940
1941            if frame.is_fully_initialized() {
1942                trace!("It's fully initialized, we can drop it");
1943                unsafe { frame.drop_and_dealloc_if_needed() };
1944            } else if frame.istate.flags.contains(FrameFlags::ALLOCATED) {
1945                trace!("Not initialized but allocated, let's free it");
1946                frame.dealloc_if_needed();
1947            }
1948        }
1949    }
1950}