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