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