facet_reflect/partial/
typed.rs

1use alloc::{boxed::Box, string::String};
2
3use crate::{Partial, Peek, ReflectError, trace};
4use core::marker::PhantomData;
5use facet_core::{Facet, PtrConst, PtrUninit, Shape, Variant};
6
7/// A typed wrapper around `Partial`, for when you want to statically
8/// ensure that `build` gives you the proper type.
9pub struct TypedPartial<'facet, T: ?Sized> {
10    pub(crate) inner: Partial<'facet>,
11    pub(crate) phantom: PhantomData<T>,
12}
13
14impl<'facet, T> TypedPartial<'facet, T> {
15    /// Borrows the inner [Partial] mutably
16    pub fn inner_mut(&mut self) -> &mut Partial<'facet> {
17        &mut self.inner
18    }
19}
20
21////////////////////////////////////////////////////////////////////////////////////////////////////
22// Misc.
23////////////////////////////////////////////////////////////////////////////////////////////////////
24impl<'facet, T: ?Sized> TypedPartial<'facet, T> {
25    /// Returns the current frame count (depth of nesting)
26    ///
27    /// The initial frame count is 1 — `begin_field` would push a new frame,
28    /// bringing it to 2, then `end` would bring it back to `1`.
29    ///
30    /// This is an implementation detail of `Partial`, kinda, but deserializers
31    /// might use this for debug assertions, to make sure the state is what
32    /// they think it is.
33    #[inline]
34    pub fn frame_count(&self) -> usize {
35        self.inner.frame_count()
36    }
37
38    /// Returns the shape of the current frame.
39    #[inline]
40    pub fn shape(&self) -> &'static Shape {
41        self.inner.shape()
42    }
43
44    /// Pops the current frame off the stack, indicating we're done initializing the current field
45    #[inline]
46    pub fn end(&mut self) -> Result<&mut Self, ReflectError> {
47        self.inner.end()?;
48        Ok(self)
49    }
50
51    /// Returns a human-readable path representing the current traversal in the builder,
52    /// e.g., `RootStruct.fieldName[index].subfield`.
53    pub fn path(&self) -> String {
54        self.inner.path()
55    }
56}
57
58////////////////////////////////////////////////////////////////////////////////////////////////////
59// Build
60////////////////////////////////////////////////////////////////////////////////////////////////////
61impl<'facet, T> TypedPartial<'facet, T> {
62    /// Builds the value and returns a `Box<T>`
63    pub fn build(&mut self) -> Result<Box<T>, ReflectError>
64    where
65        T: Facet<'facet>,
66    {
67        self.inner.require_active()?;
68
69        trace!(
70            "TypedPartial::build: Building value for type {} which should == {}",
71            T::SHAPE,
72            self.inner.shape()
73        );
74        let heap_value = self.inner.build()?;
75        trace!(
76            "TypedPartial::build: Built heap value with shape: {}",
77            heap_value.shape()
78        );
79        // Safety: HeapValue was constructed from T and the shape layout is correct.
80        let result = unsafe { heap_value.into_box_unchecked::<T>() };
81        trace!("TypedPartial::build: Successfully converted to Box<T>");
82        Ok(result)
83    }
84}
85
86////////////////////////////////////////////////////////////////////////////////////////////////////
87// `Set` and set helpers
88////////////////////////////////////////////////////////////////////////////////////////////////////
89impl<'facet, T: ?Sized> TypedPartial<'facet, T> {
90    /// Sets a value wholesale into the current frame.
91    ///
92    /// If the current frame was already initialized, the previous value is
93    /// dropped. If it was partially initialized, the fields that were initialized
94    /// are dropped, etc.
95    #[inline]
96    pub fn set<U>(&mut self, value: U) -> Result<&mut Self, ReflectError>
97    where
98        U: Facet<'facet>,
99    {
100        self.inner.set(value)?;
101        Ok(self)
102    }
103
104    /// Sets a value into the current frame by shape, for shape-based operations
105    ///
106    /// If this returns Ok, then `src_value` has been moved out of
107    ///
108    /// # Safety
109    ///
110    /// The caller must ensure that `src_value` points to a valid instance of a value
111    /// whose memory layout and type matches `src_shape`, and that this value can be
112    /// safely copied (bitwise) into the destination specified by the Partial's current frame.
113    /// No automatic drop will be performed for any existing value, so calling this on an
114    /// already-initialized destination may result in leaks or double drops if misused.
115    /// After a successful call, the ownership of the value at `src_value` is effectively moved
116    /// into the Partial (i.e., the destination), and the original value should not be used
117    /// or dropped by the caller; consider using `core::mem::forget` on the passed value.
118    /// If an error is returned, the destination remains unmodified and safe for future operations.
119    #[inline]
120    pub unsafe fn set_shape(
121        &mut self,
122        src_value: PtrConst<'_>,
123        src_shape: &'static Shape,
124    ) -> Result<&mut Self, ReflectError> {
125        unsafe { self.inner.set_shape(src_value, src_shape)? };
126        Ok(self)
127    }
128
129    /// Sets the current frame using a function that initializes the value
130    ///
131    /// # Safety
132    ///
133    /// If `f` returns Ok(), it is assumed that it initialized the passed pointer fully and with a
134    /// value of the right type.
135    ///
136    /// If `f` returns Err(), it is assumed that it did NOT initialize the passed pointer and that
137    /// there is no need to drop it in place.
138    #[inline]
139    pub unsafe fn set_from_function<F>(&mut self, f: F) -> Result<&mut Self, ReflectError>
140    where
141        F: FnOnce(PtrUninit<'_>) -> Result<(), ReflectError>,
142    {
143        unsafe {
144            self.inner.set_from_function(f)?;
145        }
146        Ok(self)
147    }
148
149    /// Sets the current frame to its default value using `default_in_place` from the
150    /// vtable.
151    ///
152    /// Note: if you have `struct S { field: F }`, and `F` does not implement `Default`
153    /// but `S` does, this doesn't magically uses S's `Default` implementation to get a value
154    /// for `field`.
155    ///
156    /// If the current frame's shape does not implement `Default`, then this returns an error.
157    #[inline]
158    pub fn set_default(&mut self) -> Result<&mut Self, ReflectError> {
159        self.inner.set_default()?;
160        Ok(self)
161    }
162
163    /// Copy a value from a Peek into the current frame.
164    ///
165    /// # Invariants
166    ///
167    /// `peek` must be a thin pointer, otherwise this panics.
168    ///
169    /// # Safety
170    ///
171    /// If this succeeds, the value `Peek` points to has been moved out of, and
172    /// as such, should not be dropped (but should be deallocated).
173    pub unsafe fn set_from_peek(&mut self, peek: &Peek<'_, '_>) -> Result<&mut Self, ReflectError> {
174        unsafe {
175            self.inner.set_from_peek(peek)?;
176        }
177        Ok(self)
178    }
179
180    /// Parses a string value into the current frame using the type's ParseFn from the vtable.
181    ///
182    /// If the current frame was previously initialized, its contents are dropped in place.
183    #[inline]
184    pub fn parse_from_str(&mut self, s: &str) -> Result<&mut Self, ReflectError> {
185        self.inner.parse_from_str(s)?;
186        Ok(self)
187    }
188}
189
190////////////////////////////////////////////////////////////////////////////////////////////////////
191// Enum variant selection
192////////////////////////////////////////////////////////////////////////////////////////////////////
193impl<'facet, T: ?Sized> TypedPartial<'facet, T> {
194    /// Get the currently selected variant for an enum
195    #[inline]
196    pub fn selected_variant(&self) -> Option<Variant> {
197        self.inner.selected_variant()
198    }
199
200    /// Find a variant by name in the current enum
201    #[inline]
202    pub fn find_variant(&self, variant_name: &str) -> Option<(usize, &'static Variant)> {
203        self.inner.find_variant(variant_name)
204    }
205
206    /// Assuming the current frame is an enum, this selects a variant by index
207    /// (0-based, in declaration order).
208    ///
209    /// For example:
210    ///
211    /// ```rust,no_run
212    /// enum E { A, B, C }
213    /// ```
214    ///
215    /// Calling `select_nth_variant(2)` would select variant `C`.
216    ///
217    /// This will return an error if the current frame is anything other than fully-uninitialized.
218    /// In other words, it's not possible to "switch to a different variant" once you've selected one.
219    ///
220    /// This does _not_ push a frame on the stack.
221    #[inline]
222    pub fn select_nth_variant(&mut self, index: usize) -> Result<&mut Self, ReflectError> {
223        self.inner.select_nth_variant(index)?;
224        Ok(self)
225    }
226
227    /// Pushes a variant for enum initialization by name
228    ///
229    /// See [Self::select_nth_variant] for more notes.
230    #[inline]
231    pub fn select_variant_named(&mut self, variant_name: &str) -> Result<&mut Self, ReflectError> {
232        self.inner.select_variant_named(variant_name)?;
233        Ok(self)
234    }
235
236    /// Selects a given enum variant by discriminant. If none of the variants
237    /// of the frame's enum have that discriminant, this returns an error.
238    ///
239    /// See [Self::select_nth_variant] for more notes.
240    #[inline]
241    pub fn select_variant(&mut self, discriminant: i64) -> Result<&mut Self, ReflectError> {
242        self.inner.select_variant(discriminant)?;
243        Ok(self)
244    }
245}
246
247////////////////////////////////////////////////////////////////////////////////////////////////////
248// Field selection
249////////////////////////////////////////////////////////////////////////////////////////////////////
250impl<'facet, T: ?Sized> TypedPartial<'facet, T> {
251    /// Find the index of a field by name in the current struct
252    ///
253    /// If the current frame isn't a struct or an enum (with a selected variant)
254    /// then this returns `None` for sure.
255    #[inline]
256    pub fn field_index(&self, field_name: &str) -> Option<usize> {
257        self.inner.field_index(field_name)
258    }
259
260    /// Check if a struct field at the given index has been set
261    #[inline]
262    pub fn is_field_set(&self, index: usize) -> Result<bool, ReflectError> {
263        self.inner.is_field_set(index)
264    }
265
266    /// Selects a field (by name) of a struct or enum data.
267    ///
268    /// For enums, the variant needs to be selected first, see [Self::select_nth_variant]
269    /// and friends.
270    #[inline]
271    pub fn begin_field(&mut self, field_name: &str) -> Result<&mut Self, ReflectError> {
272        self.inner.begin_field(field_name)?;
273        Ok(self)
274    }
275
276    /// Begins the nth field of a struct, enum variant, or array, by index.
277    ///
278    /// On success, this pushes a new frame which must be ended with a call to [Partial::end]
279    #[inline]
280    pub fn begin_nth_field(&mut self, idx: usize) -> Result<&mut Self, ReflectError> {
281        self.inner.begin_nth_field(idx)?;
282        Ok(self)
283    }
284
285    /// Sets the given field to its default value, preferring:
286    ///
287    ///   * A `default = some_fn()` function
288    ///   * The field's `Default` implementation if any
289    ///
290    /// But without going all the way up to the parent struct's `Default` impl.
291    ///
292    /// Errors out if idx is out of bound, if the field has no default method or Default impl.
293    #[inline]
294    pub fn set_nth_field_to_default(&mut self, idx: usize) -> Result<&mut Self, ReflectError> {
295        self.inner.set_nth_field_to_default(idx)?;
296        Ok(self)
297    }
298
299    /// Given a `Partial` for the same shape, and assuming that partial has the nth
300    /// field initialized, move the value from `src` to `self`, marking it as deinitialized
301    /// in `src`.
302    #[inline]
303    pub fn steal_nth_field(
304        &mut self,
305        src: &mut TypedPartial<T>,
306        field_index: usize,
307    ) -> Result<&mut Self, ReflectError> {
308        self.inner.steal_nth_field(&mut src.inner, field_index)?;
309        Ok(self)
310    }
311
312    /// For a field that supports custom deserialization via the `deserialize_with` attribute begin
313    /// the process of constructing the shape to be used as input to the `deserialize_with` method.
314    /// Calling end after constructing the shape will pass it to the `deserialize_with` associated method
315    /// and store the result in the frame's pointer.
316    #[inline]
317    pub fn begin_custom_deserialization(&mut self) -> Result<&mut Self, ReflectError> {
318        self.inner.begin_custom_deserialization()?;
319        Ok(self)
320    }
321}
322
323////////////////////////////////////////////////////////////////////////////////////////////////////
324// Smart pointers
325////////////////////////////////////////////////////////////////////////////////////////////////////
326impl<'facet, T: ?Sized> TypedPartial<'facet, T> {
327    /// Pushes a frame to initialize the inner value of a smart pointer (`Box<T>`, `Arc<T>`, etc.)
328    #[inline]
329    pub fn begin_smart_ptr(&mut self) -> Result<&mut Self, ReflectError> {
330        self.inner.begin_smart_ptr()?;
331        Ok(self)
332    }
333}
334
335////////////////////////////////////////////////////////////////////////////////////////////////////
336// Lists
337////////////////////////////////////////////////////////////////////////////////////////////////////
338impl<'facet, T: ?Sized> TypedPartial<'facet, T> {
339    /// Initializes a list (Vec, etc.) if it hasn't been initialized before.
340    /// This is a prerequisite to `begin_push_item`/`set`/`end` or the shorthand
341    /// `push`.
342    ///
343    /// `begin_list` does not clear the list if it was previously initialized.
344    /// `begin_list` does not push a new frame to the stack, and thus does not
345    /// require `end` to be called afterwards.
346    #[inline]
347    pub fn begin_list(&mut self) -> Result<&mut Self, ReflectError> {
348        self.inner.begin_list()?;
349        Ok(self)
350    }
351
352    /// Pushes an element to the list
353    /// The element should be set using `set()` or similar methods, then `pop()` to complete
354    #[inline]
355    pub fn begin_list_item(&mut self) -> Result<&mut Self, ReflectError> {
356        self.inner.begin_list_item()?;
357        Ok(self)
358    }
359}
360
361////////////////////////////////////////////////////////////////////////////////////////////////////
362// Maps
363////////////////////////////////////////////////////////////////////////////////////////////////////
364impl<'facet, T: ?Sized> TypedPartial<'facet, T> {
365    /// Begins a map initialization operation
366    ///
367    /// This initializes the map with default capacity and allows inserting key-value pairs
368    /// It does _not_ push a new frame onto the stack.
369    #[inline]
370    pub fn begin_map(&mut self) -> Result<&mut Self, ReflectError> {
371        self.inner.begin_map()?;
372        Ok(self)
373    }
374
375    /// Pushes a frame for the map key. After that, `set()` should be called
376    /// (or the key should be initialized somehow) and `end()` should be called
377    /// to pop the frame.
378    #[inline]
379    pub fn begin_key(&mut self) -> Result<&mut Self, ReflectError> {
380        self.inner.begin_key()?;
381        Ok(self)
382    }
383
384    /// Pushes a frame for the map value
385    /// Must be called after the key has been set and popped
386    #[inline]
387    pub fn begin_value(&mut self) -> Result<&mut Self, ReflectError> {
388        self.inner.begin_value()?;
389        Ok(self)
390    }
391}
392
393////////////////////////////////////////////////////////////////////////////////////////////////////
394// Option / inner
395////////////////////////////////////////////////////////////////////////////////////////////////////
396impl<'facet, T: ?Sized> TypedPartial<'facet, T> {
397    /// Begin building the `Some` variant of an `Option`
398    #[inline]
399    pub fn begin_some(&mut self) -> Result<&mut Self, ReflectError> {
400        self.inner.begin_some()?;
401        Ok(self)
402    }
403
404    /// Begin building the inner value of a wrapper type
405    #[inline]
406    pub fn begin_inner(&mut self) -> Result<&mut Self, ReflectError> {
407        self.inner.begin_inner()?;
408        Ok(self)
409    }
410}
411
412////////////////////////////////////////////////////////////////////////////////////////////////////
413// Shorthands
414////////////////////////////////////////////////////////////////////////////////////////////////////
415impl<'facet, T: ?Sized> TypedPartial<'facet, T> {
416    /// Convenience shortcut: sets the field at index `idx` directly to value, popping after.
417    #[inline]
418    pub fn set_nth_field<U>(&mut self, idx: usize, value: U) -> Result<&mut Self, ReflectError>
419    where
420        U: Facet<'facet>,
421    {
422        self.inner.set_nth_field(idx, value)?;
423        Ok(self)
424    }
425
426    /// Convenience shortcut: sets the named field to value, popping after.
427    #[inline]
428    pub fn set_field<U>(&mut self, field_name: &str, value: U) -> Result<&mut Self, ReflectError>
429    where
430        U: Facet<'facet>,
431    {
432        self.inner.set_field(field_name, value)?;
433        Ok(self)
434    }
435
436    /// Convenience shortcut: sets the key for a map key-value insertion, then pops after.
437    #[inline]
438    pub fn set_key<U>(&mut self, value: U) -> Result<&mut Self, ReflectError>
439    where
440        U: Facet<'facet>,
441    {
442        self.inner.set_key(value)?;
443        Ok(self)
444    }
445
446    /// Convenience shortcut: sets the value for a map key-value insertion, then pops after.
447    #[inline]
448    pub fn set_value<U>(&mut self, value: U) -> Result<&mut Self, ReflectError>
449    where
450        U: Facet<'facet>,
451    {
452        self.inner.set_value(value)?;
453        Ok(self)
454    }
455
456    /// Shorthand for: begin_list_item(), set(), end(), useful when pushing a scalar
457    #[inline]
458    pub fn push<U>(&mut self, value: U) -> Result<&mut Self, ReflectError>
459    where
460        U: Facet<'facet>,
461    {
462        self.inner.push(value)?;
463        Ok(self)
464    }
465}
466
467impl<'facet, T> core::fmt::Debug for TypedPartial<'facet, T> {
468    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
469        f.debug_struct("TypedPartial")
470            .field("shape", &self.inner.frames.last().map(|frame| frame.shape))
471            .finish()
472    }
473}