facet_reflect/partial/
partial_api.rs

1// This module contains the public-facing API for `Partial`
2
3use alloc::{
4    boxed::Box,
5    format,
6    string::{String, ToString},
7    vec::Vec,
8};
9
10use core::{marker::PhantomData, mem::ManuallyDrop, ptr::NonNull};
11
12use crate::{
13    Guard, HeapValue, Partial, Peek, ReflectError, TypedPartial,
14    partial::{Frame, FrameOwnership, MapInsertState, PartialState, Tracker, iset::ISet},
15    trace,
16};
17use facet_core::{
18    ArrayType, Characteristic, Def, EnumRepr, EnumType, Facet, Field, KnownPointer, PtrConst,
19    PtrMut, PtrUninit, SequenceType, Shape, StructType, Type, UserType, Variant,
20};
21
22////////////////////////////////////////////////////////////////////////////////////////////////////
23// Allocation, constructors etc.
24////////////////////////////////////////////////////////////////////////////////////////////////////
25impl<'facet> Partial<'facet> {
26    /// Allocates a new [TypedPartial] instance on the heap, with the given shape and type
27    pub fn alloc<T>() -> Result<TypedPartial<'facet, T>, ReflectError>
28    where
29        T: Facet<'facet> + ?Sized,
30    {
31        Ok(TypedPartial {
32            inner: Self::alloc_shape(T::SHAPE)?,
33            phantom: PhantomData,
34        })
35    }
36
37    /// Allocates a new [Partial] instance on the heap, with the given shape.
38    pub fn alloc_shape(shape: &'static Shape) -> Result<Self, ReflectError> {
39        crate::trace!(
40            "alloc_shape({:?}), with layout {:?}",
41            shape,
42            shape.layout.sized_layout()
43        );
44
45        let data = shape.allocate().map_err(|_| ReflectError::Unsized {
46            shape,
47            operation: "alloc_shape",
48        })?;
49
50        // Preallocate a couple of frames. The cost of allocating 4 frames is
51        // basically identical to allocating 1 frame, so for every type that
52        // has at least 1 level of nesting, this saves at least one guaranteed reallocation.
53        let mut frames = Vec::with_capacity(4);
54        frames.push(Frame::new(data, shape, FrameOwnership::Owned));
55
56        Ok(Self {
57            frames,
58            state: PartialState::Active,
59            invariant: PhantomData,
60        })
61    }
62}
63
64////////////////////////////////////////////////////////////////////////////////////////////////////
65// Misc.
66////////////////////////////////////////////////////////////////////////////////////////////////////
67impl<'facet> Partial<'facet> {
68    /// Returns the current frame count (depth of nesting)
69    ///
70    /// The initial frame count is 1 — `begin_field` would push a new frame,
71    /// bringing it to 2, then `end` would bring it back to `1`.
72    ///
73    /// This is an implementation detail of `Partial`, kinda, but deserializers
74    /// might use this for debug assertions, to make sure the state is what
75    /// they think it is.
76    #[inline]
77    pub fn frame_count(&self) -> usize {
78        self.frames.len()
79    }
80
81    /// Returns the shape of the current frame.
82    #[inline]
83    pub fn shape(&self) -> &'static Shape {
84        self.frames
85            .last()
86            .expect("Partial always has at least one frame")
87            .shape
88    }
89
90    /// Pops the current frame off the stack, indicating we're done initializing the current field
91    pub fn end(&mut self) -> Result<&mut Self, ReflectError> {
92        crate::trace!("end() called");
93        self.require_active()?;
94
95        // Special handling for SmartPointerSlice - convert builder to Arc
96        if self.frames.len() == 1 {
97            if let Tracker::SmartPointerSlice {
98                vtable,
99                building_item,
100            } = &self.frames[0].tracker
101            {
102                if *building_item {
103                    return Err(ReflectError::OperationFailed {
104                        shape: self.frames[0].shape,
105                        operation: "still building an item, finish it first",
106                    });
107                }
108
109                // Convert the builder to Arc<[T]>
110                let builder_ptr = unsafe { self.frames[0].data.assume_init() };
111                let arc_ptr = unsafe { (vtable.convert_fn)(builder_ptr) };
112
113                // Update the frame to store the Arc
114                self.frames[0].data = PtrUninit::new(unsafe {
115                    NonNull::new_unchecked(arc_ptr.as_byte_ptr() as *mut u8)
116                });
117                self.frames[0].tracker = Tracker::Init;
118                // The builder memory has been consumed by convert_fn, so we no longer own it
119                self.frames[0].ownership = FrameOwnership::ManagedElsewhere;
120
121                return Ok(self);
122            }
123        }
124
125        if self.frames.len() <= 1 {
126            // Never pop the last/root frame.
127            return Err(ReflectError::InvariantViolation {
128                invariant: "Partial::end() called with only one frame on the stack",
129            });
130        }
131
132        // Require that the top frame is fully initialized before popping.
133        {
134            let frame = self.frames.last().unwrap();
135            trace!(
136                "end(): Checking full initialization for frame with shape {} and tracker {:?}",
137                frame.shape,
138                frame.tracker.kind()
139            );
140            frame.require_full_initialization()?
141        }
142
143        // Pop the frame and save its data pointer for SmartPointer handling
144        let mut popped_frame = self.frames.pop().unwrap();
145
146        // Update parent frame's tracking when popping from a child
147        let parent_frame = self.frames.last_mut().unwrap();
148
149        trace!(
150            "end(): Popped {} (tracker {:?}), Parent {} (tracker {:?})",
151            popped_frame.shape,
152            popped_frame.tracker.kind(),
153            parent_frame.shape,
154            parent_frame.tracker.kind()
155        );
156
157        // Check if we need to do a conversion - this happens when:
158        // 1. The parent frame has an inner type that matches the popped frame's shape
159        // 2. The parent frame has try_from
160        // 3. The parent frame is not yet initialized
161        let needs_conversion = matches!(parent_frame.tracker, Tracker::Uninit)
162            && parent_frame.shape.inner.is_some()
163            && parent_frame.shape.inner.unwrap() == popped_frame.shape
164            && parent_frame.shape.vtable.try_from.is_some();
165
166        if needs_conversion {
167            trace!(
168                "Detected implicit conversion needed from {} to {}",
169                popped_frame.shape, parent_frame.shape
170            );
171            // Perform the conversion
172            if let Some(try_from_fn) = parent_frame.shape.vtable.try_from {
173                let inner_ptr = unsafe { popped_frame.data.assume_init().as_const() };
174                let inner_shape = popped_frame.shape;
175
176                trace!("Converting from {} to {}", inner_shape, parent_frame.shape);
177                let result = unsafe { try_from_fn(inner_ptr, inner_shape, parent_frame.data) };
178
179                if let Err(e) = result {
180                    trace!("Conversion failed: {e:?}");
181
182                    // Deallocate the inner value's memory since conversion failed
183                    if let FrameOwnership::Owned = popped_frame.ownership {
184                        if let Ok(layout) = popped_frame.shape.layout.sized_layout() {
185                            if layout.size() > 0 {
186                                trace!(
187                                    "Deallocating conversion frame memory after failure: size={}, align={}",
188                                    layout.size(),
189                                    layout.align()
190                                );
191                                unsafe {
192                                    alloc::alloc::dealloc(
193                                        popped_frame.data.as_mut_byte_ptr(),
194                                        layout,
195                                    );
196                                }
197                            }
198                        }
199                    }
200
201                    return Err(ReflectError::TryFromError {
202                        src_shape: inner_shape,
203                        dst_shape: parent_frame.shape,
204                        inner: e,
205                    });
206                }
207
208                trace!("Conversion succeeded, marking parent as initialized");
209                parent_frame.tracker = Tracker::Init;
210
211                // Deallocate the inner value's memory since try_from consumed it
212                if let FrameOwnership::Owned = popped_frame.ownership {
213                    if let Ok(layout) = popped_frame.shape.layout.sized_layout() {
214                        if layout.size() > 0 {
215                            trace!(
216                                "Deallocating conversion frame memory: size={}, align={}",
217                                layout.size(),
218                                layout.align()
219                            );
220                            unsafe {
221                                alloc::alloc::dealloc(popped_frame.data.as_mut_byte_ptr(), layout);
222                            }
223                        }
224                    }
225                }
226
227                return Ok(self);
228            }
229        }
230
231        match &mut parent_frame.tracker {
232            Tracker::Struct {
233                iset,
234                current_child,
235            } => {
236                if let Some(idx) = *current_child {
237                    iset.set(idx);
238                    *current_child = None;
239                }
240            }
241            Tracker::Array {
242                iset,
243                current_child,
244            } => {
245                if let Some(idx) = *current_child {
246                    iset.set(idx);
247                    *current_child = None;
248                }
249            }
250            Tracker::SmartPointer { is_initialized } => {
251                // We just popped the inner value frame, so now we need to create the smart pointer
252                if let Def::Pointer(smart_ptr_def) = parent_frame.shape.def {
253                    let Some(new_into_fn) = smart_ptr_def.vtable.new_into_fn else {
254                        return Err(ReflectError::OperationFailed {
255                            shape: parent_frame.shape,
256                            operation: "SmartPointer missing new_into_fn",
257                        });
258                    };
259
260                    // The child frame contained the inner value
261                    let inner_ptr = PtrMut::new(unsafe {
262                        NonNull::new_unchecked(popped_frame.data.as_mut_byte_ptr())
263                    });
264
265                    // Use new_into_fn to create the Box
266                    unsafe {
267                        new_into_fn(parent_frame.data, inner_ptr);
268                    }
269
270                    // We just moved out of it
271                    popped_frame.tracker = Tracker::Uninit;
272
273                    // Deallocate the inner value's memory since new_into_fn moved it
274                    popped_frame.dealloc();
275
276                    *is_initialized = true;
277                }
278            }
279            Tracker::Enum {
280                data,
281                current_child,
282                ..
283            } => {
284                if let Some(idx) = *current_child {
285                    data.set(idx);
286                    *current_child = None;
287                }
288            }
289            Tracker::List {
290                is_initialized: true,
291                current_child,
292            } => {
293                if *current_child {
294                    // We just popped an element frame, now push it to the list
295                    if let Def::List(list_def) = parent_frame.shape.def {
296                        let Some(push_fn) = list_def.vtable.push else {
297                            return Err(ReflectError::OperationFailed {
298                                shape: parent_frame.shape,
299                                operation: "List missing push function",
300                            });
301                        };
302
303                        // The child frame contained the element value
304                        let element_ptr = PtrMut::new(unsafe {
305                            NonNull::new_unchecked(popped_frame.data.as_mut_byte_ptr())
306                        });
307
308                        // Use push to add element to the list
309                        unsafe {
310                            push_fn(
311                                PtrMut::new(NonNull::new_unchecked(
312                                    parent_frame.data.as_mut_byte_ptr(),
313                                )),
314                                element_ptr,
315                            );
316                        }
317
318                        // Push moved out of popped_frame
319                        popped_frame.tracker = Tracker::Uninit;
320                        popped_frame.dealloc();
321
322                        *current_child = false;
323                    }
324                }
325            }
326            Tracker::Map {
327                is_initialized: true,
328                insert_state,
329            } => {
330                match insert_state {
331                    MapInsertState::PushingKey { key_ptr } => {
332                        // We just popped the key frame
333                        if let Some(key_ptr) = key_ptr {
334                            // Transition to PushingValue state
335                            *insert_state = MapInsertState::PushingValue {
336                                key_ptr: *key_ptr,
337                                value_ptr: None,
338                            };
339                        }
340                    }
341                    MapInsertState::PushingValue { key_ptr, value_ptr } => {
342                        // We just popped the value frame, now insert the pair
343                        if let (Some(value_ptr), Def::Map(map_def)) =
344                            (value_ptr, parent_frame.shape.def)
345                        {
346                            let insert_fn = map_def.vtable.insert_fn;
347
348                            // Use insert to add key-value pair to the map
349                            unsafe {
350                                insert_fn(
351                                    PtrMut::new(NonNull::new_unchecked(
352                                        parent_frame.data.as_mut_byte_ptr(),
353                                    )),
354                                    PtrMut::new(NonNull::new_unchecked(key_ptr.as_mut_byte_ptr())),
355                                    PtrMut::new(NonNull::new_unchecked(
356                                        value_ptr.as_mut_byte_ptr(),
357                                    )),
358                                );
359                            }
360
361                            // Note: We don't deallocate the key and value memory here.
362                            // The insert function has semantically moved the values into the map,
363                            // but we still need to deallocate the temporary buffers.
364                            // However, since we don't have frames for them anymore (they were popped),
365                            // we need to handle deallocation here.
366                            if let Ok(key_shape) = map_def.k().layout.sized_layout() {
367                                if key_shape.size() > 0 {
368                                    unsafe {
369                                        alloc::alloc::dealloc(key_ptr.as_mut_byte_ptr(), key_shape);
370                                    }
371                                }
372                            }
373                            if let Ok(value_shape) = map_def.v().layout.sized_layout() {
374                                if value_shape.size() > 0 {
375                                    unsafe {
376                                        alloc::alloc::dealloc(
377                                            value_ptr.as_mut_byte_ptr(),
378                                            value_shape,
379                                        );
380                                    }
381                                }
382                            }
383
384                            // Reset to idle state
385                            *insert_state = MapInsertState::Idle;
386                        }
387                    }
388                    MapInsertState::Idle => {
389                        // Nothing to do
390                    }
391                }
392            }
393            Tracker::Option { building_inner } => {
394                // We just popped the inner value frame for an Option's Some variant
395                if *building_inner {
396                    if let Def::Option(option_def) = parent_frame.shape.def {
397                        // Use the Option vtable to initialize Some(inner_value)
398                        let init_some_fn = option_def.vtable.init_some_fn;
399
400                        // The popped frame contains the inner value
401                        let inner_value_ptr = unsafe { popped_frame.data.assume_init().as_const() };
402
403                        // Initialize the Option as Some(inner_value)
404                        unsafe {
405                            init_some_fn(parent_frame.data, inner_value_ptr);
406                        }
407
408                        // Deallocate the inner value's memory since init_some_fn moved it
409                        if let FrameOwnership::Owned = popped_frame.ownership {
410                            if let Ok(layout) = popped_frame.shape.layout.sized_layout() {
411                                if layout.size() > 0 {
412                                    unsafe {
413                                        alloc::alloc::dealloc(
414                                            popped_frame.data.as_mut_byte_ptr(),
415                                            layout,
416                                        );
417                                    }
418                                }
419                            }
420                        }
421
422                        // Mark that we're no longer building the inner value
423                        *building_inner = false;
424                    } else {
425                        return Err(ReflectError::OperationFailed {
426                            shape: parent_frame.shape,
427                            operation: "Option frame without Option definition",
428                        });
429                    }
430                }
431            }
432            Tracker::Uninit | Tracker::Init => {
433                // the main case here is: the popped frame was a `String` and the
434                // parent frame is an `Arc<str>`, `Box<str>` etc.
435                match &parent_frame.shape.def {
436                    Def::Pointer(smart_ptr_def) => {
437                        let pointee =
438                            smart_ptr_def
439                                .pointee()
440                                .ok_or(ReflectError::InvariantViolation {
441                                    invariant: "pointer type doesn't have a pointee",
442                                })?;
443
444                        if !pointee.is_shape(str::SHAPE) {
445                            return Err(ReflectError::InvariantViolation {
446                                invariant: "only T=str is supported when building SmartPointer<T> and T is unsized",
447                            });
448                        }
449
450                        if !popped_frame.shape.is_shape(String::SHAPE) {
451                            return Err(ReflectError::InvariantViolation {
452                                invariant: "the popped frame should be String when building a SmartPointer<T>",
453                            });
454                        }
455
456                        popped_frame.require_full_initialization()?;
457
458                        // if the just-popped frame was a SmartPointerStr, we have some conversion to do:
459                        // Special-case: SmartPointer<str> (Box<str>, Arc<str>, Rc<str>) via SmartPointerStr tracker
460                        // Here, popped_frame actually contains a value for String that should be moved into the smart pointer.
461                        // We convert the String into Box<str>, Arc<str>, or Rc<str> as appropriate and write it to the parent frame.
462                        use alloc::{rc::Rc, string::String, sync::Arc};
463                        let parent_shape = parent_frame.shape;
464
465                        let Some(known) = smart_ptr_def.known else {
466                            return Err(ReflectError::OperationFailed {
467                                shape: parent_shape,
468                                operation: "SmartPointerStr for unknown smart pointer kind",
469                            });
470                        };
471
472                        parent_frame.deinit();
473
474                        // Interpret the memory as a String, then convert and write.
475                        let string_ptr = popped_frame.data.as_mut_byte_ptr() as *mut String;
476                        let string_value = unsafe { core::ptr::read(string_ptr) };
477
478                        match known {
479                            KnownPointer::Box => {
480                                let boxed: Box<str> = string_value.into_boxed_str();
481                                unsafe {
482                                    core::ptr::write(
483                                        parent_frame.data.as_mut_byte_ptr() as *mut Box<str>,
484                                        boxed,
485                                    );
486                                }
487                            }
488                            KnownPointer::Arc => {
489                                let arc: Arc<str> = Arc::from(string_value.into_boxed_str());
490                                unsafe {
491                                    core::ptr::write(
492                                        parent_frame.data.as_mut_byte_ptr() as *mut Arc<str>,
493                                        arc,
494                                    );
495                                }
496                            }
497                            KnownPointer::Rc => {
498                                let rc: Rc<str> = Rc::from(string_value.into_boxed_str());
499                                unsafe {
500                                    core::ptr::write(
501                                        parent_frame.data.as_mut_byte_ptr() as *mut Rc<str>,
502                                        rc,
503                                    );
504                                }
505                            }
506                            _ => {
507                                return Err(ReflectError::OperationFailed {
508                                    shape: parent_shape,
509                                    operation: "Don't know how to build this pointer type",
510                                });
511                            }
512                        }
513
514                        parent_frame.tracker = Tracker::Init;
515
516                        popped_frame.tracker = Tracker::Uninit;
517                        popped_frame.dealloc();
518                    }
519                    _ => {
520                        unreachable!(
521                            "we popped a frame and parent was Init or Uninit, but it wasn't a smart pointer and... there's no way this should happen normally"
522                        )
523                    }
524                }
525            }
526            Tracker::SmartPointerSlice {
527                vtable,
528                building_item,
529            } => {
530                if *building_item {
531                    // We just popped an element frame, now push it to the slice builder
532                    let element_ptr = PtrMut::new(unsafe {
533                        NonNull::new_unchecked(popped_frame.data.as_mut_byte_ptr())
534                    });
535
536                    // Use the slice builder's push_fn to add the element
537                    crate::trace!("Pushing element to slice builder");
538                    unsafe {
539                        let parent_ptr = parent_frame.data.assume_init();
540                        (vtable.push_fn)(parent_ptr, element_ptr);
541                    }
542
543                    popped_frame.tracker = Tracker::Uninit;
544                    popped_frame.dealloc();
545
546                    if let Tracker::SmartPointerSlice {
547                        building_item: bi, ..
548                    } = &mut parent_frame.tracker
549                    {
550                        *bi = false;
551                    }
552                }
553            }
554            _ => {}
555        }
556
557        Ok(self)
558    }
559
560    /// Returns a human-readable path representing the current traversal in the builder,
561    /// e.g., `RootStruct.fieldName[index].subfield`.
562    pub fn path(&self) -> String {
563        let mut out = String::new();
564
565        let mut path_components = Vec::new();
566        // The stack of enum/struct/sequence names currently in context.
567        // Start from root and build upwards.
568        for (i, frame) in self.frames.iter().enumerate() {
569            match frame.shape.ty {
570                Type::User(user_type) => match user_type {
571                    UserType::Struct(struct_type) => {
572                        // Try to get currently active field index
573                        let mut field_str = None;
574                        if let Tracker::Struct {
575                            current_child: Some(idx),
576                            ..
577                        } = &frame.tracker
578                        {
579                            if let Some(field) = struct_type.fields.get(*idx) {
580                                field_str = Some(field.name);
581                            }
582                        }
583                        if i == 0 {
584                            // Use Display for the root struct shape
585                            path_components.push(format!("{}", frame.shape));
586                        }
587                        if let Some(field_name) = field_str {
588                            path_components.push(format!(".{field_name}"));
589                        }
590                    }
591                    UserType::Enum(_enum_type) => {
592                        // Try to get currently active variant and field
593                        if let Tracker::Enum {
594                            variant,
595                            current_child,
596                            ..
597                        } = &frame.tracker
598                        {
599                            if i == 0 {
600                                // Use Display for the root enum shape
601                                path_components.push(format!("{}", frame.shape));
602                            }
603                            path_components.push(format!("::{}", variant.name));
604                            if let Some(idx) = *current_child {
605                                if let Some(field) = variant.data.fields.get(idx) {
606                                    path_components.push(format!(".{}", field.name));
607                                }
608                            }
609                        } else if i == 0 {
610                            // just the enum display
611                            path_components.push(format!("{}", frame.shape));
612                        }
613                    }
614                    UserType::Union(_union_type) => {
615                        path_components.push(format!("{}", frame.shape));
616                    }
617                    UserType::Opaque => {
618                        path_components.push("<opaque>".to_string());
619                    }
620                },
621                Type::Sequence(seq_type) => match seq_type {
622                    facet_core::SequenceType::Array(_array_def) => {
623                        // Try to show current element index
624                        if let Tracker::Array {
625                            current_child: Some(idx),
626                            ..
627                        } = &frame.tracker
628                        {
629                            path_components.push(format!("[{idx}]"));
630                        }
631                    }
632                    // You can add more for Slice, Vec, etc., if applicable
633                    _ => {
634                        // just indicate "[]" for sequence
635                        path_components.push("[]".to_string());
636                    }
637                },
638                Type::Pointer(_) => {
639                    // Indicate deref
640                    path_components.push("*".to_string());
641                }
642                _ => {
643                    // No structural path
644                }
645            }
646        }
647        // Merge the path_components into a single string
648        for component in path_components {
649            out.push_str(&component);
650        }
651        out
652    }
653}
654
655////////////////////////////////////////////////////////////////////////////////////////////////////
656// Build
657////////////////////////////////////////////////////////////////////////////////////////////////////
658impl<'facet> Partial<'facet> {
659    /// Builds the value
660    pub fn build(&mut self) -> Result<HeapValue<'facet>, ReflectError> {
661        self.require_active()?;
662        if self.frames.len() != 1 {
663            self.state = PartialState::BuildFailed;
664            return Err(ReflectError::InvariantViolation {
665                invariant: "Partial::build() expects a single frame — call end() until that's the case",
666            });
667        }
668
669        let frame = self.frames.pop().unwrap();
670
671        // Check initialization before proceeding
672        if let Err(e) = frame.require_full_initialization() {
673            // Put the frame back so Drop can handle cleanup properly
674            self.frames.push(frame);
675            self.state = PartialState::BuildFailed;
676            return Err(e);
677        }
678
679        // Check invariants if present
680        if let Some(invariants_fn) = frame.shape.vtable.invariants {
681            // Safety: The value is fully initialized at this point (we just checked with require_full_initialization)
682            let value_ptr = unsafe { frame.data.assume_init().as_const() };
683            let invariants_ok = unsafe { invariants_fn(value_ptr) };
684
685            if !invariants_ok {
686                // Put the frame back so Drop can handle cleanup properly
687                self.frames.push(frame);
688                self.state = PartialState::BuildFailed;
689                return Err(ReflectError::InvariantViolation {
690                    invariant: "Type invariants check failed",
691                });
692            }
693        }
694
695        // Mark as built to prevent reuse
696        self.state = PartialState::Built;
697
698        match frame
699            .shape
700            .layout
701            .sized_layout()
702            .map_err(|_layout_err| ReflectError::Unsized {
703                shape: frame.shape,
704                operation: "build (final check for sized layout)",
705            }) {
706            Ok(layout) => Ok(HeapValue {
707                guard: Some(Guard {
708                    ptr: unsafe { NonNull::new_unchecked(frame.data.as_mut_byte_ptr()) },
709                    layout,
710                }),
711                shape: frame.shape,
712                phantom: PhantomData,
713            }),
714            Err(e) => {
715                // Put the frame back for proper cleanup
716                self.frames.push(frame);
717                self.state = PartialState::BuildFailed;
718                Err(e)
719            }
720        }
721    }
722}
723
724////////////////////////////////////////////////////////////////////////////////////////////////////
725// `Set` and set helpers
726////////////////////////////////////////////////////////////////////////////////////////////////////
727impl<'facet> Partial<'facet> {
728    /// Sets a value wholesale into the current frame.
729    ///
730    /// If the current frame was already initialized, the previous value is
731    /// dropped. If it was partially initialized, the fields that were initialized
732    /// are dropped, etc.
733    pub fn set<U>(&mut self, value: U) -> Result<&mut Self, ReflectError>
734    where
735        U: Facet<'facet>,
736    {
737        self.require_active()?;
738        struct DropVal<U> {
739            ptr: *mut U,
740        }
741        impl<U> Drop for DropVal<U> {
742            #[inline]
743            fn drop(&mut self) {
744                unsafe { core::ptr::drop_in_place(self.ptr) };
745            }
746        }
747
748        let mut value = ManuallyDrop::new(value);
749        let drop = DropVal {
750            ptr: (&mut value) as *mut ManuallyDrop<U> as *mut U,
751        };
752
753        let ptr_const = PtrConst::new(unsafe { NonNull::new_unchecked(drop.ptr) });
754        unsafe {
755            // Safety: We are calling set_shape with a valid shape and a valid pointer
756            self.set_shape(ptr_const, U::SHAPE)?
757        };
758        core::mem::forget(drop);
759
760        Ok(self)
761    }
762
763    /// Sets a value into the current frame by [PtrConst] / [Shape].
764    ///
765    /// # Safety
766    ///
767    /// The caller must ensure that `src_value` points to a valid instance of a value
768    /// whose memory layout and type matches `src_shape`, and that this value can be
769    /// safely copied (bitwise) into the destination specified by the Partial's current frame.
770    ///
771    /// After a successful call, the ownership of the value at `src_value` is effectively moved
772    /// into the Partial (i.e., the destination), and the original value should not be used
773    /// or dropped by the caller; you should use `core::mem::forget` on the passed value.
774    ///
775    /// If an error is returned, the destination remains unmodified and safe for future operations.
776    #[inline]
777    pub unsafe fn set_shape(
778        &mut self,
779        src_value: PtrConst<'_>,
780        src_shape: &'static Shape,
781    ) -> Result<&mut Self, ReflectError> {
782        self.require_active()?;
783
784        let fr = self.frames.last_mut().unwrap();
785        crate::trace!("set_shape({src_shape:?})");
786
787        if !fr.shape.is_shape(src_shape) {
788            return Err(ReflectError::WrongShape {
789                expected: fr.shape,
790                actual: src_shape,
791            });
792        }
793
794        fr.deinit();
795
796        // SAFETY: `fr.shape` and `src_shape` are the same, so they have the same size,
797        // and the preconditions for this function are that `src_value` is fully intialized.
798        unsafe {
799            // unwrap safety: the only failure condition for copy_from is that shape is unsized,
800            // which is not possible for `Partial`
801            fr.data.copy_from(src_value, fr.shape).unwrap();
802        }
803
804        // SAFETY: if we reached this point, `fr.data` is correctly initialized
805        unsafe {
806            fr.mark_as_init();
807        }
808
809        Ok(self)
810    }
811
812    /// Sets the current frame using a function that initializes the value
813    ///
814    /// # Safety
815    ///
816    /// If `f` returns Ok(), it is assumed that it initialized the passed pointer fully and with a
817    /// value of the right type.
818    ///
819    /// If `f` returns Err(), it is assumed that it did NOT initialize the passed pointer and that
820    /// there is no need to drop it in place.
821    pub unsafe fn set_from_function<F>(&mut self, f: F) -> Result<&mut Self, ReflectError>
822    where
823        F: FnOnce(PtrUninit<'_>) -> Result<(), ReflectError>,
824    {
825        self.require_active()?;
826        let frame = self.frames.last_mut().unwrap();
827
828        frame.deinit();
829        f(frame.data)?;
830
831        // safety: `f()` returned Ok, so `frame.data` must be initialized
832        unsafe {
833            frame.mark_as_init();
834        }
835
836        Ok(self)
837    }
838
839    /// Sets the current frame to its default value using `default_in_place` from the
840    /// vtable.
841    ///
842    /// Note: if you have `struct S { field: F }`, and `F` does not implement `Default`
843    /// but `S` does, this doesn't magically uses S's `Default` implementation to get a value
844    /// for `field`.
845    ///
846    /// If the current frame's shape does not implement `Default`, then this returns an error.
847    #[inline]
848    pub fn set_default(&mut self) -> Result<&mut Self, ReflectError> {
849        let frame = self.frames.last().unwrap();
850
851        let Some(default_fn) = frame.shape.vtable.default_in_place else {
852            return Err(ReflectError::OperationFailed {
853                shape: frame.shape,
854                operation: "type does not implement Default",
855            });
856        };
857
858        // SAFETY: `default_fn` fully initializes the passed pointer. we took it
859        // from the vtable of `frame.shape`.
860        unsafe {
861            self.set_from_function(move |ptr| {
862                default_fn(ptr);
863                Ok(())
864            })
865        }
866    }
867
868    /// Copy a value from a Peek into the current frame.
869    ///
870    /// # Invariants
871    ///
872    /// `peek` must be a thin pointer, otherwise this panics.
873    ///
874    /// # Safety
875    ///
876    /// If this succeeds, the value `Peek` points to has been moved out of, and
877    /// as such, should not be dropped (but should be deallocated).
878    pub unsafe fn set_from_peek(&mut self, peek: &Peek<'_, '_>) -> Result<&mut Self, ReflectError> {
879        self.require_active()?;
880
881        // Get the source value's pointer and shape
882        let src_ptr = peek.data();
883        let src_shape = peek.shape();
884
885        // SAFETY: `Peek` guarantees that src_ptr is initialized and of type src_shape
886        unsafe { self.set_shape(src_ptr, src_shape) }
887    }
888
889    /// Parses a string value into the current frame using the type's ParseFn from the vtable.
890    ///
891    /// If the current frame was previously initialized, its contents are dropped in place.
892    pub fn parse_from_str(&mut self, s: &str) -> Result<&mut Self, ReflectError> {
893        self.require_active()?;
894
895        let frame = self.frames.last_mut().unwrap();
896
897        // Check if the type has a parse function
898        let Some(parse_fn) = frame.shape.vtable.parse else {
899            return Err(ReflectError::OperationFailed {
900                shape: frame.shape,
901                operation: "Type does not support parsing from string",
902            });
903        };
904
905        // Note: deinit leaves us in `Tracker::Uninit` state which is valid even if we error out.
906        frame.deinit();
907
908        // Parse the string value using the type's parse function
909        let result = unsafe { parse_fn(s, frame.data) };
910        if let Err(_pe) = result {
911            // TODO: can we propagate the ParseError somehow?
912            return Err(ReflectError::OperationFailed {
913                shape: frame.shape,
914                operation: "Failed to parse string value",
915            });
916        }
917
918        // SAFETY: `parse_fn` returned `Ok`, so `frame.data` is fully initialized now.
919        unsafe {
920            frame.mark_as_init();
921        }
922        Ok(self)
923    }
924}
925
926////////////////////////////////////////////////////////////////////////////////////////////////////
927// Enum variant selection
928////////////////////////////////////////////////////////////////////////////////////////////////////
929impl<'facet> Partial<'facet> {
930    /// Get the currently selected variant for an enum
931    pub fn selected_variant(&self) -> Option<Variant> {
932        let frame = self.frames.last()?;
933
934        match &frame.tracker {
935            Tracker::Enum { variant, .. } => Some(**variant),
936            _ => None,
937        }
938    }
939
940    /// Find a variant by name in the current enum
941    pub fn find_variant(&self, variant_name: &str) -> Option<(usize, &'static Variant)> {
942        let frame = self.frames.last()?;
943
944        if let Type::User(UserType::Enum(enum_def)) = frame.shape.ty {
945            enum_def
946                .variants
947                .iter()
948                .enumerate()
949                .find(|(_, v)| v.name == variant_name)
950        } else {
951            None
952        }
953    }
954
955    /// Assuming the current frame is an enum, this selects a variant by index
956    /// (0-based, in declaration order).
957    ///
958    /// For example:
959    ///
960    /// ```rust,no_run
961    /// enum E { A, B, C }
962    /// ```
963    ///
964    /// Calling `select_nth_variant(2)` would select variant `C`.
965    ///
966    /// This will return an error if the current frame is anything other than fully-uninitialized.
967    /// In other words, it's not possible to "switch to a different variant" once you've selected one.
968    ///
969    /// This does _not_ push a frame on the stack.
970    pub fn select_nth_variant(&mut self, index: usize) -> Result<&mut Self, ReflectError> {
971        self.require_active()?;
972
973        let frame = self.frames.last().unwrap();
974        let enum_type = frame.get_enum_type()?;
975
976        if index >= enum_type.variants.len() {
977            return Err(ReflectError::OperationFailed {
978                shape: frame.shape,
979                operation: "variant index out of bounds",
980            });
981        }
982        let variant = &enum_type.variants[index];
983
984        self.select_variant_internal(&enum_type, variant)?;
985        Ok(self)
986    }
987
988    /// Pushes a variant for enum initialization by name
989    ///
990    /// See [Self::select_nth_variant] for more notes.
991    pub fn select_variant_named(&mut self, variant_name: &str) -> Result<&mut Self, ReflectError> {
992        self.require_active()?;
993
994        let frame = self.frames.last_mut().unwrap();
995        let enum_type = frame.get_enum_type()?;
996
997        let Some(variant) = enum_type.variants.iter().find(|v| v.name == variant_name) else {
998            return Err(ReflectError::OperationFailed {
999                shape: frame.shape,
1000                operation: "No variant found with the given name",
1001            });
1002        };
1003
1004        self.select_variant_internal(&enum_type, variant)?;
1005        Ok(self)
1006    }
1007
1008    /// Selects a given enum variant by discriminant. If none of the variants
1009    /// of the frame's enum have that discriminant, this returns an error.
1010    ///
1011    /// See [Self::select_nth_variant] for more notes.
1012    pub fn select_variant(&mut self, discriminant: i64) -> Result<&mut Self, ReflectError> {
1013        self.require_active()?;
1014
1015        // Check all invariants early before making any changes
1016        let frame = self.frames.last().unwrap();
1017
1018        // Check that we're dealing with an enum
1019        let enum_type = match frame.shape.ty {
1020            Type::User(UserType::Enum(e)) => e,
1021            _ => {
1022                return Err(ReflectError::WasNotA {
1023                    expected: "enum",
1024                    actual: frame.shape,
1025                });
1026            }
1027        };
1028
1029        // Find the variant with the matching discriminant
1030        let Some(variant) = enum_type
1031            .variants
1032            .iter()
1033            .find(|v| v.discriminant == Some(discriminant))
1034        else {
1035            return Err(ReflectError::OperationFailed {
1036                shape: frame.shape,
1037                operation: "No variant found with the given discriminant",
1038            });
1039        };
1040
1041        // Update the frame tracker to select the variant
1042        self.select_variant_internal(&enum_type, variant)?;
1043
1044        Ok(self)
1045    }
1046}
1047
1048////////////////////////////////////////////////////////////////////////////////////////////////////
1049// Field selection
1050////////////////////////////////////////////////////////////////////////////////////////////////////
1051impl Partial<'_> {
1052    /// Find the index of a field by name in the current struct
1053    ///
1054    /// If the current frame isn't a struct or an enum (with a selected variant)
1055    /// then this returns `None` for sure.
1056    pub fn field_index(&self, field_name: &str) -> Option<usize> {
1057        let frame = self.frames.last()?;
1058
1059        match frame.shape.ty {
1060            Type::User(UserType::Struct(struct_def)) => {
1061                struct_def.fields.iter().position(|f| f.name == field_name)
1062            }
1063            Type::User(UserType::Enum(_)) => {
1064                // If we're in an enum variant, check its fields
1065                if let Tracker::Enum { variant, .. } = &frame.tracker {
1066                    variant
1067                        .data
1068                        .fields
1069                        .iter()
1070                        .position(|f| f.name == field_name)
1071                } else {
1072                    None
1073                }
1074            }
1075            _ => None,
1076        }
1077    }
1078
1079    /// Check if a struct field at the given index has been set
1080    pub fn is_field_set(&self, index: usize) -> Result<bool, ReflectError> {
1081        let frame = self.frames.last().ok_or(ReflectError::NoActiveFrame)?;
1082
1083        match &frame.tracker {
1084            Tracker::Uninit => Ok(false),
1085            Tracker::Init => Ok(true),
1086            Tracker::Struct { iset, .. } => Ok(iset.get(index)),
1087            Tracker::Enum { data, variant, .. } => {
1088                // Check if the field is already marked as set
1089                if data.get(index) {
1090                    return Ok(true);
1091                }
1092
1093                // For enum variant fields that are empty structs, they are always initialized
1094                if let Some(field) = variant.data.fields.get(index) {
1095                    if let Type::User(UserType::Struct(field_struct)) = field.shape().ty {
1096                        if field_struct.fields.is_empty() {
1097                            return Ok(true);
1098                        }
1099                    }
1100                }
1101
1102                Ok(false)
1103            }
1104            Tracker::Option { building_inner } => {
1105                // For Options, index 0 represents the inner value
1106                if index == 0 {
1107                    Ok(!building_inner)
1108                } else {
1109                    Err(ReflectError::InvalidOperation {
1110                        operation: "is_field_set",
1111                        reason: "Option only has one field (index 0)",
1112                    })
1113                }
1114            }
1115            _ => Err(ReflectError::InvalidOperation {
1116                operation: "is_field_set",
1117                reason: "Current frame is not a struct, enum variant, or option",
1118            }),
1119        }
1120    }
1121
1122    /// Selects a field (by name) of a struct or enum data.
1123    ///
1124    /// For enums, the variant needs to be selected first, see [Self::select_nth_variant]
1125    /// and friends.
1126    pub fn begin_field(&mut self, field_name: &str) -> Result<&mut Self, ReflectError> {
1127        self.require_active()?;
1128
1129        let frame = self.frames.last().unwrap();
1130        let fields = self.get_fields()?;
1131        let Some(idx) = fields.iter().position(|f| f.name == field_name) else {
1132            return Err(ReflectError::FieldError {
1133                shape: frame.shape,
1134                field_error: facet_core::FieldError::NoSuchField,
1135            });
1136        };
1137        self.begin_nth_field(idx)
1138    }
1139
1140    /// Begins the nth field of a struct, enum variant, or array, by index.
1141    ///
1142    /// On success, this pushes a new frame which must be ended with a call to [Partial::end]
1143    pub fn begin_nth_field(&mut self, idx: usize) -> Result<&mut Self, ReflectError> {
1144        self.require_active()?;
1145        let frame = self.frames.last_mut().unwrap();
1146
1147        let next_frame = match frame.shape.ty {
1148            Type::User(user_type) => match user_type {
1149                UserType::Struct(struct_type) => {
1150                    Self::begin_nth_struct_field(frame, struct_type, idx)?
1151                }
1152                UserType::Enum(_) => {
1153                    // Check if we have a variant selected
1154                    match &frame.tracker {
1155                        Tracker::Enum { variant, .. } => {
1156                            Self::begin_nth_enum_field(frame, variant, idx)?
1157                        }
1158                        _ => {
1159                            return Err(ReflectError::OperationFailed {
1160                                shape: frame.shape,
1161                                operation: "must call select_variant before selecting enum fields",
1162                            });
1163                        }
1164                    }
1165                }
1166                UserType::Union(_) => {
1167                    return Err(ReflectError::OperationFailed {
1168                        shape: frame.shape,
1169                        operation: "cannot select a field from a union",
1170                    });
1171                }
1172                UserType::Opaque => {
1173                    return Err(ReflectError::OperationFailed {
1174                        shape: frame.shape,
1175                        operation: "cannot select a field from an opaque type",
1176                    });
1177                }
1178            },
1179            Type::Sequence(sequence_type) => match sequence_type {
1180                SequenceType::Array(array_type) => {
1181                    Self::begin_nth_array_element(frame, array_type, idx)?
1182                }
1183                SequenceType::Slice(_) => {
1184                    return Err(ReflectError::OperationFailed {
1185                        shape: frame.shape,
1186                        operation: "cannot select a field from slices yet",
1187                    });
1188                }
1189            },
1190            _ => {
1191                return Err(ReflectError::OperationFailed {
1192                    shape: frame.shape,
1193                    operation: "cannot select a field from this type",
1194                });
1195            }
1196        };
1197
1198        self.frames.push(next_frame);
1199        Ok(self)
1200    }
1201
1202    /// Sets the given field to its default value, preferring:
1203    ///
1204    ///   * A `default = some_fn()` function
1205    ///   * The field's `Default` implementation if any
1206    ///
1207    /// But without going all the way up to the parent struct's `Default` impl.
1208    ///
1209    /// Errors out if idx is out of bound, if the field has no default method or Default impl.
1210    pub fn set_nth_field_to_default(&mut self, idx: usize) -> Result<&mut Self, ReflectError> {
1211        self.require_active()?;
1212
1213        let frame = self.frames.last().unwrap();
1214        let fields = self.get_fields()?;
1215
1216        if idx >= fields.len() {
1217            return Err(ReflectError::OperationFailed {
1218                shape: frame.shape,
1219                operation: "field index out of bounds",
1220            });
1221        }
1222
1223        let field = fields[idx];
1224
1225        // Check for field-level default function first, then type-level default
1226        if let Some(field_default_fn) = field.vtable.default_fn {
1227            self.begin_nth_field(idx)?;
1228            // the field default fn should be well-behaved
1229            unsafe {
1230                self.set_from_function(|ptr| {
1231                    field_default_fn(ptr);
1232                    Ok(())
1233                })?;
1234            }
1235            self.end()
1236        } else if field.shape().is(Characteristic::Default) {
1237            self.begin_nth_field(idx)?;
1238            self.set_default()?;
1239            self.end()
1240        } else {
1241            return Err(ReflectError::DefaultAttrButNoDefaultImpl {
1242                shape: field.shape(),
1243            });
1244        }
1245    }
1246
1247    /// Given a `Partial` for the same shape, and assuming that partial has the nth
1248    /// field initialized, move the value from `src` to `self`, marking it as deinitialized
1249    /// in `src`.
1250    pub fn steal_nth_field(
1251        &mut self,
1252        src: &mut Partial,
1253        field_index: usize,
1254    ) -> Result<&mut Self, ReflectError> {
1255        let dst_shape = self.shape();
1256        let src_shape = src.shape();
1257        if dst_shape != src_shape {
1258            return Err(ReflectError::HeistCancelledDifferentShapes {
1259                src_shape,
1260                dst_shape,
1261            });
1262        }
1263
1264        // FIXME: what about enums? we don't check that the right variant is
1265        // selected here.
1266        if !src.is_field_set(field_index)? {
1267            return Err(ReflectError::InvariantViolation {
1268                invariant: "stolen field must be initialized",
1269            });
1270        }
1271
1272        let maybe_fields = match src_shape.ty {
1273            Type::Primitive(_primitive_type) => None,
1274            Type::Sequence(_sequence_type) => None,
1275            Type::User(user_type) => match user_type {
1276                UserType::Struct(struct_type) => Some(struct_type.fields),
1277                UserType::Enum(_enum_type) => match self.selected_variant() {
1278                    Some(variant) => Some(variant.data.fields),
1279                    None => {
1280                        return Err(ReflectError::InvariantViolation {
1281                            invariant: "enum field thief must have variant selected",
1282                        });
1283                    }
1284                },
1285                UserType::Union(_union_type) => None,
1286                UserType::Opaque => None,
1287            },
1288            Type::Pointer(_pointer_type) => None,
1289        };
1290
1291        let Some(fields) = maybe_fields else {
1292            return Err(ReflectError::OperationFailed {
1293                shape: src_shape,
1294                operation: "fetching field list for steal_nth_field",
1295            });
1296        };
1297
1298        if field_index >= fields.len() {
1299            return Err(ReflectError::OperationFailed {
1300                shape: src_shape,
1301                operation: "field index out of bounds",
1302            });
1303        }
1304        let field = fields[field_index];
1305
1306        let src_frame = src.frames.last_mut().unwrap();
1307
1308        self.begin_nth_field(field_index)?;
1309        unsafe {
1310            self.set_from_function(|dst_field_ptr| {
1311                let src_field_ptr = src_frame.data.field_init_at(field.offset).as_const();
1312                dst_field_ptr
1313                    .copy_from(src_field_ptr, field.shape())
1314                    .unwrap();
1315                Ok(())
1316            })?;
1317        }
1318        self.end()?;
1319
1320        // now mark field as uninitialized in `src`
1321        match &mut src_frame.tracker {
1322            Tracker::Uninit => {
1323                unreachable!("we just stole a field from src, it couldn't have been fully uninit")
1324            }
1325            Tracker::Init => {
1326                // all struct fields were init so we don't even have a struct tracker,
1327                // let's make one!
1328                let mut iset = ISet::new(fields.len());
1329                iset.set_all();
1330                iset.unset(field_index);
1331                src_frame.tracker = Tracker::Struct {
1332                    iset,
1333                    current_child: None,
1334                }
1335            }
1336            Tracker::Array { .. } => unreachable!("can't steal fields from arrays"),
1337            Tracker::Struct { iset, .. } => {
1338                iset.unset(field_index);
1339            }
1340            Tracker::SmartPointer { .. } => {
1341                unreachable!("can't steal fields from smart pointers")
1342            }
1343            Tracker::SmartPointerSlice { .. } => {
1344                unreachable!("can't steal fields from smart pointer slices")
1345            }
1346            Tracker::Enum { data, .. } => {
1347                data.unset(field_index);
1348            }
1349            Tracker::List { .. } => {
1350                unreachable!("can't steal fields from lists")
1351            }
1352            Tracker::Map { .. } => {
1353                unreachable!("can't steal fields from maps")
1354            }
1355            Tracker::Option { .. } => {
1356                unreachable!("can't steal fields from options")
1357            }
1358        }
1359
1360        Ok(self)
1361    }
1362}
1363
1364////////////////////////////////////////////////////////////////////////////////////////////////////
1365// Smart pointers
1366////////////////////////////////////////////////////////////////////////////////////////////////////
1367impl Partial<'_> {
1368    /// Pushes a frame to initialize the inner value of a smart pointer (`Box<T>`, `Arc<T>`, etc.)
1369    pub fn begin_smart_ptr(&mut self) -> Result<&mut Self, ReflectError> {
1370        crate::trace!("begin_smart_ptr()");
1371        self.require_active()?;
1372        let frame = self.frames.last_mut().unwrap();
1373
1374        // Check that we have a SmartPointer
1375        match &frame.shape.def {
1376            Def::Pointer(smart_ptr_def) => {
1377                // Check for supported smart pointer types
1378                match smart_ptr_def.known {
1379                    Some(KnownPointer::Box)
1380                    | Some(KnownPointer::Rc)
1381                    | Some(KnownPointer::Arc)
1382                    | Some(KnownPointer::SharedReference) => {
1383                        // Supported types, continue
1384                    }
1385                    _ => {
1386                        return Err(ReflectError::OperationFailed {
1387                            shape: frame.shape,
1388                            operation: "only the following pointers are currently supported: Box<T>, Rc<T>, Arc<T>, and &T",
1389                        });
1390                    }
1391                }
1392
1393                // Get the pointee shape
1394                let pointee_shape = match smart_ptr_def.pointee() {
1395                    Some(shape) => shape,
1396                    None => {
1397                        return Err(ReflectError::OperationFailed {
1398                            shape: frame.shape,
1399                            operation: "Box must have a pointee shape",
1400                        });
1401                    }
1402                };
1403
1404                if pointee_shape.layout.sized_layout().is_ok() {
1405                    // pointee is sized, we can allocate it — for `Arc<T>` we'll be allocating a `T` and
1406                    // holding onto it. We'll build a new Arc with it when ending the smart pointer frame.
1407
1408                    if matches!(frame.tracker, Tracker::Uninit) {
1409                        frame.tracker = Tracker::SmartPointer {
1410                            is_initialized: false,
1411                        };
1412                    }
1413
1414                    let inner_layout = match pointee_shape.layout.sized_layout() {
1415                        Ok(layout) => layout,
1416                        Err(_) => {
1417                            return Err(ReflectError::Unsized {
1418                                shape: pointee_shape,
1419                                operation: "begin_smart_ptr, calculating inner value layout",
1420                            });
1421                        }
1422                    };
1423                    let inner_ptr: *mut u8 = unsafe { alloc::alloc::alloc(inner_layout) };
1424                    let Some(inner_ptr) = NonNull::new(inner_ptr) else {
1425                        return Err(ReflectError::OperationFailed {
1426                            shape: frame.shape,
1427                            operation: "failed to allocate memory for smart pointer inner value",
1428                        });
1429                    };
1430
1431                    // Push a new frame for the inner value
1432                    self.frames.push(Frame::new(
1433                        PtrUninit::new(inner_ptr),
1434                        pointee_shape,
1435                        FrameOwnership::Owned,
1436                    ));
1437                } else {
1438                    // pointee is unsized, we only support a handful of cases there
1439                    if pointee_shape == str::SHAPE {
1440                        crate::trace!("Pointee is str");
1441
1442                        // Allocate space for a String
1443                        let string_layout = String::SHAPE
1444                            .layout
1445                            .sized_layout()
1446                            .expect("String must have a sized layout");
1447                        let string_ptr: *mut u8 = unsafe { alloc::alloc::alloc(string_layout) };
1448                        let Some(string_ptr) = NonNull::new(string_ptr) else {
1449                            return Err(ReflectError::OperationFailed {
1450                                shape: frame.shape,
1451                                operation: "failed to allocate memory for string",
1452                            });
1453                        };
1454                        let mut frame = Frame::new(
1455                            PtrUninit::new(string_ptr),
1456                            String::SHAPE,
1457                            FrameOwnership::Owned,
1458                        );
1459                        frame.tracker = Tracker::Uninit;
1460                        self.frames.push(frame);
1461                    } else if let Type::Sequence(SequenceType::Slice(_st)) = pointee_shape.ty {
1462                        crate::trace!("Pointee is [{}]", _st.t);
1463
1464                        // Get the slice builder vtable
1465                        let slice_builder_vtable = smart_ptr_def
1466                            .vtable
1467                            .slice_builder_vtable
1468                            .ok_or(ReflectError::OperationFailed {
1469                                shape: frame.shape,
1470                                operation: "smart pointer does not support slice building",
1471                            })?;
1472
1473                        // Create a new builder
1474                        let builder_ptr = (slice_builder_vtable.new_fn)();
1475
1476                        // Deallocate the original Arc allocation before replacing with slice builder
1477                        if let FrameOwnership::Owned = frame.ownership {
1478                            if let Ok(layout) = frame.shape.layout.sized_layout() {
1479                                if layout.size() > 0 {
1480                                    unsafe {
1481                                        alloc::alloc::dealloc(frame.data.as_mut_byte_ptr(), layout)
1482                                    };
1483                                }
1484                            }
1485                        }
1486
1487                        // Update the current frame to use the slice builder
1488                        frame.data = builder_ptr.as_uninit();
1489                        frame.tracker = Tracker::SmartPointerSlice {
1490                            vtable: slice_builder_vtable,
1491                            building_item: false,
1492                        };
1493                        // The slice builder memory is managed by the vtable, not by us
1494                        frame.ownership = FrameOwnership::ManagedElsewhere;
1495                    } else {
1496                        todo!("unsupported unsize pointee shape: {}", pointee_shape)
1497                    }
1498                }
1499
1500                Ok(self)
1501            }
1502            _ => Err(ReflectError::OperationFailed {
1503                shape: frame.shape,
1504                operation: "push_smart_ptr can only be called on compatible types",
1505            }),
1506        }
1507    }
1508}
1509
1510////////////////////////////////////////////////////////////////////////////////////////////////////
1511// Lists
1512////////////////////////////////////////////////////////////////////////////////////////////////////
1513impl Partial<'_> {
1514    /// Initializes a list (Vec, etc.) if it hasn't been initialized before.
1515    /// This is a prerequisite to `begin_push_item`/`set`/`end` or the shorthand
1516    /// `push`.
1517    ///
1518    /// `begin_list` does not clear the list if it was previously initialized.
1519    /// `begin_list` does not push a new frame to the stack, and thus does not
1520    /// require `end` to be called afterwards.
1521    pub fn begin_list(&mut self) -> Result<&mut Self, ReflectError> {
1522        crate::trace!("begin_list()");
1523        self.require_active()?;
1524        let frame = self.frames.last_mut().unwrap();
1525
1526        match &frame.tracker {
1527            Tracker::Uninit => {
1528                // that's good, let's initialize it
1529            }
1530            Tracker::Init => {
1531                // initialized (perhaps from a previous round?) but should be a list tracker, let's fix that:
1532                frame.tracker = Tracker::List {
1533                    is_initialized: true,
1534                    current_child: false,
1535                };
1536                return Ok(self);
1537            }
1538            Tracker::List { is_initialized, .. } => {
1539                if *is_initialized {
1540                    // already initialized, nothing to do
1541                    return Ok(self);
1542                }
1543            }
1544            Tracker::SmartPointerSlice { .. } => {
1545                // begin_list is kinda superfluous when we're in a SmartPointerSlice state
1546                return Ok(self);
1547            }
1548            _ => {
1549                return Err(ReflectError::UnexpectedTracker {
1550                    message: "begin_list called but tracker isn't something list-like",
1551                    current_tracker: frame.tracker.kind(),
1552                });
1553            }
1554        };
1555
1556        // Check that we have a List
1557        let list_def = match &frame.shape.def {
1558            Def::List(list_def) => list_def,
1559            _ => {
1560                return Err(ReflectError::OperationFailed {
1561                    shape: frame.shape,
1562                    operation: "begin_list can only be called on List types",
1563                });
1564            }
1565        };
1566
1567        // Check that we have init_in_place_with_capacity function
1568        let init_fn = match list_def.vtable.init_in_place_with_capacity {
1569            Some(f) => f,
1570            None => {
1571                return Err(ReflectError::OperationFailed {
1572                    shape: frame.shape,
1573                    operation: "list type does not support initialization with capacity",
1574                });
1575            }
1576        };
1577
1578        // Initialize the list with default capacity (0)
1579        unsafe {
1580            init_fn(frame.data, 0);
1581        }
1582
1583        // Update tracker to List state
1584        frame.tracker = Tracker::List {
1585            is_initialized: true,
1586            current_child: false,
1587        };
1588
1589        Ok(self)
1590    }
1591
1592    /// Pushes an element to the list
1593    /// The element should be set using `set()` or similar methods, then `pop()` to complete
1594    pub fn begin_list_item(&mut self) -> Result<&mut Self, ReflectError> {
1595        crate::trace!("begin_list_item()");
1596        self.require_active()?;
1597        let frame = self.frames.last_mut().unwrap();
1598
1599        // Check if we're building a smart pointer slice
1600        if let Tracker::SmartPointerSlice {
1601            building_item,
1602            vtable: _,
1603        } = &frame.tracker
1604        {
1605            if *building_item {
1606                return Err(ReflectError::OperationFailed {
1607                    shape: frame.shape,
1608                    operation: "already building an item, call end() first",
1609                });
1610            }
1611
1612            // Get the element type from the smart pointer's pointee
1613            let element_shape = match &frame.shape.def {
1614                Def::Pointer(smart_ptr_def) => match smart_ptr_def.pointee() {
1615                    Some(pointee_shape) => match &pointee_shape.ty {
1616                        Type::Sequence(SequenceType::Slice(slice_type)) => slice_type.t,
1617                        _ => {
1618                            return Err(ReflectError::OperationFailed {
1619                                shape: frame.shape,
1620                                operation: "smart pointer pointee is not a slice",
1621                            });
1622                        }
1623                    },
1624                    None => {
1625                        return Err(ReflectError::OperationFailed {
1626                            shape: frame.shape,
1627                            operation: "smart pointer has no pointee",
1628                        });
1629                    }
1630                },
1631                _ => {
1632                    return Err(ReflectError::OperationFailed {
1633                        shape: frame.shape,
1634                        operation: "expected smart pointer definition",
1635                    });
1636                }
1637            };
1638
1639            // Allocate space for the element
1640            crate::trace!("Pointee is a slice of {element_shape}");
1641            let element_layout = match element_shape.layout.sized_layout() {
1642                Ok(layout) => layout,
1643                Err(_) => {
1644                    return Err(ReflectError::OperationFailed {
1645                        shape: element_shape,
1646                        operation: "cannot allocate unsized element",
1647                    });
1648                }
1649            };
1650
1651            let element_ptr: *mut u8 = unsafe { alloc::alloc::alloc(element_layout) };
1652            let Some(element_ptr) = NonNull::new(element_ptr) else {
1653                return Err(ReflectError::OperationFailed {
1654                    shape: frame.shape,
1655                    operation: "failed to allocate memory for list element",
1656                });
1657            };
1658
1659            // Create and push the element frame
1660            crate::trace!("Pushing element frame, which we just allocated");
1661            let element_frame = Frame::new(
1662                PtrUninit::new(element_ptr),
1663                element_shape,
1664                FrameOwnership::Owned,
1665            );
1666            self.frames.push(element_frame);
1667
1668            // Mark that we're building an item
1669            // We need to update the tracker after pushing the frame
1670            let parent_idx = self.frames.len() - 2;
1671            if let Tracker::SmartPointerSlice { building_item, .. } =
1672                &mut self.frames[parent_idx].tracker
1673            {
1674                crate::trace!("Marking element frame as building item");
1675                *building_item = true;
1676            }
1677
1678            return Ok(self);
1679        }
1680
1681        // Check that we have a List that's been initialized
1682        let list_def = match &frame.shape.def {
1683            Def::List(list_def) => list_def,
1684            _ => {
1685                return Err(ReflectError::OperationFailed {
1686                    shape: frame.shape,
1687                    operation: "push can only be called on List types",
1688                });
1689            }
1690        };
1691
1692        // Verify the tracker is in List state and initialized
1693        match &mut frame.tracker {
1694            Tracker::List {
1695                is_initialized: true,
1696                current_child,
1697            } => {
1698                if *current_child {
1699                    return Err(ReflectError::OperationFailed {
1700                        shape: frame.shape,
1701                        operation: "already pushing an element, call pop() first",
1702                    });
1703                }
1704                *current_child = true;
1705            }
1706            _ => {
1707                return Err(ReflectError::OperationFailed {
1708                    shape: frame.shape,
1709                    operation: "must call begin_list() before push()",
1710                });
1711            }
1712        }
1713
1714        // Get the element shape
1715        let element_shape = list_def.t();
1716
1717        // Allocate space for the new element
1718        let element_layout = match element_shape.layout.sized_layout() {
1719            Ok(layout) => layout,
1720            Err(_) => {
1721                return Err(ReflectError::Unsized {
1722                    shape: element_shape,
1723                    operation: "begin_list_item: calculating element layout",
1724                });
1725            }
1726        };
1727        let element_ptr: *mut u8 = unsafe { alloc::alloc::alloc(element_layout) };
1728
1729        let Some(element_ptr) = NonNull::new(element_ptr) else {
1730            return Err(ReflectError::OperationFailed {
1731                shape: frame.shape,
1732                operation: "failed to allocate memory for list element",
1733            });
1734        };
1735
1736        // Push a new frame for the element
1737        self.frames.push(Frame::new(
1738            PtrUninit::new(element_ptr),
1739            element_shape,
1740            FrameOwnership::Owned,
1741        ));
1742
1743        Ok(self)
1744    }
1745}
1746
1747////////////////////////////////////////////////////////////////////////////////////////////////////
1748// Maps
1749////////////////////////////////////////////////////////////////////////////////////////////////////
1750impl Partial<'_> {
1751    /// Begins a map initialization operation
1752    ///
1753    /// This initializes the map with default capacity and allows inserting key-value pairs
1754    /// It does _not_ push a new frame onto the stack.
1755    pub fn begin_map(&mut self) -> Result<&mut Self, ReflectError> {
1756        self.require_active()?;
1757        let frame = self.frames.last_mut().unwrap();
1758
1759        // Check that we have a Map
1760        let map_def = match &frame.shape.def {
1761            Def::Map(map_def) => map_def,
1762            _ => {
1763                return Err(ReflectError::OperationFailed {
1764                    shape: frame.shape,
1765                    operation: "begin_map can only be called on Map types",
1766                });
1767            }
1768        };
1769
1770        let init_fn = map_def.vtable.init_in_place_with_capacity_fn;
1771
1772        // Initialize the map with default capacity (0)
1773        unsafe {
1774            init_fn(frame.data, 0);
1775        }
1776
1777        // Update tracker to Map state
1778        frame.tracker = Tracker::Map {
1779            is_initialized: true,
1780            insert_state: MapInsertState::Idle,
1781        };
1782
1783        Ok(self)
1784    }
1785
1786    /// Pushes a frame for the map key. After that, `set()` should be called
1787    /// (or the key should be initialized somehow) and `end()` should be called
1788    /// to pop the frame.
1789    pub fn begin_key(&mut self) -> Result<&mut Self, ReflectError> {
1790        self.require_active()?;
1791        let frame = self.frames.last_mut().unwrap();
1792
1793        // Check that we have a Map and set up for key insertion
1794        let map_def = match (&frame.shape.def, &mut frame.tracker) {
1795            (
1796                Def::Map(map_def),
1797                Tracker::Map {
1798                    is_initialized: true,
1799                    insert_state,
1800                },
1801            ) => {
1802                match insert_state {
1803                    MapInsertState::Idle => {
1804                        // Start a new insert automatically
1805                        *insert_state = MapInsertState::PushingKey { key_ptr: None };
1806                    }
1807                    MapInsertState::PushingKey { key_ptr } => {
1808                        if key_ptr.is_some() {
1809                            return Err(ReflectError::OperationFailed {
1810                                shape: frame.shape,
1811                                operation: "already pushing a key, call end() first",
1812                            });
1813                        }
1814                    }
1815                    _ => {
1816                        return Err(ReflectError::OperationFailed {
1817                            shape: frame.shape,
1818                            operation: "must complete current operation before begin_key()",
1819                        });
1820                    }
1821                }
1822                map_def
1823            }
1824            _ => {
1825                return Err(ReflectError::OperationFailed {
1826                    shape: frame.shape,
1827                    operation: "must call begin_map() before begin_key()",
1828                });
1829            }
1830        };
1831
1832        // Get the key shape
1833        let key_shape = map_def.k();
1834
1835        // Allocate space for the key
1836        let key_layout = match key_shape.layout.sized_layout() {
1837            Ok(layout) => layout,
1838            Err(_) => {
1839                return Err(ReflectError::Unsized {
1840                    shape: key_shape,
1841                    operation: "begin_key allocating key",
1842                });
1843            }
1844        };
1845        let key_ptr_raw: *mut u8 = unsafe { alloc::alloc::alloc(key_layout) };
1846
1847        let Some(key_ptr_raw) = NonNull::new(key_ptr_raw) else {
1848            return Err(ReflectError::OperationFailed {
1849                shape: frame.shape,
1850                operation: "failed to allocate memory for map key",
1851            });
1852        };
1853
1854        // Store the key pointer in the insert state
1855        match &mut frame.tracker {
1856            Tracker::Map {
1857                insert_state: MapInsertState::PushingKey { key_ptr: kp },
1858                ..
1859            } => {
1860                *kp = Some(PtrUninit::new(key_ptr_raw));
1861            }
1862            _ => unreachable!(),
1863        }
1864
1865        // Push a new frame for the key
1866        self.frames.push(Frame::new(
1867            PtrUninit::new(key_ptr_raw),
1868            key_shape,
1869            FrameOwnership::ManagedElsewhere, // Ownership tracked in MapInsertState
1870        ));
1871
1872        Ok(self)
1873    }
1874
1875    /// Pushes a frame for the map value
1876    /// Must be called after the key has been set and popped
1877    pub fn begin_value(&mut self) -> Result<&mut Self, ReflectError> {
1878        self.require_active()?;
1879        let frame = self.frames.last_mut().unwrap();
1880
1881        // Check that we have a Map in PushingValue state
1882        let map_def = match (&frame.shape.def, &mut frame.tracker) {
1883            (
1884                Def::Map(map_def),
1885                Tracker::Map {
1886                    insert_state: MapInsertState::PushingValue { value_ptr, .. },
1887                    ..
1888                },
1889            ) => {
1890                if value_ptr.is_some() {
1891                    return Err(ReflectError::OperationFailed {
1892                        shape: frame.shape,
1893                        operation: "already pushing a value, call pop() first",
1894                    });
1895                }
1896                map_def
1897            }
1898            _ => {
1899                return Err(ReflectError::OperationFailed {
1900                    shape: frame.shape,
1901                    operation: "must complete key before push_value()",
1902                });
1903            }
1904        };
1905
1906        // Get the value shape
1907        let value_shape = map_def.v();
1908
1909        // Allocate space for the value
1910        let value_layout = match value_shape.layout.sized_layout() {
1911            Ok(layout) => layout,
1912            Err(_) => {
1913                return Err(ReflectError::Unsized {
1914                    shape: value_shape,
1915                    operation: "begin_value allocating value",
1916                });
1917            }
1918        };
1919        let value_ptr_raw: *mut u8 = unsafe { alloc::alloc::alloc(value_layout) };
1920
1921        let Some(value_ptr_raw) = NonNull::new(value_ptr_raw) else {
1922            return Err(ReflectError::OperationFailed {
1923                shape: frame.shape,
1924                operation: "failed to allocate memory for map value",
1925            });
1926        };
1927
1928        // Store the value pointer in the insert state
1929        match &mut frame.tracker {
1930            Tracker::Map {
1931                insert_state: MapInsertState::PushingValue { value_ptr: vp, .. },
1932                ..
1933            } => {
1934                *vp = Some(PtrUninit::new(value_ptr_raw));
1935            }
1936            _ => unreachable!(),
1937        }
1938
1939        // Push a new frame for the value
1940        self.frames.push(Frame::new(
1941            PtrUninit::new(value_ptr_raw),
1942            value_shape,
1943            FrameOwnership::ManagedElsewhere, // Ownership tracked in MapInsertState
1944        ));
1945
1946        Ok(self)
1947    }
1948}
1949
1950////////////////////////////////////////////////////////////////////////////////////////////////////
1951// Option / inner
1952////////////////////////////////////////////////////////////////////////////////////////////////////
1953impl Partial<'_> {
1954    /// Begin building the Some variant of an Option
1955    pub fn begin_some(&mut self) -> Result<&mut Self, ReflectError> {
1956        self.require_active()?;
1957        let frame = self.frames.last_mut().unwrap();
1958
1959        // Verify we're working with an Option
1960        let option_def = match frame.shape.def {
1961            Def::Option(def) => def,
1962            _ => {
1963                return Err(ReflectError::WasNotA {
1964                    expected: "Option",
1965                    actual: frame.shape,
1966                });
1967            }
1968        };
1969
1970        // Initialize the tracker for Option building
1971        if matches!(frame.tracker, Tracker::Uninit) {
1972            frame.tracker = Tracker::Option {
1973                building_inner: true,
1974            };
1975        }
1976
1977        // Get the inner type shape
1978        let inner_shape = option_def.t;
1979
1980        // Allocate memory for the inner value
1981        let inner_layout =
1982            inner_shape
1983                .layout
1984                .sized_layout()
1985                .map_err(|_| ReflectError::Unsized {
1986                    shape: inner_shape,
1987                    operation: "begin_some, allocating Option inner value",
1988                })?;
1989
1990        let inner_data = if inner_layout.size() == 0 {
1991            // For ZST, use a non-null but unallocated pointer
1992            PtrUninit::new(NonNull::<u8>::dangling())
1993        } else {
1994            // Allocate memory for the inner value
1995            let ptr = unsafe { alloc::alloc::alloc(inner_layout) };
1996            let Some(ptr) = NonNull::new(ptr) else {
1997                alloc::alloc::handle_alloc_error(inner_layout);
1998            };
1999            PtrUninit::new(ptr)
2000        };
2001
2002        // Create a new frame for the inner value
2003        let inner_frame = Frame::new(inner_data, inner_shape, FrameOwnership::Owned);
2004        self.frames.push(inner_frame);
2005
2006        Ok(self)
2007    }
2008
2009    /// Begin building the inner value of a wrapper type
2010    pub fn begin_inner(&mut self) -> Result<&mut Self, ReflectError> {
2011        self.require_active()?;
2012
2013        // Get the inner shape and check for try_from
2014        let (inner_shape, has_try_from, parent_shape) = {
2015            let frame = self.frames.last().unwrap();
2016            if let Some(inner_shape) = frame.shape.inner {
2017                let has_try_from = frame.shape.vtable.try_from.is_some();
2018                (Some(inner_shape), has_try_from, frame.shape)
2019            } else {
2020                (None, false, frame.shape)
2021            }
2022        };
2023
2024        if let Some(inner_shape) = inner_shape {
2025            if has_try_from {
2026                // Create a conversion frame with the inner shape
2027
2028                // For conversion frames, we leave the parent tracker unchanged
2029                // This allows automatic conversion detection to work properly
2030
2031                // Allocate memory for the inner value (conversion source)
2032                let inner_layout =
2033                    inner_shape
2034                        .layout
2035                        .sized_layout()
2036                        .map_err(|_| ReflectError::Unsized {
2037                            shape: inner_shape,
2038                            operation: "begin_inner, getting inner layout",
2039                        })?;
2040
2041                let inner_data = if inner_layout.size() == 0 {
2042                    // For ZST, use a non-null but unallocated pointer
2043                    PtrUninit::new(NonNull::<u8>::dangling())
2044                } else {
2045                    // Allocate memory for the inner value
2046                    let ptr = unsafe { alloc::alloc::alloc(inner_layout) };
2047                    let Some(ptr) = NonNull::new(ptr) else {
2048                        alloc::alloc::handle_alloc_error(inner_layout);
2049                    };
2050                    PtrUninit::new(ptr)
2051                };
2052
2053                // For conversion frames, we create a frame directly with the inner shape
2054                // This allows setting values of the inner type which will be converted
2055                // The automatic conversion detection in end() will handle the conversion
2056                trace!(
2057                    "begin_inner: Creating frame for inner type {inner_shape} (parent is {parent_shape})"
2058                );
2059                self.frames
2060                    .push(Frame::new(inner_data, inner_shape, FrameOwnership::Owned));
2061
2062                Ok(self)
2063            } else {
2064                // For wrapper types without try_from, navigate to the first field
2065                // This is a common pattern for newtype wrappers
2066                trace!("begin_inner: No try_from for {parent_shape}, using field navigation");
2067                self.begin_nth_field(0)
2068            }
2069        } else {
2070            Err(ReflectError::OperationFailed {
2071                shape: parent_shape,
2072                operation: "type does not have an inner value",
2073            })
2074        }
2075    }
2076}
2077
2078////////////////////////////////////////////////////////////////////////////////////////////////////
2079// Shorthands
2080////////////////////////////////////////////////////////////////////////////////////////////////////
2081impl<'facet> Partial<'facet> {
2082    /// Convenience shortcut: sets the field at index `idx` directly to value, popping after.
2083    ///
2084    /// Works on structs, enums (after selecting a variant) and arrays.
2085    pub fn set_nth_field<U>(&mut self, idx: usize, value: U) -> Result<&mut Self, ReflectError>
2086    where
2087        U: Facet<'facet>,
2088    {
2089        self.begin_nth_field(idx)?.set(value)?.end()
2090    }
2091
2092    /// Convenience shortcut: sets the named field to value, popping after.
2093    pub fn set_field<U>(&mut self, field_name: &str, value: U) -> Result<&mut Self, ReflectError>
2094    where
2095        U: Facet<'facet>,
2096    {
2097        self.begin_field(field_name)?.set(value)?.end()
2098    }
2099
2100    /// Convenience shortcut: sets the key for a map key-value insertion, then pops after.
2101    pub fn set_key<U>(&mut self, value: U) -> Result<&mut Self, ReflectError>
2102    where
2103        U: Facet<'facet>,
2104    {
2105        self.begin_key()?.set(value)?.end()
2106    }
2107
2108    /// Convenience shortcut: sets the value for a map key-value insertion, then pops after.
2109    pub fn set_value<U>(&mut self, value: U) -> Result<&mut Self, ReflectError>
2110    where
2111        U: Facet<'facet>,
2112    {
2113        self.begin_value()?.set(value)?.end()
2114    }
2115
2116    /// Shorthand for: begin_list_item(), set(), end()
2117    pub fn push<U>(&mut self, value: U) -> Result<&mut Self, ReflectError>
2118    where
2119        U: Facet<'facet>,
2120    {
2121        self.begin_list_item()?.set(value)?.end()
2122    }
2123}
2124
2125////////////////////////////////////////////////////////////////////////////////////////////////////
2126// Internal methods
2127////////////////////////////////////////////////////////////////////////////////////////////////////
2128impl<'facet> Partial<'facet> {
2129    /// Preconditions:
2130    ///
2131    /// - `require_active()` check was made
2132    /// - frame.shape.ty is an Enum
2133    /// - `discriminant` is a valid discriminant
2134    ///
2135    /// Panics if current tracker is anything other than `Uninit`
2136    /// (switching variants is not supported for now).
2137    fn select_variant_internal(
2138        &mut self,
2139        enum_type: &EnumType,
2140        variant: &'static Variant,
2141    ) -> Result<(), ReflectError> {
2142        // Check all invariants early before making any changes
2143        let frame = self.frames.last().unwrap();
2144
2145        // Check enum representation early
2146        match enum_type.enum_repr {
2147            EnumRepr::RustNPO => {
2148                return Err(ReflectError::OperationFailed {
2149                    shape: frame.shape,
2150                    operation: "RustNPO enums are not supported for incremental building",
2151                });
2152            }
2153            EnumRepr::U8
2154            | EnumRepr::U16
2155            | EnumRepr::U32
2156            | EnumRepr::U64
2157            | EnumRepr::I8
2158            | EnumRepr::I16
2159            | EnumRepr::I32
2160            | EnumRepr::I64
2161            | EnumRepr::USize
2162            | EnumRepr::ISize => {
2163                // These are supported, continue
2164            }
2165        }
2166
2167        let Some(discriminant) = variant.discriminant else {
2168            return Err(ReflectError::OperationFailed {
2169                shape: frame.shape,
2170                operation: "trying to select an enum variant without a discriminant",
2171            });
2172        };
2173
2174        // All checks passed, now we can safely make changes
2175        let fr = self.frames.last_mut().unwrap();
2176
2177        // Write the discriminant to memory
2178        unsafe {
2179            match enum_type.enum_repr {
2180                EnumRepr::U8 => {
2181                    let ptr = fr.data.as_mut_byte_ptr();
2182                    *ptr = discriminant as u8;
2183                }
2184                EnumRepr::U16 => {
2185                    let ptr = fr.data.as_mut_byte_ptr() as *mut u16;
2186                    *ptr = discriminant as u16;
2187                }
2188                EnumRepr::U32 => {
2189                    let ptr = fr.data.as_mut_byte_ptr() as *mut u32;
2190                    *ptr = discriminant as u32;
2191                }
2192                EnumRepr::U64 => {
2193                    let ptr = fr.data.as_mut_byte_ptr() as *mut u64;
2194                    *ptr = discriminant as u64;
2195                }
2196                EnumRepr::I8 => {
2197                    let ptr = fr.data.as_mut_byte_ptr() as *mut i8;
2198                    *ptr = discriminant as i8;
2199                }
2200                EnumRepr::I16 => {
2201                    let ptr = fr.data.as_mut_byte_ptr() as *mut i16;
2202                    *ptr = discriminant as i16;
2203                }
2204                EnumRepr::I32 => {
2205                    let ptr = fr.data.as_mut_byte_ptr() as *mut i32;
2206                    *ptr = discriminant as i32;
2207                }
2208                EnumRepr::I64 => {
2209                    let ptr = fr.data.as_mut_byte_ptr() as *mut i64;
2210                    *ptr = discriminant;
2211                }
2212                EnumRepr::USize => {
2213                    let ptr = fr.data.as_mut_byte_ptr() as *mut usize;
2214                    *ptr = discriminant as usize;
2215                }
2216                EnumRepr::ISize => {
2217                    let ptr = fr.data.as_mut_byte_ptr() as *mut isize;
2218                    *ptr = discriminant as isize;
2219                }
2220                _ => unreachable!("Already checked enum representation above"),
2221            }
2222        }
2223
2224        // Update tracker to track the variant
2225        fr.tracker = Tracker::Enum {
2226            variant,
2227            data: ISet::new(variant.data.fields.len()),
2228            current_child: None,
2229        };
2230
2231        Ok(())
2232    }
2233
2234    /// Used by `begin_field` etc. to get a list of fields to look through, errors out
2235    /// if we're not pointing to a struct or an enum with an already-selected variant
2236    fn get_fields(&self) -> Result<&'static [Field], ReflectError> {
2237        let frame = self.frames.last().unwrap();
2238        match frame.shape.ty {
2239            Type::Primitive(_) => Err(ReflectError::OperationFailed {
2240                shape: frame.shape,
2241                operation: "cannot select a field from a primitive type",
2242            }),
2243            Type::Sequence(_) => Err(ReflectError::OperationFailed {
2244                shape: frame.shape,
2245                operation: "cannot select a field from a sequence type",
2246            }),
2247            Type::User(user_type) => match user_type {
2248                UserType::Struct(struct_type) => Ok(struct_type.fields),
2249                UserType::Enum(_) => {
2250                    let Tracker::Enum { variant, .. } = &frame.tracker else {
2251                        return Err(ReflectError::OperationFailed {
2252                            shape: frame.shape,
2253                            operation: "must select variant before selecting enum fields",
2254                        });
2255                    };
2256                    Ok(variant.data.fields)
2257                }
2258                UserType::Union(_) => Err(ReflectError::OperationFailed {
2259                    shape: frame.shape,
2260                    operation: "cannot select a field from a union type",
2261                }),
2262                UserType::Opaque => Err(ReflectError::OperationFailed {
2263                    shape: frame.shape,
2264                    operation: "opaque types cannot be reflected upon",
2265                }),
2266            },
2267            Type::Pointer(_) => Err(ReflectError::OperationFailed {
2268                shape: frame.shape,
2269                operation: "cannot select a field from a pointer type",
2270            }),
2271        }
2272    }
2273
2274    /// Selects the nth field of a struct by index
2275    fn begin_nth_struct_field(
2276        frame: &mut Frame,
2277        struct_type: StructType,
2278        idx: usize,
2279    ) -> Result<Frame, ReflectError> {
2280        if idx >= struct_type.fields.len() {
2281            return Err(ReflectError::OperationFailed {
2282                shape: frame.shape,
2283                operation: "field index out of bounds",
2284            });
2285        }
2286        let field = &struct_type.fields[idx];
2287
2288        if !matches!(frame.tracker, Tracker::Struct { .. }) {
2289            frame.tracker = Tracker::Struct {
2290                iset: ISet::new(struct_type.fields.len()),
2291                current_child: None,
2292            }
2293        }
2294
2295        let was_field_init = match &mut frame.tracker {
2296            Tracker::Struct {
2297                iset,
2298                current_child,
2299            } => {
2300                *current_child = Some(idx);
2301                iset.get(idx)
2302            }
2303            _ => unreachable!(),
2304        };
2305
2306        // Push a new frame for this field onto the frames stack.
2307        let field_ptr = unsafe { frame.data.field_uninit_at(field.offset) };
2308        let field_shape = field.shape();
2309
2310        let mut next_frame = Frame::new(field_ptr, field_shape, FrameOwnership::Field);
2311        if was_field_init {
2312            unsafe {
2313                // the struct field tracker said so!
2314                next_frame.mark_as_init();
2315            }
2316        }
2317
2318        Ok(next_frame)
2319    }
2320
2321    /// Selects the nth element of an array by index
2322    fn begin_nth_array_element(
2323        frame: &mut Frame,
2324        array_type: ArrayType,
2325        idx: usize,
2326    ) -> Result<Frame, ReflectError> {
2327        if idx >= array_type.n {
2328            return Err(ReflectError::OperationFailed {
2329                shape: frame.shape,
2330                operation: "array index out of bounds",
2331            });
2332        }
2333
2334        if array_type.n > 63 {
2335            return Err(ReflectError::OperationFailed {
2336                shape: frame.shape,
2337                operation: "arrays larger than 63 elements are not yet supported",
2338            });
2339        }
2340
2341        // Ensure frame is in Array state
2342        match &frame.tracker {
2343            Tracker::Uninit => {
2344                // this is fine
2345                frame.tracker = Tracker::Array {
2346                    iset: ISet::default(),
2347                    current_child: None,
2348                };
2349            }
2350            Tracker::Array { .. } => {
2351                // fine too
2352            }
2353            _other => {
2354                return Err(ReflectError::OperationFailed {
2355                    shape: frame.shape,
2356                    operation: "unexpected tracker state: expected Uninit or Array",
2357                });
2358            }
2359        }
2360
2361        match &mut frame.tracker {
2362            Tracker::Array {
2363                iset,
2364                current_child,
2365            } => {
2366                *current_child = Some(idx);
2367                let was_field_init = iset.get(idx);
2368
2369                // Calculate the offset for this array element
2370                let Ok(element_layout) = array_type.t.layout.sized_layout() else {
2371                    return Err(ReflectError::Unsized {
2372                        shape: array_type.t,
2373                        operation: "begin_nth_element, calculating array element offset",
2374                    });
2375                };
2376                let offset = element_layout.size() * idx;
2377                let element_data = unsafe { frame.data.field_uninit_at(offset) };
2378
2379                let mut next_frame = Frame::new(element_data, array_type.t, FrameOwnership::Field);
2380                if was_field_init {
2381                    // safety: `iset` said it was initialized already
2382                    unsafe {
2383                        next_frame.mark_as_init();
2384                    }
2385                }
2386                Ok(next_frame)
2387            }
2388            _ => unreachable!(),
2389        }
2390    }
2391
2392    /// Selects the nth field of an enum variant by index
2393    fn begin_nth_enum_field(
2394        frame: &mut Frame,
2395        variant: &'static Variant,
2396        idx: usize,
2397    ) -> Result<Frame, ReflectError> {
2398        if idx >= variant.data.fields.len() {
2399            return Err(ReflectError::OperationFailed {
2400                shape: frame.shape,
2401                operation: "enum field index out of bounds",
2402            });
2403        }
2404
2405        let field = &variant.data.fields[idx];
2406
2407        // Update tracker
2408        let was_field_init = match &mut frame.tracker {
2409            Tracker::Enum {
2410                data,
2411                current_child,
2412                ..
2413            } => {
2414                *current_child = Some(idx);
2415                data.get(idx)
2416            }
2417            _ => {
2418                return Err(ReflectError::OperationFailed {
2419                    shape: frame.shape,
2420                    operation: "selecting a field on an enum requires selecting a variant first",
2421                });
2422            }
2423        };
2424
2425        // SAFETY: the field offset comes from an unsafe impl of the Facet trait, we trust it.
2426        // also, we checked that the variant was selected.
2427        let field_ptr = unsafe { frame.data.field_uninit_at(field.offset) };
2428        let field_shape = field.shape();
2429
2430        let mut next_frame = Frame::new(field_ptr, field_shape, FrameOwnership::Field);
2431        if was_field_init {
2432            // SAFETY: `ISet` told us the field was initialized
2433            unsafe {
2434                next_frame.mark_as_init();
2435            }
2436        }
2437
2438        Ok(next_frame)
2439    }
2440
2441    /// Require that the partial is active
2442    #[inline]
2443    pub(crate) fn require_active(&self) -> Result<(), ReflectError> {
2444        if self.state == PartialState::Active {
2445            Ok(())
2446        } else {
2447            Err(ReflectError::InvariantViolation {
2448                invariant: "Cannot use Partial after it has been built or poisoned",
2449            })
2450        }
2451    }
2452}