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