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 succeeds, 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    /// Given a `Partial` for the same shape, and assuming that partial has the nth
1235    /// field initialized, move the value from `src` to `self`, marking it as deinitialized
1236    /// in `src`.
1237    pub fn steal_nth_field(
1238        &mut self,
1239        src: &mut Partial,
1240        field_index: usize,
1241    ) -> Result<&mut Self, ReflectError> {
1242        let dst_shape = self.shape();
1243        let src_shape = src.shape();
1244        if dst_shape != src_shape {
1245            return Err(ReflectError::HeistCancelledDifferentShapes {
1246                src_shape,
1247                dst_shape,
1248            });
1249        }
1250
1251        // FIXME: what about enums? we don't check that the right variant is
1252        // selected here.
1253        if !src.is_field_set(field_index)? {
1254            return Err(ReflectError::InvariantViolation {
1255                invariant: "stolen field must be initialized",
1256            });
1257        }
1258
1259        let maybe_fields = match src_shape.ty {
1260            Type::Primitive(_primitive_type) => None,
1261            Type::Sequence(_sequence_type) => None,
1262            Type::User(user_type) => match user_type {
1263                UserType::Struct(struct_type) => Some(struct_type.fields),
1264                UserType::Enum(_enum_type) => match self.selected_variant() {
1265                    Some(variant) => Some(variant.data.fields),
1266                    None => {
1267                        return Err(ReflectError::InvariantViolation {
1268                            invariant: "enum field thief must have variant selected",
1269                        });
1270                    }
1271                },
1272                UserType::Union(_union_type) => None,
1273                UserType::Opaque => None,
1274            },
1275            Type::Pointer(_pointer_type) => None,
1276        };
1277
1278        let Some(fields) = maybe_fields else {
1279            return Err(ReflectError::OperationFailed {
1280                shape: src_shape,
1281                operation: "fetching field list for steal_nth_field",
1282            });
1283        };
1284
1285        if field_index >= fields.len() {
1286            return Err(ReflectError::OperationFailed {
1287                shape: src_shape,
1288                operation: "field index out of bounds",
1289            });
1290        }
1291        let field = fields[field_index];
1292
1293        let src_frame = src.frames.last_mut().unwrap();
1294
1295        self.begin_nth_field(field_index)?;
1296        unsafe {
1297            self.set_from_function(|dst_field_ptr| {
1298                let src_field_ptr = src_frame.data.field_init_at(field.offset).as_const();
1299                dst_field_ptr.copy_from(src_field_ptr, field.shape).unwrap();
1300                Ok(())
1301            })?;
1302        }
1303        self.end()?;
1304
1305        // now mark field as uninitialized in `src`
1306        match &mut src_frame.tracker {
1307            Tracker::Uninit => {
1308                unreachable!("we just stole a field from src, it couldn't have been fully uninit")
1309            }
1310            Tracker::Init => {
1311                // all struct fields were init so we don't even have a struct tracker,
1312                // let's make one!
1313                let mut iset = ISet::new(fields.len());
1314                iset.set_all();
1315                iset.unset(field_index);
1316                src_frame.tracker = Tracker::Struct {
1317                    iset,
1318                    current_child: None,
1319                }
1320            }
1321            Tracker::Array { .. } => unreachable!("can't steal fields from arrays"),
1322            Tracker::Struct { iset, .. } => {
1323                iset.unset(field_index);
1324            }
1325            Tracker::SmartPointer { .. } => {
1326                unreachable!("can't steal fields from smart pointers")
1327            }
1328            Tracker::SmartPointerSlice { .. } => {
1329                unreachable!("can't steal fields from smart pointer slices")
1330            }
1331            Tracker::Enum { data, .. } => {
1332                data.unset(field_index);
1333            }
1334            Tracker::List { .. } => {
1335                unreachable!("can't steal fields from lists")
1336            }
1337            Tracker::Map { .. } => {
1338                unreachable!("can't steal fields from maps")
1339            }
1340            Tracker::Option { .. } => {
1341                unreachable!("can't steal fields from options")
1342            }
1343        }
1344
1345        Ok(self)
1346    }
1347}
1348
1349////////////////////////////////////////////////////////////////////////////////////////////////////
1350// Smart pointers
1351////////////////////////////////////////////////////////////////////////////////////////////////////
1352impl Partial<'_> {
1353    /// Pushes a frame to initialize the inner value of a smart pointer (`Box<T>`, `Arc<T>`, etc.)
1354    pub fn begin_smart_ptr(&mut self) -> Result<&mut Self, ReflectError> {
1355        crate::trace!("begin_smart_ptr()");
1356        self.require_active()?;
1357        let frame = self.frames.last_mut().unwrap();
1358
1359        // Check that we have a SmartPointer
1360        match &frame.shape.def {
1361            Def::Pointer(smart_ptr_def) => {
1362                // Check for supported smart pointer types
1363                match smart_ptr_def.known {
1364                    Some(KnownPointer::Box)
1365                    | Some(KnownPointer::Rc)
1366                    | Some(KnownPointer::Arc)
1367                    | Some(KnownPointer::SharedReference) => {
1368                        // Supported types, continue
1369                    }
1370                    _ => {
1371                        return Err(ReflectError::OperationFailed {
1372                            shape: frame.shape,
1373                            operation: "only the following pointers are currently supported: Box<T>, Rc<T>, Arc<T>, and &T",
1374                        });
1375                    }
1376                }
1377
1378                // Get the pointee shape
1379                let pointee_shape = match smart_ptr_def.pointee() {
1380                    Some(shape) => shape,
1381                    None => {
1382                        return Err(ReflectError::OperationFailed {
1383                            shape: frame.shape,
1384                            operation: "Box must have a pointee shape",
1385                        });
1386                    }
1387                };
1388
1389                if pointee_shape.layout.sized_layout().is_ok() {
1390                    // pointee is sized, we can allocate it — for `Arc<T>` we'll be allocating a `T` and
1391                    // holding onto it. We'll build a new Arc with it when ending the smart pointer frame.
1392
1393                    if matches!(frame.tracker, Tracker::Uninit) {
1394                        frame.tracker = Tracker::SmartPointer {
1395                            is_initialized: false,
1396                        };
1397                    }
1398
1399                    let inner_layout = match pointee_shape.layout.sized_layout() {
1400                        Ok(layout) => layout,
1401                        Err(_) => {
1402                            return Err(ReflectError::Unsized {
1403                                shape: pointee_shape,
1404                                operation: "begin_smart_ptr, calculating inner value layout",
1405                            });
1406                        }
1407                    };
1408                    let inner_ptr: *mut u8 = unsafe { alloc::alloc::alloc(inner_layout) };
1409                    if inner_ptr.is_null() {
1410                        return Err(ReflectError::OperationFailed {
1411                            shape: frame.shape,
1412                            operation: "failed to allocate memory for smart pointer inner value",
1413                        });
1414                    }
1415
1416                    // Push a new frame for the inner value
1417                    self.frames.push(Frame::new(
1418                        PtrUninit::new(inner_ptr),
1419                        pointee_shape,
1420                        FrameOwnership::Owned,
1421                    ));
1422                } else {
1423                    // pointee is unsized, we only support a handful of cases there
1424                    if pointee_shape == str::SHAPE {
1425                        crate::trace!("Pointee is str");
1426
1427                        // Allocate space for a String
1428                        let string_layout = String::SHAPE
1429                            .layout
1430                            .sized_layout()
1431                            .expect("String must have a sized layout");
1432                        let string_ptr: *mut u8 = unsafe { alloc::alloc::alloc(string_layout) };
1433                        if string_ptr.is_null() {
1434                            alloc::alloc::handle_alloc_error(string_layout);
1435                        }
1436                        let mut frame = Frame::new(
1437                            PtrUninit::new(string_ptr),
1438                            String::SHAPE,
1439                            FrameOwnership::Owned,
1440                        );
1441                        frame.tracker = Tracker::Uninit;
1442                        self.frames.push(frame);
1443                    } else if let Type::Sequence(SequenceType::Slice(_st)) = pointee_shape.ty {
1444                        crate::trace!("Pointee is [{}]", _st.t);
1445
1446                        // Get the slice builder vtable
1447                        let slice_builder_vtable = smart_ptr_def
1448                            .vtable
1449                            .slice_builder_vtable
1450                            .ok_or(ReflectError::OperationFailed {
1451                                shape: frame.shape,
1452                                operation: "smart pointer does not support slice building",
1453                            })?;
1454
1455                        // Create a new builder
1456                        let builder_ptr = (slice_builder_vtable.new_fn)();
1457
1458                        // Deallocate the original Arc allocation before replacing with slice builder
1459                        if let FrameOwnership::Owned = frame.ownership {
1460                            if let Ok(layout) = frame.shape.layout.sized_layout() {
1461                                if layout.size() > 0 {
1462                                    unsafe {
1463                                        alloc::alloc::dealloc(frame.data.as_mut_byte_ptr(), layout)
1464                                    };
1465                                }
1466                            }
1467                        }
1468
1469                        // Update the current frame to use the slice builder
1470                        frame.data = PtrUninit::new(builder_ptr.as_mut_byte_ptr());
1471                        frame.tracker = Tracker::SmartPointerSlice {
1472                            vtable: slice_builder_vtable,
1473                            building_item: false,
1474                        };
1475                        // The slice builder memory is managed by the vtable, not by us
1476                        frame.ownership = FrameOwnership::ManagedElsewhere;
1477                    } else {
1478                        todo!("unsupported unsize pointee shape: {}", pointee_shape)
1479                    }
1480                }
1481
1482                Ok(self)
1483            }
1484            _ => Err(ReflectError::OperationFailed {
1485                shape: frame.shape,
1486                operation: "push_smart_ptr can only be called on compatible types",
1487            }),
1488        }
1489    }
1490}
1491
1492////////////////////////////////////////////////////////////////////////////////////////////////////
1493// Lists
1494////////////////////////////////////////////////////////////////////////////////////////////////////
1495impl Partial<'_> {
1496    /// Initializes a list (Vec, etc.) if it hasn't been initialized before.
1497    /// This is a prerequisite to `begin_push_item`/`set`/`end` or the shorthand
1498    /// `push`.
1499    ///
1500    /// `begin_list` does not clear the list if it was previously initialized.
1501    /// `begin_list` does not push a new frame to the stack, and thus does not
1502    /// require `end` to be called afterwards.
1503    pub fn begin_list(&mut self) -> Result<&mut Self, ReflectError> {
1504        crate::trace!("begin_list()");
1505        self.require_active()?;
1506        let frame = self.frames.last_mut().unwrap();
1507
1508        match &frame.tracker {
1509            Tracker::Uninit => {
1510                // that's good, let's initialize it
1511            }
1512            Tracker::Init => {
1513                // initialized (perhaps from a previous round?) but should be a list tracker, let's fix that:
1514                frame.tracker = Tracker::List {
1515                    is_initialized: true,
1516                    current_child: false,
1517                };
1518                return Ok(self);
1519            }
1520            Tracker::List { is_initialized, .. } => {
1521                if *is_initialized {
1522                    // already initialized, nothing to do
1523                    return Ok(self);
1524                }
1525            }
1526            Tracker::SmartPointerSlice { .. } => {
1527                // begin_list is kinda superfluous when we're in a SmartPointerSlice state
1528                return Ok(self);
1529            }
1530            _ => {
1531                return Err(ReflectError::UnexpectedTracker {
1532                    message: "begin_list called but tracker isn't something list-like",
1533                    current_tracker: frame.tracker.kind(),
1534                });
1535            }
1536        };
1537
1538        // Check that we have a List
1539        let list_def = match &frame.shape.def {
1540            Def::List(list_def) => list_def,
1541            _ => {
1542                return Err(ReflectError::OperationFailed {
1543                    shape: frame.shape,
1544                    operation: "begin_list can only be called on List types",
1545                });
1546            }
1547        };
1548
1549        // Check that we have init_in_place_with_capacity function
1550        let init_fn = match list_def.vtable.init_in_place_with_capacity {
1551            Some(f) => f,
1552            None => {
1553                return Err(ReflectError::OperationFailed {
1554                    shape: frame.shape,
1555                    operation: "list type does not support initialization with capacity",
1556                });
1557            }
1558        };
1559
1560        // Initialize the list with default capacity (0)
1561        unsafe {
1562            init_fn(frame.data, 0);
1563        }
1564
1565        // Update tracker to List state
1566        frame.tracker = Tracker::List {
1567            is_initialized: true,
1568            current_child: false,
1569        };
1570
1571        Ok(self)
1572    }
1573
1574    /// Pushes an element to the list
1575    /// The element should be set using `set()` or similar methods, then `pop()` to complete
1576    pub fn begin_list_item(&mut self) -> Result<&mut Self, ReflectError> {
1577        crate::trace!("begin_list_item()");
1578        self.require_active()?;
1579        let frame = self.frames.last_mut().unwrap();
1580
1581        // Check if we're building a smart pointer slice
1582        if let Tracker::SmartPointerSlice {
1583            building_item,
1584            vtable: _,
1585        } = &frame.tracker
1586        {
1587            if *building_item {
1588                return Err(ReflectError::OperationFailed {
1589                    shape: frame.shape,
1590                    operation: "already building an item, call end() first",
1591                });
1592            }
1593
1594            // Get the element type from the smart pointer's pointee
1595            let element_shape = match &frame.shape.def {
1596                Def::Pointer(smart_ptr_def) => match smart_ptr_def.pointee() {
1597                    Some(pointee_shape) => match &pointee_shape.ty {
1598                        Type::Sequence(SequenceType::Slice(slice_type)) => slice_type.t,
1599                        _ => {
1600                            return Err(ReflectError::OperationFailed {
1601                                shape: frame.shape,
1602                                operation: "smart pointer pointee is not a slice",
1603                            });
1604                        }
1605                    },
1606                    None => {
1607                        return Err(ReflectError::OperationFailed {
1608                            shape: frame.shape,
1609                            operation: "smart pointer has no pointee",
1610                        });
1611                    }
1612                },
1613                _ => {
1614                    return Err(ReflectError::OperationFailed {
1615                        shape: frame.shape,
1616                        operation: "expected smart pointer definition",
1617                    });
1618                }
1619            };
1620
1621            // Allocate space for the element
1622            crate::trace!("Pointee is a slice of {element_shape}");
1623            let element_layout = match element_shape.layout.sized_layout() {
1624                Ok(layout) => layout,
1625                Err(_) => {
1626                    return Err(ReflectError::OperationFailed {
1627                        shape: element_shape,
1628                        operation: "cannot allocate unsized element",
1629                    });
1630                }
1631            };
1632
1633            let element_ptr: *mut u8 = unsafe { alloc::alloc::alloc(element_layout) };
1634            if element_ptr.is_null() {
1635                alloc::alloc::handle_alloc_error(element_layout);
1636            }
1637
1638            // Create and push the element frame
1639            crate::trace!("Pushing element frame, which we just allocated");
1640            let element_frame = Frame::new(
1641                PtrUninit::new(element_ptr),
1642                element_shape,
1643                FrameOwnership::Owned,
1644            );
1645            self.frames.push(element_frame);
1646
1647            // Mark that we're building an item
1648            // We need to update the tracker after pushing the frame
1649            let parent_idx = self.frames.len() - 2;
1650            if let Tracker::SmartPointerSlice { building_item, .. } =
1651                &mut self.frames[parent_idx].tracker
1652            {
1653                crate::trace!("Marking element frame as building item");
1654                *building_item = true;
1655            }
1656
1657            return Ok(self);
1658        }
1659
1660        // Check that we have a List that's been initialized
1661        let list_def = match &frame.shape.def {
1662            Def::List(list_def) => list_def,
1663            _ => {
1664                return Err(ReflectError::OperationFailed {
1665                    shape: frame.shape,
1666                    operation: "push can only be called on List types",
1667                });
1668            }
1669        };
1670
1671        // Verify the tracker is in List state and initialized
1672        match &mut frame.tracker {
1673            Tracker::List {
1674                is_initialized: true,
1675                current_child,
1676            } => {
1677                if *current_child {
1678                    return Err(ReflectError::OperationFailed {
1679                        shape: frame.shape,
1680                        operation: "already pushing an element, call pop() first",
1681                    });
1682                }
1683                *current_child = true;
1684            }
1685            _ => {
1686                return Err(ReflectError::OperationFailed {
1687                    shape: frame.shape,
1688                    operation: "must call begin_list() before push()",
1689                });
1690            }
1691        }
1692
1693        // Get the element shape
1694        let element_shape = list_def.t();
1695
1696        // Allocate space for the new element
1697        let element_layout = match element_shape.layout.sized_layout() {
1698            Ok(layout) => layout,
1699            Err(_) => {
1700                return Err(ReflectError::Unsized {
1701                    shape: element_shape,
1702                    operation: "begin_list_item: calculating element layout",
1703                });
1704            }
1705        };
1706        let element_ptr: *mut u8 = unsafe { alloc::alloc::alloc(element_layout) };
1707
1708        if element_ptr.is_null() {
1709            return Err(ReflectError::OperationFailed {
1710                shape: frame.shape,
1711                operation: "failed to allocate memory for list element",
1712            });
1713        }
1714
1715        // Push a new frame for the element
1716        self.frames.push(Frame::new(
1717            PtrUninit::new(element_ptr),
1718            element_shape,
1719            FrameOwnership::Owned,
1720        ));
1721
1722        Ok(self)
1723    }
1724}
1725
1726////////////////////////////////////////////////////////////////////////////////////////////////////
1727// Maps
1728////////////////////////////////////////////////////////////////////////////////////////////////////
1729impl Partial<'_> {
1730    /// Begins a map initialization operation
1731    ///
1732    /// This initializes the map with default capacity and allows inserting key-value pairs
1733    /// It does _not_ push a new frame onto the stack.
1734    pub fn begin_map(&mut self) -> Result<&mut Self, ReflectError> {
1735        self.require_active()?;
1736        let frame = self.frames.last_mut().unwrap();
1737
1738        // Check that we have a Map
1739        let map_def = match &frame.shape.def {
1740            Def::Map(map_def) => map_def,
1741            _ => {
1742                return Err(ReflectError::OperationFailed {
1743                    shape: frame.shape,
1744                    operation: "begin_map can only be called on Map types",
1745                });
1746            }
1747        };
1748
1749        let init_fn = map_def.vtable.init_in_place_with_capacity_fn;
1750
1751        // Initialize the map with default capacity (0)
1752        unsafe {
1753            init_fn(frame.data, 0);
1754        }
1755
1756        // Update tracker to Map state
1757        frame.tracker = Tracker::Map {
1758            is_initialized: true,
1759            insert_state: MapInsertState::Idle,
1760        };
1761
1762        Ok(self)
1763    }
1764
1765    /// Pushes a frame for the map key. After that, `set()` should be called
1766    /// (or the key should be initialized somehow) and `end()` should be called
1767    /// to pop the frame.
1768    pub fn begin_key(&mut self) -> Result<&mut Self, ReflectError> {
1769        self.require_active()?;
1770        let frame = self.frames.last_mut().unwrap();
1771
1772        // Check that we have a Map and set up for key insertion
1773        let map_def = match (&frame.shape.def, &mut frame.tracker) {
1774            (
1775                Def::Map(map_def),
1776                Tracker::Map {
1777                    is_initialized: true,
1778                    insert_state,
1779                },
1780            ) => {
1781                match insert_state {
1782                    MapInsertState::Idle => {
1783                        // Start a new insert automatically
1784                        *insert_state = MapInsertState::PushingKey { key_ptr: None };
1785                    }
1786                    MapInsertState::PushingKey { key_ptr } => {
1787                        if key_ptr.is_some() {
1788                            return Err(ReflectError::OperationFailed {
1789                                shape: frame.shape,
1790                                operation: "already pushing a key, call end() first",
1791                            });
1792                        }
1793                    }
1794                    _ => {
1795                        return Err(ReflectError::OperationFailed {
1796                            shape: frame.shape,
1797                            operation: "must complete current operation before begin_key()",
1798                        });
1799                    }
1800                }
1801                map_def
1802            }
1803            _ => {
1804                return Err(ReflectError::OperationFailed {
1805                    shape: frame.shape,
1806                    operation: "must call begin_map() before begin_key()",
1807                });
1808            }
1809        };
1810
1811        // Get the key shape
1812        let key_shape = map_def.k();
1813
1814        // Allocate space for the key
1815        let key_layout = match key_shape.layout.sized_layout() {
1816            Ok(layout) => layout,
1817            Err(_) => {
1818                return Err(ReflectError::Unsized {
1819                    shape: key_shape,
1820                    operation: "begin_key allocating key",
1821                });
1822            }
1823        };
1824        let key_ptr_raw: *mut u8 = unsafe { alloc::alloc::alloc(key_layout) };
1825        if key_ptr_raw.is_null() {
1826            return Err(ReflectError::OperationFailed {
1827                shape: frame.shape,
1828                operation: "failed to allocate memory for map key",
1829            });
1830        }
1831
1832        // Store the key pointer in the insert state
1833        match &mut frame.tracker {
1834            Tracker::Map {
1835                insert_state: MapInsertState::PushingKey { key_ptr: kp },
1836                ..
1837            } => {
1838                *kp = Some(PtrUninit::new(key_ptr_raw));
1839            }
1840            _ => unreachable!(),
1841        }
1842
1843        // Push a new frame for the key
1844        self.frames.push(Frame::new(
1845            PtrUninit::new(key_ptr_raw),
1846            key_shape,
1847            FrameOwnership::ManagedElsewhere, // Ownership tracked in MapInsertState
1848        ));
1849
1850        Ok(self)
1851    }
1852
1853    /// Pushes a frame for the map value
1854    /// Must be called after the key has been set and popped
1855    pub fn begin_value(&mut self) -> Result<&mut Self, ReflectError> {
1856        self.require_active()?;
1857        let frame = self.frames.last_mut().unwrap();
1858
1859        // Check that we have a Map in PushingValue state
1860        let map_def = match (&frame.shape.def, &mut frame.tracker) {
1861            (
1862                Def::Map(map_def),
1863                Tracker::Map {
1864                    insert_state: MapInsertState::PushingValue { value_ptr, .. },
1865                    ..
1866                },
1867            ) => {
1868                if value_ptr.is_some() {
1869                    return Err(ReflectError::OperationFailed {
1870                        shape: frame.shape,
1871                        operation: "already pushing a value, call pop() first",
1872                    });
1873                }
1874                map_def
1875            }
1876            _ => {
1877                return Err(ReflectError::OperationFailed {
1878                    shape: frame.shape,
1879                    operation: "must complete key before push_value()",
1880                });
1881            }
1882        };
1883
1884        // Get the value shape
1885        let value_shape = map_def.v();
1886
1887        // Allocate space for the value
1888        let value_layout = match value_shape.layout.sized_layout() {
1889            Ok(layout) => layout,
1890            Err(_) => {
1891                return Err(ReflectError::Unsized {
1892                    shape: value_shape,
1893                    operation: "begin_value allocating value",
1894                });
1895            }
1896        };
1897        let value_ptr_raw: *mut u8 = unsafe { alloc::alloc::alloc(value_layout) };
1898
1899        if value_ptr_raw.is_null() {
1900            return Err(ReflectError::OperationFailed {
1901                shape: frame.shape,
1902                operation: "failed to allocate memory for map value",
1903            });
1904        }
1905
1906        // Store the value pointer in the insert state
1907        match &mut frame.tracker {
1908            Tracker::Map {
1909                insert_state: MapInsertState::PushingValue { value_ptr: vp, .. },
1910                ..
1911            } => {
1912                *vp = Some(PtrUninit::new(value_ptr_raw));
1913            }
1914            _ => unreachable!(),
1915        }
1916
1917        // Push a new frame for the value
1918        self.frames.push(Frame::new(
1919            PtrUninit::new(value_ptr_raw),
1920            value_shape,
1921            FrameOwnership::ManagedElsewhere, // Ownership tracked in MapInsertState
1922        ));
1923
1924        Ok(self)
1925    }
1926}
1927
1928////////////////////////////////////////////////////////////////////////////////////////////////////
1929// Option / inner
1930////////////////////////////////////////////////////////////////////////////////////////////////////
1931impl Partial<'_> {
1932    /// Begin building the Some variant of an Option
1933    pub fn begin_some(&mut self) -> Result<&mut Self, ReflectError> {
1934        self.require_active()?;
1935        let frame = self.frames.last_mut().unwrap();
1936
1937        // Verify we're working with an Option
1938        let option_def = match frame.shape.def {
1939            Def::Option(def) => def,
1940            _ => {
1941                return Err(ReflectError::WasNotA {
1942                    expected: "Option",
1943                    actual: frame.shape,
1944                });
1945            }
1946        };
1947
1948        // Initialize the tracker for Option building
1949        if matches!(frame.tracker, Tracker::Uninit) {
1950            frame.tracker = Tracker::Option {
1951                building_inner: true,
1952            };
1953        }
1954
1955        // Get the inner type shape
1956        let inner_shape = option_def.t;
1957
1958        // Allocate memory for the inner value
1959        let inner_layout =
1960            inner_shape
1961                .layout
1962                .sized_layout()
1963                .map_err(|_| ReflectError::Unsized {
1964                    shape: inner_shape,
1965                    operation: "begin_some, allocating Option inner value",
1966                })?;
1967
1968        let inner_data = if inner_layout.size() == 0 {
1969            // For ZST, use a non-null but unallocated pointer
1970            PtrUninit::new(core::ptr::NonNull::<u8>::dangling().as_ptr())
1971        } else {
1972            // Allocate memory for the inner value
1973            let ptr = unsafe { alloc::alloc::alloc(inner_layout) };
1974            if ptr.is_null() {
1975                alloc::alloc::handle_alloc_error(inner_layout);
1976            }
1977            PtrUninit::new(ptr)
1978        };
1979
1980        // Create a new frame for the inner value
1981        let inner_frame = Frame::new(inner_data, inner_shape, FrameOwnership::Owned);
1982        self.frames.push(inner_frame);
1983
1984        Ok(self)
1985    }
1986
1987    /// Begin building the inner value of a wrapper type
1988    pub fn begin_inner(&mut self) -> Result<&mut Self, ReflectError> {
1989        self.require_active()?;
1990
1991        // Get the inner shape and check for try_from
1992        let (inner_shape, has_try_from, parent_shape) = {
1993            let frame = self.frames.last().unwrap();
1994            if let Some(inner_fn) = frame.shape.inner {
1995                let inner_shape = inner_fn();
1996                let has_try_from = frame
1997                    .shape
1998                    .vtable
1999                    .sized()
2000                    .and_then(|v| (v.try_from)())
2001                    .is_some();
2002                (Some(inner_shape), has_try_from, frame.shape)
2003            } else {
2004                (None, false, frame.shape)
2005            }
2006        };
2007
2008        if let Some(inner_shape) = inner_shape {
2009            if has_try_from {
2010                // Create a conversion frame with the inner shape
2011
2012                // For conversion frames, we leave the parent tracker unchanged
2013                // This allows automatic conversion detection to work properly
2014
2015                // Allocate memory for the inner value (conversion source)
2016                let inner_layout =
2017                    inner_shape
2018                        .layout
2019                        .sized_layout()
2020                        .map_err(|_| ReflectError::Unsized {
2021                            shape: inner_shape,
2022                            operation: "begin_inner, getting inner layout",
2023                        })?;
2024
2025                let inner_data = if inner_layout.size() == 0 {
2026                    // For ZST, use a non-null but unallocated pointer
2027                    PtrUninit::new(core::ptr::NonNull::<u8>::dangling().as_ptr())
2028                } else {
2029                    // Allocate memory for the inner value
2030                    let ptr = unsafe { alloc::alloc::alloc(inner_layout) };
2031                    if ptr.is_null() {
2032                        alloc::alloc::handle_alloc_error(inner_layout);
2033                    }
2034                    PtrUninit::new(ptr)
2035                };
2036
2037                // For conversion frames, we create a frame directly with the inner shape
2038                // This allows setting values of the inner type which will be converted
2039                // The automatic conversion detection in end() will handle the conversion
2040                trace!(
2041                    "begin_inner: Creating frame for inner type {inner_shape} (parent is {parent_shape})"
2042                );
2043                self.frames
2044                    .push(Frame::new(inner_data, inner_shape, FrameOwnership::Owned));
2045
2046                Ok(self)
2047            } else {
2048                // For wrapper types without try_from, navigate to the first field
2049                // This is a common pattern for newtype wrappers
2050                trace!("begin_inner: No try_from for {parent_shape}, using field navigation");
2051                self.begin_nth_field(0)
2052            }
2053        } else {
2054            Err(ReflectError::OperationFailed {
2055                shape: parent_shape,
2056                operation: "type does not have an inner value",
2057            })
2058        }
2059    }
2060}
2061
2062////////////////////////////////////////////////////////////////////////////////////////////////////
2063// Shorthands
2064////////////////////////////////////////////////////////////////////////////////////////////////////
2065impl<'facet> Partial<'facet> {
2066    /// Convenience shortcut: sets the field at index `idx` directly to value, popping after.
2067    ///
2068    /// Works on structs, enums (after selecting a variant) and arrays.
2069    pub fn set_nth_field<U>(&mut self, idx: usize, value: U) -> Result<&mut Self, ReflectError>
2070    where
2071        U: Facet<'facet>,
2072    {
2073        self.begin_nth_field(idx)?.set(value)?.end()
2074    }
2075
2076    /// Convenience shortcut: sets the named field to value, popping after.
2077    pub fn set_field<U>(&mut self, field_name: &str, value: U) -> Result<&mut Self, ReflectError>
2078    where
2079        U: Facet<'facet>,
2080    {
2081        self.begin_field(field_name)?.set(value)?.end()
2082    }
2083
2084    /// Convenience shortcut: sets the key for a map key-value insertion, then pops after.
2085    pub fn set_key<U>(&mut self, value: U) -> Result<&mut Self, ReflectError>
2086    where
2087        U: Facet<'facet>,
2088    {
2089        self.begin_key()?.set(value)?.end()
2090    }
2091
2092    /// Convenience shortcut: sets the value for a map key-value insertion, then pops after.
2093    pub fn set_value<U>(&mut self, value: U) -> Result<&mut Self, ReflectError>
2094    where
2095        U: Facet<'facet>,
2096    {
2097        self.begin_value()?.set(value)?.end()
2098    }
2099
2100    /// Shorthand for: begin_list_item(), set(), end()
2101    pub fn push<U>(&mut self, value: U) -> Result<&mut Self, ReflectError>
2102    where
2103        U: Facet<'facet>,
2104    {
2105        self.begin_list_item()?.set(value)?.end()
2106    }
2107}
2108
2109////////////////////////////////////////////////////////////////////////////////////////////////////
2110// Internal methods
2111////////////////////////////////////////////////////////////////////////////////////////////////////
2112impl<'facet> Partial<'facet> {
2113    /// Preconditions:
2114    ///
2115    /// - `require_active()` check was made
2116    /// - frame.shape.ty is an Enum
2117    /// - `discriminant` is a valid discriminant
2118    ///
2119    /// Panics if current tracker is anything other than `Uninit`
2120    /// (switching variants is not supported for now).
2121    fn select_variant_internal(
2122        &mut self,
2123        enum_type: &EnumType,
2124        variant: &'static Variant,
2125    ) -> Result<(), ReflectError> {
2126        // Check all invariants early before making any changes
2127        let frame = self.frames.last().unwrap();
2128
2129        // Check enum representation early
2130        match enum_type.enum_repr {
2131            EnumRepr::RustNPO => {
2132                return Err(ReflectError::OperationFailed {
2133                    shape: frame.shape,
2134                    operation: "RustNPO enums are not supported for incremental building",
2135                });
2136            }
2137            EnumRepr::U8
2138            | EnumRepr::U16
2139            | EnumRepr::U32
2140            | EnumRepr::U64
2141            | EnumRepr::I8
2142            | EnumRepr::I16
2143            | EnumRepr::I32
2144            | EnumRepr::I64
2145            | EnumRepr::USize
2146            | EnumRepr::ISize => {
2147                // These are supported, continue
2148            }
2149        }
2150
2151        let Some(discriminant) = variant.discriminant else {
2152            return Err(ReflectError::OperationFailed {
2153                shape: frame.shape,
2154                operation: "trying to select an enum variant without a discriminant",
2155            });
2156        };
2157
2158        // All checks passed, now we can safely make changes
2159        let fr = self.frames.last_mut().unwrap();
2160
2161        // Write the discriminant to memory
2162        unsafe {
2163            match enum_type.enum_repr {
2164                EnumRepr::U8 => {
2165                    let ptr = fr.data.as_mut_byte_ptr();
2166                    *ptr = discriminant as u8;
2167                }
2168                EnumRepr::U16 => {
2169                    let ptr = fr.data.as_mut_byte_ptr() as *mut u16;
2170                    *ptr = discriminant as u16;
2171                }
2172                EnumRepr::U32 => {
2173                    let ptr = fr.data.as_mut_byte_ptr() as *mut u32;
2174                    *ptr = discriminant as u32;
2175                }
2176                EnumRepr::U64 => {
2177                    let ptr = fr.data.as_mut_byte_ptr() as *mut u64;
2178                    *ptr = discriminant as u64;
2179                }
2180                EnumRepr::I8 => {
2181                    let ptr = fr.data.as_mut_byte_ptr() as *mut i8;
2182                    *ptr = discriminant as i8;
2183                }
2184                EnumRepr::I16 => {
2185                    let ptr = fr.data.as_mut_byte_ptr() as *mut i16;
2186                    *ptr = discriminant as i16;
2187                }
2188                EnumRepr::I32 => {
2189                    let ptr = fr.data.as_mut_byte_ptr() as *mut i32;
2190                    *ptr = discriminant as i32;
2191                }
2192                EnumRepr::I64 => {
2193                    let ptr = fr.data.as_mut_byte_ptr() as *mut i64;
2194                    *ptr = discriminant;
2195                }
2196                EnumRepr::USize => {
2197                    let ptr = fr.data.as_mut_byte_ptr() as *mut usize;
2198                    *ptr = discriminant as usize;
2199                }
2200                EnumRepr::ISize => {
2201                    let ptr = fr.data.as_mut_byte_ptr() as *mut isize;
2202                    *ptr = discriminant as isize;
2203                }
2204                _ => unreachable!("Already checked enum representation above"),
2205            }
2206        }
2207
2208        // Update tracker to track the variant
2209        fr.tracker = Tracker::Enum {
2210            variant,
2211            data: ISet::new(variant.data.fields.len()),
2212            current_child: None,
2213        };
2214
2215        Ok(())
2216    }
2217
2218    /// Used by `begin_field` etc. to get a list of fields to look through, errors out
2219    /// if we're not pointing to a struct or an enum with an already-selected variant
2220    fn get_fields(&self) -> Result<&'static [Field], ReflectError> {
2221        let frame = self.frames.last().unwrap();
2222        match frame.shape.ty {
2223            Type::Primitive(_) => Err(ReflectError::OperationFailed {
2224                shape: frame.shape,
2225                operation: "cannot select a field from a primitive type",
2226            }),
2227            Type::Sequence(_) => Err(ReflectError::OperationFailed {
2228                shape: frame.shape,
2229                operation: "cannot select a field from a sequence type",
2230            }),
2231            Type::User(user_type) => match user_type {
2232                UserType::Struct(struct_type) => Ok(struct_type.fields),
2233                UserType::Enum(_) => {
2234                    let Tracker::Enum { variant, .. } = &frame.tracker else {
2235                        return Err(ReflectError::OperationFailed {
2236                            shape: frame.shape,
2237                            operation: "must select variant before selecting enum fields",
2238                        });
2239                    };
2240                    Ok(variant.data.fields)
2241                }
2242                UserType::Union(_) => Err(ReflectError::OperationFailed {
2243                    shape: frame.shape,
2244                    operation: "cannot select a field from a union type",
2245                }),
2246                UserType::Opaque => Err(ReflectError::OperationFailed {
2247                    shape: frame.shape,
2248                    operation: "opaque types cannot be reflected upon",
2249                }),
2250            },
2251            Type::Pointer(_) => Err(ReflectError::OperationFailed {
2252                shape: frame.shape,
2253                operation: "cannot select a field from a pointer type",
2254            }),
2255        }
2256    }
2257
2258    /// Selects the nth field of a struct by index
2259    fn begin_nth_struct_field(
2260        frame: &mut Frame,
2261        struct_type: StructType,
2262        idx: usize,
2263    ) -> Result<Frame, ReflectError> {
2264        if idx >= struct_type.fields.len() {
2265            return Err(ReflectError::OperationFailed {
2266                shape: frame.shape,
2267                operation: "field index out of bounds",
2268            });
2269        }
2270        let field = &struct_type.fields[idx];
2271
2272        if !matches!(frame.tracker, Tracker::Struct { .. }) {
2273            frame.tracker = Tracker::Struct {
2274                iset: ISet::new(struct_type.fields.len()),
2275                current_child: None,
2276            }
2277        }
2278
2279        let was_field_init = match &mut frame.tracker {
2280            Tracker::Struct {
2281                iset,
2282                current_child,
2283            } => {
2284                *current_child = Some(idx);
2285                iset.get(idx)
2286            }
2287            _ => unreachable!(),
2288        };
2289
2290        // Push a new frame for this field onto the frames stack.
2291        let field_ptr = unsafe { frame.data.field_uninit_at(field.offset) };
2292        let field_shape = field.shape;
2293
2294        let mut next_frame = Frame::new(field_ptr, field_shape, FrameOwnership::Field);
2295        if was_field_init {
2296            unsafe {
2297                // the struct field tracker said so!
2298                next_frame.mark_as_init();
2299            }
2300        }
2301
2302        Ok(next_frame)
2303    }
2304
2305    /// Selects the nth element of an array by index
2306    fn begin_nth_array_element(
2307        frame: &mut Frame,
2308        array_type: ArrayType,
2309        idx: usize,
2310    ) -> Result<Frame, ReflectError> {
2311        if idx >= array_type.n {
2312            return Err(ReflectError::OperationFailed {
2313                shape: frame.shape,
2314                operation: "array index out of bounds",
2315            });
2316        }
2317
2318        if array_type.n > 63 {
2319            return Err(ReflectError::OperationFailed {
2320                shape: frame.shape,
2321                operation: "arrays larger than 63 elements are not yet supported",
2322            });
2323        }
2324
2325        // Ensure frame is in Array state
2326        match &frame.tracker {
2327            Tracker::Uninit => {
2328                // this is fine
2329                frame.tracker = Tracker::Array {
2330                    iset: ISet::default(),
2331                    current_child: None,
2332                };
2333            }
2334            Tracker::Array { .. } => {
2335                // fine too
2336            }
2337            _other => {
2338                return Err(ReflectError::OperationFailed {
2339                    shape: frame.shape,
2340                    operation: "unexpected tracker state: expected Uninit or Array",
2341                });
2342            }
2343        }
2344
2345        match &mut frame.tracker {
2346            Tracker::Array {
2347                iset,
2348                current_child,
2349            } => {
2350                *current_child = Some(idx);
2351                let was_field_init = iset.get(idx);
2352
2353                // Calculate the offset for this array element
2354                let Ok(element_layout) = array_type.t.layout.sized_layout() else {
2355                    return Err(ReflectError::Unsized {
2356                        shape: array_type.t,
2357                        operation: "begin_nth_element, calculating array element offset",
2358                    });
2359                };
2360                let offset = element_layout.size() * idx;
2361                let element_data = unsafe { frame.data.field_uninit_at(offset) };
2362
2363                let mut next_frame = Frame::new(element_data, array_type.t, FrameOwnership::Field);
2364                if was_field_init {
2365                    // safety: `iset` said it was initialized already
2366                    unsafe {
2367                        next_frame.mark_as_init();
2368                    }
2369                }
2370                Ok(next_frame)
2371            }
2372            _ => unreachable!(),
2373        }
2374    }
2375
2376    /// Selects the nth field of an enum variant by index
2377    fn begin_nth_enum_field(
2378        frame: &mut Frame,
2379        variant: &'static Variant,
2380        idx: usize,
2381    ) -> Result<Frame, ReflectError> {
2382        if idx >= variant.data.fields.len() {
2383            return Err(ReflectError::OperationFailed {
2384                shape: frame.shape,
2385                operation: "enum field index out of bounds",
2386            });
2387        }
2388
2389        let field = &variant.data.fields[idx];
2390
2391        // Update tracker
2392        let was_field_init = match &mut frame.tracker {
2393            Tracker::Enum {
2394                data,
2395                current_child,
2396                ..
2397            } => {
2398                *current_child = Some(idx);
2399                data.get(idx)
2400            }
2401            _ => {
2402                return Err(ReflectError::OperationFailed {
2403                    shape: frame.shape,
2404                    operation: "selecting a field on an enum requires selecting a variant first",
2405                });
2406            }
2407        };
2408
2409        // SAFETY: the field offset comes from an unsafe impl of the Facet trait, we trust it.
2410        // also, we checked that the variant was selected.
2411        let field_ptr = unsafe { frame.data.field_uninit_at(field.offset) };
2412        let field_shape = field.shape;
2413
2414        let mut next_frame = Frame::new(field_ptr, field_shape, FrameOwnership::Field);
2415        if was_field_init {
2416            // SAFETY: `ISet` told us the field was initialized
2417            unsafe {
2418                next_frame.mark_as_init();
2419            }
2420        }
2421
2422        Ok(next_frame)
2423    }
2424
2425    /// Require that the partial is active
2426    #[inline]
2427    pub(crate) fn require_active(&self) -> Result<(), ReflectError> {
2428        if self.state == PartialState::Active {
2429            Ok(())
2430        } else {
2431            Err(ReflectError::InvariantViolation {
2432                invariant: "Cannot use Partial after it has been built or poisoned",
2433            })
2434        }
2435    }
2436}