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