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 owo_colors::OwoColorize;
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 current 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 the `Some(T)` variant of an `Option<T>`.
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        // Get the option definition
1187        let Def::Option(option_def) = option_shape.def else {
1188            return Err(ReflectError::WasNotA {
1189                expected: "option",
1190                actual: option_shape,
1191            });
1192        };
1193
1194        // Get the inner type of the option
1195        let inner_shape = option_def.t();
1196
1197        // Allocate memory for the inner value
1198        let inner_data = inner_shape.allocate();
1199
1200        // Create a new frame for the inner value
1201        let mut inner_frame = Frame {
1202            data: inner_data,
1203            shape: inner_shape,
1204            // this is only set when we pop
1205            field_index_in_parent: None,
1206            istate: IState::new(
1207                self.frames.len(),
1208                FrameMode::OptionSome,
1209                // TODO: we could lazy-allocate it when something like `field` is called, tbh
1210                FrameFlags::ALLOCATED,
1211            ),
1212        };
1213
1214        trace!(
1215            "[{}] Pushing option frame for {}",
1216            self.frames.len(),
1217            option_shape.blue(),
1218        );
1219
1220        if let Some(iset) = self.istates.remove(&inner_frame.id()) {
1221            trace!(
1222                "[{}] Restoring saved state for {}",
1223                self.frames.len(),
1224                inner_frame.id().shape.blue()
1225            );
1226            inner_frame.istate = iset;
1227        }
1228
1229        self.frames.push(inner_frame);
1230        Ok(self)
1231    }
1232
1233    /// Pops a not-yet-initialized option frame, setting it to None in the parent
1234    ///
1235    /// This is used to set an option to None instead of Some.
1236    /// Steps:
1237    ///  1. Asserts the option frame is NOT initialized
1238    ///  2. Frees the memory for the pushed value
1239    ///  3. Pops the frame
1240    ///  4. Sets the parent option to its default value (i.e., None)
1241    ///  5. Pops the parent option (which is the actual `Option<T>`, but no longer in option mode)
1242    pub fn pop_some_push_none(mut self) -> Result<Self, ReflectError> {
1243        // 1. Option frame must exist
1244        let Some(frame) = self.frames.last_mut() else {
1245            return Err(ReflectError::OperationFailed {
1246                shape: <()>::SHAPE,
1247                operation: "tried to pop_some_push_none but there was no frame",
1248            });
1249        };
1250
1251        // 1. Make sure the current frame is an option inner frame in "Option" mode
1252        if frame.istate.mode != FrameMode::OptionSome {
1253            return Err(ReflectError::OperationFailed {
1254                shape: frame.shape,
1255                operation: "pop_some_push_none called, but frame was not in Option mode",
1256            });
1257        }
1258
1259        // 1. Check not initialized
1260        if frame.is_fully_initialized() {
1261            return Err(ReflectError::OperationFailed {
1262                shape: frame.shape,
1263                operation: "option frame already initialized, cannot pop_some_push_none",
1264            });
1265        }
1266
1267        frame.dealloc_if_needed();
1268
1269        // 3. Pop the frame (this discards, doesn't propagate up)
1270        let _frame = self.frames.pop().expect("frame already checked");
1271
1272        // 4. Set parent option (which we just popped into) to default (None)
1273        let parent_frame = self
1274            .frames
1275            .last_mut()
1276            .ok_or(ReflectError::OperationFailed {
1277                shape: <()>::SHAPE,
1278                operation: "tried to pop_some_push_none but there was no parent frame",
1279            })?;
1280
1281        // Safety: option frames are correctly sized, and data is valid
1282        unsafe {
1283            if let Some(default_fn) = parent_frame.shape.vtable.default_in_place {
1284                default_fn(parent_frame.data);
1285            } else {
1286                return Err(ReflectError::OperationFailed {
1287                    shape: parent_frame.shape,
1288                    operation: "option type does not implement Default",
1289                });
1290            }
1291            parent_frame.mark_fully_initialized();
1292        }
1293
1294        let Def::Option(od) = parent_frame.shape.def else {
1295            return Err(ReflectError::OperationFailed {
1296                shape: parent_frame.shape,
1297                operation: "pop_some_push_none and the parent isn't of type Option???",
1298            });
1299        };
1300
1301        // Now push a `None` frame
1302        let data = parent_frame.data;
1303
1304        let mut frame = Frame {
1305            data,
1306            shape: od.t(),
1307            field_index_in_parent: Some(0),
1308            istate: IState::new(self.frames.len(), FrameMode::OptionNone, FrameFlags::EMPTY),
1309        };
1310        unsafe {
1311            frame.mark_fully_initialized();
1312        }
1313
1314        self.frames.push(frame);
1315
1316        Ok(self)
1317    }
1318
1319    /// Pushes a new key frame for a map entry
1320    ///
1321    /// This creates a new frame for the key. After setting the key value,
1322    /// call `push_map_value` to create a frame for the corresponding value.
1323    pub fn push_map_key(mut self) -> Result<Self, ReflectError> {
1324        // Make sure we're initializing a map
1325        let frame = self.frames.last().unwrap();
1326        let map_shape = frame.shape;
1327
1328        if !matches!(map_shape.def, Def::Map(_)) {
1329            return Err(ReflectError::WasNotA {
1330                expected: "map or hash map",
1331                actual: map_shape,
1332            });
1333        }
1334
1335        // If the map isn't initialized yet, initialize it
1336        if !frame.istate.fields.has(0) {
1337            self = self.begin_map_insert()?;
1338        }
1339
1340        // Get the key type
1341        let key_shape = self.key_shape()?;
1342
1343        // Allocate memory for the key
1344        let key_data = key_shape.allocate();
1345
1346        // Create a new frame for the key
1347        let mut key_frame = Frame {
1348            data: key_data,
1349            shape: key_shape,
1350            field_index_in_parent: None,
1351            istate: IState::new(self.frames.len(), FrameMode::MapKey, FrameFlags::ALLOCATED),
1352        };
1353
1354        trace!(
1355            "[{}] Pushing key of type {} for map {}",
1356            self.frames.len(),
1357            key_shape.green(),
1358            map_shape.blue(),
1359        );
1360
1361        if let Some(iset) = self.istates.remove(&key_frame.id()) {
1362            trace!(
1363                "[{}] Restoring saved state for {}",
1364                self.frames.len(),
1365                key_frame.id().shape.blue()
1366            );
1367            key_frame.istate = iset;
1368        }
1369
1370        self.frames.push(key_frame);
1371        Ok(self)
1372    }
1373
1374    /// Pushes a new value frame for a map entry
1375    ///
1376    /// This should be called after pushing and initializing a key frame.
1377    /// When the value frame is popped, the key-value pair will be added to the map.
1378    pub fn push_map_value(mut self) -> Result<Self, ReflectError> {
1379        trace!("Wants to push map value. Frames = ");
1380        for (i, f) in self.frames.iter().enumerate() {
1381            trace!("Frame {}: {:?}", i, f);
1382        }
1383
1384        // First, ensure we have a valid key frame
1385        if self.frames.len() < 2 {
1386            return Err(ReflectError::OperationFailed {
1387                shape: <()>::SHAPE,
1388                operation: "tried to push map value but there was no key frame",
1389            });
1390        }
1391
1392        // Check the frame before the last to ensure it's a map key
1393        let key_frame_index = self.frames.len() - 1;
1394        let key_frame = &self.frames[key_frame_index];
1395
1396        // Verify the current frame is a key frame
1397        match key_frame.istate.mode {
1398            FrameMode::MapKey => {} // Valid - continue
1399            _ => {
1400                return Err(ReflectError::OperationFailed {
1401                    shape: key_frame.shape,
1402                    operation: "current frame is not a map key",
1403                });
1404            }
1405        }
1406
1407        // Check that the key is fully initialized
1408        if !key_frame.is_fully_initialized() {
1409            return Err(ReflectError::OperationFailed {
1410                shape: key_frame.shape,
1411                operation: "map key is not fully initialized",
1412            });
1413        }
1414
1415        // Get the parent map frame to verify we're working with a map
1416        let map_frame_index = self.frames.len() - 2;
1417        let map_frame = &self.frames[map_frame_index];
1418        let map_shape = map_frame.shape;
1419
1420        let Def::Map(map_def) = map_shape.def else {
1421            return Err(ReflectError::WasNotA {
1422                expected: "map",
1423                actual: map_frame.shape,
1424            });
1425        };
1426
1427        let value_shape = map_def.v;
1428
1429        // Allocate memory for the value
1430        let value_data = value_shape.allocate();
1431
1432        // Create a new frame for the value
1433        let mut value_frame = Frame {
1434            data: value_data,
1435            shape: value_shape,
1436            field_index_in_parent: None,
1437            istate: IState::new(
1438                self.frames.len(),
1439                FrameMode::MapValue {
1440                    index: key_frame_index,
1441                },
1442                FrameFlags::ALLOCATED,
1443            ),
1444        };
1445
1446        trace!(
1447            "[{}] Pushing value of type {} for map {} with key type {}",
1448            self.frames.len(),
1449            value_shape.green(),
1450            map_shape.blue(),
1451            key_frame.shape.yellow(),
1452        );
1453
1454        if let Some(iset) = self.istates.remove(&value_frame.id()) {
1455            trace!(
1456                "[{}] Restoring saved state for {}",
1457                self.frames.len(),
1458                value_frame.id().shape.blue()
1459            );
1460            value_frame.istate = iset;
1461        }
1462
1463        self.frames.push(value_frame);
1464        Ok(self)
1465    }
1466
1467    /// Pops the current frame — goes back up one level
1468    pub fn pop(mut self) -> Result<Self, ReflectError> {
1469        let Some(frame) = self.pop_inner() else {
1470            return Err(ReflectError::InvariantViolation {
1471                invariant: "No frame to pop",
1472            });
1473        };
1474        self.track(frame);
1475        Ok(self)
1476    }
1477
1478    fn pop_inner(&mut self) -> Option<Frame> {
1479        let mut frame = self.frames.pop()?;
1480        let frame_shape = frame.shape;
1481
1482        let init = frame.is_fully_initialized();
1483        trace!(
1484            "[{}] {} popped, {} initialized",
1485            self.frames.len(),
1486            frame_shape.blue(),
1487            if init {
1488                "✅ fully".style(owo_colors::Style::new().green())
1489            } else {
1490                "🚧 partially".style(owo_colors::Style::new().red())
1491            }
1492        );
1493        if init {
1494            if let Some(parent) = self.frames.last_mut() {
1495                if let Some(index) = frame.field_index_in_parent {
1496                    parent.istate.fields.set(index);
1497                }
1498            }
1499        }
1500
1501        // Handle special frame modes
1502        match frame.istate.mode {
1503            // Handle list element frames
1504            FrameMode::ListElement => {
1505                if frame.is_fully_initialized() {
1506                    // This was a list element, so we need to push it to the parent list
1507                    // Capture frame length and parent shape before mutable borrow
1508                    let frame_len = self.frames.len();
1509
1510                    // Get parent frame
1511                    let parent_frame = self.frames.last_mut().unwrap();
1512                    let parent_shape = parent_frame.shape;
1513
1514                    // Make sure the parent is a list
1515                    match parent_shape.def {
1516                        Def::List(_) => {
1517                            // Get the list vtable from the ListDef
1518                            if let Def::List(list_def) = parent_shape.def {
1519                                let list_vtable = list_def.vtable;
1520                                trace!(
1521                                    "[{}] Pushing element to list {}",
1522                                    frame_len,
1523                                    parent_shape.blue()
1524                                );
1525                                unsafe {
1526                                    // Convert the frame data pointer to Opaque and call push function from vtable
1527                                    (list_vtable.push)(
1528                                        PtrMut::new(parent_frame.data.as_mut_byte_ptr()),
1529                                        PtrMut::new(frame.data.as_mut_byte_ptr()),
1530                                    );
1531                                    frame.mark_moved_out_of();
1532                                }
1533                            } else {
1534                                panic!("parent frame is not a list type");
1535                            }
1536                        }
1537                        _ => {
1538                            panic!("Expected list or array, got {}", frame.shape);
1539                        }
1540                    }
1541                }
1542            }
1543
1544            // Handle map value frames
1545            FrameMode::MapValue {
1546                index: key_frame_index,
1547            } if frame.is_fully_initialized() => {
1548                // This was a map value, so we need to insert the key-value pair into the map
1549
1550                // Now let's remove the key frame from the frames array
1551                let mut key_frame = self.frames.remove(key_frame_index);
1552
1553                // Make sure the key is fully initialized
1554                if !key_frame.istate.fields.is_any_set() {
1555                    panic!("key is not initialized when popping value frame");
1556                }
1557
1558                // Get parent map frame
1559                let frame_len = self.frames.len();
1560                let parent_frame = self.frames.last_mut().unwrap();
1561                let parent_shape = parent_frame.shape;
1562
1563                // Make sure the parent is a map
1564                match parent_shape.def {
1565                    Def::Map(_) => {
1566                        // Get the map vtable from the MapDef
1567                        if let Def::Map(map_def) = parent_shape.def {
1568                            trace!(
1569                                "[{}] Inserting key-value pair into map {}",
1570                                frame_len,
1571                                parent_shape.blue()
1572                            );
1573                            unsafe {
1574                                // Call the map's insert function with the key and value
1575                                (map_def.vtable.insert_fn)(
1576                                    parent_frame.data.assume_init(),
1577                                    key_frame.data.assume_init(),
1578                                    PtrMut::new(frame.data.as_mut_byte_ptr()),
1579                                );
1580                                key_frame.mark_moved_out_of();
1581                                frame.mark_moved_out_of();
1582                            }
1583                        } else {
1584                            panic!("parent frame is not a map type");
1585                        }
1586                    }
1587                    _ => {
1588                        panic!("Expected map or hash map, got {}", frame.shape);
1589                    }
1590                }
1591            }
1592
1593            // Handle option frames
1594            FrameMode::OptionSome => {
1595                if frame.is_fully_initialized() {
1596                    trace!("Popping OptionSome (fully init'd)");
1597
1598                    // This was an option Some value, so we need to set it in the parent option
1599                    let frame_len = self.frames.len();
1600
1601                    // Get parent frame
1602                    let parent_frame = self.frames.last_mut().unwrap();
1603                    let parent_shape = parent_frame.shape;
1604
1605                    // Make sure the parent is an option
1606                    match parent_shape.def {
1607                        Def::Option(option_def) => {
1608                            trace!(
1609                                "[{}] Setting Some value in option {}",
1610                                frame_len,
1611                                parent_shape.blue()
1612                            );
1613                            unsafe {
1614                                // Call the option's init_some function
1615                                (option_def.vtable.init_some_fn)(
1616                                    parent_frame.data,
1617                                    PtrConst::new(frame.data.as_byte_ptr()),
1618                                );
1619                                trace!("Marking parent frame as fully initialized");
1620                                parent_frame.mark_fully_initialized();
1621
1622                                frame.mark_moved_out_of();
1623                            }
1624                        }
1625                        _ => {
1626                            panic!(
1627                                "Expected parent frame to be an option type, got {}",
1628                                frame.shape
1629                            );
1630                        }
1631                    }
1632                } else {
1633                    trace!("Popping OptionSome (not fully init'd)");
1634                }
1635            }
1636
1637            // Map keys are just tracked, they don't need special handling when popped
1638            // FIXME: that's not true, we need to deallocate them at least??
1639            FrameMode::MapKey => {}
1640
1641            // Normal frame
1642            FrameMode::Normal => {}
1643
1644            // Uninitialized special frames
1645            _ => {}
1646        }
1647
1648        Some(frame)
1649    }
1650
1651    /// Evict a frame from istates, along with all its children
1652    /// (because we're about to use `drop_in_place` on it — not
1653    /// yet though, we need to know the variant for enums, etc.)
1654    pub fn evict_tree(&mut self, frame: Frame) -> Frame {
1655        match frame.shape.def {
1656            Def::Struct(sd) => {
1657                for f in sd.fields {
1658                    let id = ValueId {
1659                        shape: f.shape(),
1660                        ptr: unsafe { frame.data.field_uninit_at(f.offset) }.as_byte_ptr(),
1661                    };
1662                    if let Some(istate) = self.istates.remove(&id) {
1663                        let frame = Frame::recompose(id, istate);
1664                        self.evict_tree(frame);
1665                    } else {
1666                        trace!("No istate found for field {}", f.name);
1667                    }
1668                }
1669            }
1670            Def::Enum(_ed) => {
1671                // Check if a variant is selected in the istate
1672                if let Some(variant) = &frame.istate.variant {
1673                    trace!(
1674                        "Evicting enum {} variant '{}' fields",
1675                        frame.shape.blue(),
1676                        variant.name.yellow()
1677                    );
1678                    // Iterate over the fields of the selected variant
1679                    for field in variant.data.fields {
1680                        // Calculate the pointer to the field within the enum's data payload
1681                        let field_ptr = unsafe { frame.data.field_uninit_at(field.offset) };
1682                        let field_shape = field.shape();
1683                        let field_id = ValueId::new(field_shape, field_ptr.as_byte_ptr());
1684
1685                        // Try to remove the field's state from istates
1686                        if let Some(field_istate) = self.istates.remove(&field_id) {
1687                            trace!(
1688                                "Evicting field '{}' (shape {}) of enum variant '{}'",
1689                                field.name.bright_blue(),
1690                                field_shape.green(),
1691                                variant.name.yellow()
1692                            );
1693                            // Recompose the frame for the field
1694                            let field_frame = Frame::recompose(field_id, field_istate);
1695                            // Recursively evict the field's subtree
1696                            self.evict_tree(field_frame);
1697                        } else {
1698                            trace!(
1699                                "Field '{}' (shape {}) of enum variant '{}' not found in istates, skipping eviction",
1700                                field.name.red(),
1701                                field_shape.red(),
1702                                variant.name.yellow()
1703                            );
1704                        }
1705                    }
1706                } else {
1707                    // No variant selected, nothing to evict within the enum
1708                    trace!(
1709                        "Enum {} has no variant selected, no fields to evict.",
1710                        frame.shape.blue()
1711                    );
1712                }
1713            }
1714            _ => {}
1715        }
1716        frame
1717    }
1718
1719    #[allow(rustdoc::broken_intra_doc_links)]
1720    /// Returns the current path in the JSON document as a string.
1721    /// For example: "$.users[0].name"
1722    pub fn path(&self) -> String {
1723        let mut path = String::from("$");
1724
1725        for (i, frame) in self.frames.iter().enumerate() {
1726            // Skip the root frame
1727            if i == 0 {
1728                continue;
1729            }
1730
1731            match frame.istate.mode {
1732                FrameMode::ListElement => {
1733                    // For arrays, we use bracket notation with index
1734                    if let Some(index) = frame.istate.list_index {
1735                        path.push_str(&format!("[{}]", index));
1736                    } else {
1737                        path.push_str("[?]");
1738                    }
1739                }
1740                FrameMode::MapKey => {
1741                    path.push_str(".key");
1742                }
1743                FrameMode::MapValue { index: _ } => {
1744                    path.push_str(".value");
1745                }
1746                FrameMode::OptionSome => {
1747                    path.push_str(".some");
1748                }
1749                FrameMode::OptionNone => {
1750                    path.push_str(".none");
1751                }
1752                FrameMode::Root => {
1753                    // Root doesn't add to the path
1754                }
1755                FrameMode::Normal => {
1756                    // For struct fields, we use dot notation with field name
1757                    if let Some(index) = frame.field_index_in_parent {
1758                        // Find the parent frame to get the field name
1759                        if let Some(parent) = self.frames.get(i - 1) {
1760                            if let Def::Struct(sd) = parent.shape.def {
1761                                if index < sd.fields.len() {
1762                                    let field_name = sd.fields[index].name;
1763                                    path.push('.');
1764                                    path.push_str(field_name);
1765                                }
1766                            } else if let Def::Enum(_) = parent.shape.def {
1767                                if let Some(variant) = &parent.istate.variant {
1768                                    if index < variant.data.fields.len() {
1769                                        let field_name = variant.data.fields[index].name;
1770                                        path.push('.');
1771                                        path.push_str(field_name);
1772                                    }
1773                                }
1774                            }
1775                        }
1776                    }
1777                }
1778            }
1779        }
1780
1781        path
1782    }
1783}
1784
1785impl Drop for Wip<'_> {
1786    fn drop(&mut self) {
1787        while let Some(frame) = self.frames.pop() {
1788            self.track(frame);
1789        }
1790        trace!("🧹 Whole WIP is dropping",);
1791
1792        let Some((root_id, _)) = self.istates.iter().find(|(_k, istate)| istate.depth == 0) else {
1793            trace!("No root found, we probably built already");
1794            return;
1795        };
1796
1797        let root_id = *root_id;
1798        let root_istate = self.istates.remove(&root_id).unwrap();
1799        let root = Frame::recompose(root_id, root_istate);
1800        let mut to_clean = vec![root];
1801
1802        let mut _root_guard: Option<Guard> = None;
1803
1804        while let Some(mut frame) = to_clean.pop() {
1805            trace!(
1806                "Cleaning frame: shape={} at {:p}, flags={:?}, mode={:?}, fully_initialized={}",
1807                frame.shape.blue(),
1808                frame.data.as_byte_ptr(),
1809                frame.istate.flags.bright_magenta(),
1810                frame.istate.mode.yellow(),
1811                if frame.is_fully_initialized() {
1812                    "✅"
1813                } else {
1814                    "❌"
1815                }
1816            );
1817
1818            if frame.istate.flags.contains(FrameFlags::MOVED) {
1819                trace!(
1820                    "{}",
1821                    "Frame was moved out of, nothing to dealloc/drop_in_place".yellow()
1822                );
1823                continue;
1824            }
1825
1826            match frame.shape.def {
1827                Def::Struct(sd) => {
1828                    if frame.is_fully_initialized() {
1829                        trace!(
1830                            "Dropping fully initialized struct: {} at {:p}",
1831                            frame.shape.green(),
1832                            frame.data.as_byte_ptr()
1833                        );
1834                        let frame = self.evict_tree(frame);
1835                        unsafe { frame.drop_and_dealloc_if_needed() };
1836                    } else {
1837                        let num_fields = sd.fields.len();
1838                        trace!(
1839                            "De-initializing struct {} at {:p} field-by-field ({} fields)",
1840                            frame.shape.yellow(),
1841                            frame.data.as_byte_ptr(),
1842                            num_fields.to_string().bright_cyan()
1843                        );
1844                        for i in 0..num_fields {
1845                            if frame.istate.fields.has(i) {
1846                                let field = sd.fields[i];
1847                                let field_shape = field.shape();
1848                                let field_ptr = unsafe { frame.data.field_init_at(field.offset) };
1849                                let field_id = ValueId::new(field_shape, field_ptr.as_byte_ptr());
1850                                trace!(
1851                                    "Recursively cleaning field #{} '{}' of {}: field_shape={}, field_ptr={:p}",
1852                                    i.to_string().bright_cyan(),
1853                                    field.name.bright_blue(),
1854                                    frame.shape.blue(),
1855                                    field_shape.green(),
1856                                    field_ptr.as_byte_ptr()
1857                                );
1858                                let istate = self.istates.remove(&field_id).unwrap();
1859                                let field_frame = Frame::recompose(field_id, istate);
1860                                to_clean.push(field_frame);
1861                            } else {
1862                                trace!(
1863                                    "Field #{} '{}' of {} was NOT initialized, skipping",
1864                                    i.to_string().bright_cyan(),
1865                                    sd.fields[i].name.bright_red(),
1866                                    frame.shape.red()
1867                                );
1868                            }
1869                        }
1870
1871                        // we'll also need to clean up if we're root
1872                        if frame.istate.mode == FrameMode::Root {
1873                            _root_guard = Some(Guard {
1874                                ptr: frame.data.as_mut_byte_ptr(),
1875                                layout: frame.shape.layout,
1876                            });
1877                        }
1878                    }
1879                }
1880                Def::Enum(_ed) => {
1881                    trace!(
1882                        "{}",
1883                        format!(
1884                            "TODO: handle enum deallocation for {} at {:p}",
1885                            frame.shape.yellow(),
1886                            frame.data.as_byte_ptr()
1887                        )
1888                        .magenta()
1889                    );
1890
1891                    // we'll also need to clean up if we're root
1892                    if frame.istate.mode == FrameMode::Root {
1893                        _root_guard = Some(Guard {
1894                            ptr: frame.data.as_mut_byte_ptr(),
1895                            layout: frame.shape.layout,
1896                        });
1897                    }
1898                }
1899                Def::Array(_)
1900                | Def::Slice(_)
1901                | Def::List(_)
1902                | Def::Map(_)
1903                | Def::SmartPointer(_)
1904                | Def::Scalar(_)
1905                | Def::Option(_) => {
1906                    trace!(
1907                        "Can drop all at once for shape {} (def variant: {:?}, frame mode {:?}) at {:p}",
1908                        frame.shape.cyan(),
1909                        frame.shape.def,
1910                        frame.istate.mode.yellow(),
1911                        frame.data.as_byte_ptr(),
1912                    );
1913
1914                    if frame.is_fully_initialized() {
1915                        unsafe { frame.drop_and_dealloc_if_needed() }
1916                    } else {
1917                        frame.dealloc_if_needed();
1918                    }
1919                }
1920                _ => {}
1921            }
1922        }
1923
1924        // We might have some frames left over to deallocate for temporary allocations for keymap insertion etc.
1925        let mut all_ids = self.istates.keys().copied().collect::<Vec<_>>();
1926        for frame_id in all_ids.drain(..) {
1927            let frame_istate = self.istates.remove(&frame_id).unwrap();
1928
1929            trace!(
1930                "Checking leftover istate: id.shape={} id.ptr={:p} mode={:?}",
1931                frame_id.shape.cyan(),
1932                frame_id.ptr,
1933                frame_istate.mode.yellow()
1934            );
1935            let mut frame = Frame::recompose(frame_id, frame_istate);
1936
1937            if frame.is_fully_initialized() {
1938                trace!("It's fully initialized, we can drop it");
1939                unsafe { frame.drop_and_dealloc_if_needed() };
1940            } else if frame.istate.flags.contains(FrameFlags::ALLOCATED) {
1941                trace!("Not initialized but allocated, let's free it");
1942                frame.dealloc_if_needed();
1943            }
1944        }
1945    }
1946}