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 suceeds, 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
300////////////////////////////////////////////////////////////////////////////////////////////////////
301// Smart pointers
302////////////////////////////////////////////////////////////////////////////////////////////////////
303impl<'facet, T: ?Sized> TypedPartial<'facet, T> {
304 /// Pushes a frame to initialize the inner value of a smart pointer (`Box<T>`, `Arc<T>`, etc.)
305 #[inline]
306 pub fn begin_smart_ptr(&mut self) -> Result<&mut Self, ReflectError> {
307 self.inner.begin_smart_ptr()?;
308 Ok(self)
309 }
310}
311
312////////////////////////////////////////////////////////////////////////////////////////////////////
313// Lists
314////////////////////////////////////////////////////////////////////////////////////////////////////
315impl<'facet, T: ?Sized> TypedPartial<'facet, T> {
316 /// Initializes a list (Vec, etc.) if it hasn't been initialized before.
317 /// This is a prerequisite to `begin_push_item`/`set`/`end` or the shorthand
318 /// `push`.
319 ///
320 /// `begin_list` does not clear the list if it was previously initialized.
321 /// `begin_list` does not push a new frame to the stack, and thus does not
322 /// require `end` to be called afterwards.
323 #[inline]
324 pub fn begin_list(&mut self) -> Result<&mut Self, ReflectError> {
325 self.inner.begin_list()?;
326 Ok(self)
327 }
328
329 /// Pushes an element to the list
330 /// The element should be set using `set()` or similar methods, then `pop()` to complete
331 #[inline]
332 pub fn begin_list_item(&mut self) -> Result<&mut Self, ReflectError> {
333 self.inner.begin_list_item()?;
334 Ok(self)
335 }
336}
337
338////////////////////////////////////////////////////////////////////////////////////////////////////
339// Maps
340////////////////////////////////////////////////////////////////////////////////////////////////////
341impl<'facet, T: ?Sized> TypedPartial<'facet, T> {
342 /// Begins a map initialization operation
343 ///
344 /// This initializes the map with default capacity and allows inserting key-value pairs
345 /// It does _not_ push a new frame onto the stack.
346 #[inline]
347 pub fn begin_map(&mut self) -> Result<&mut Self, ReflectError> {
348 self.inner.begin_map()?;
349 Ok(self)
350 }
351
352 /// Pushes a frame for the map key. After that, `set()` should be called
353 /// (or the key should be initialized somehow) and `end()` should be called
354 /// to pop the frame.
355 #[inline]
356 pub fn begin_key(&mut self) -> Result<&mut Self, ReflectError> {
357 self.inner.begin_key()?;
358 Ok(self)
359 }
360
361 /// Pushes a frame for the map value
362 /// Must be called after the key has been set and popped
363 #[inline]
364 pub fn begin_value(&mut self) -> Result<&mut Self, ReflectError> {
365 self.inner.begin_value()?;
366 Ok(self)
367 }
368}
369
370////////////////////////////////////////////////////////////////////////////////////////////////////
371// Option / inner
372////////////////////////////////////////////////////////////////////////////////////////////////////
373impl<'facet, T: ?Sized> TypedPartial<'facet, T> {
374 /// Begin building the `Some` variant of an `Option`
375 #[inline]
376 pub fn begin_some(&mut self) -> Result<&mut Self, ReflectError> {
377 self.inner.begin_some()?;
378 Ok(self)
379 }
380
381 /// Begin building the inner value of a wrapper type
382 #[inline]
383 pub fn begin_inner(&mut self) -> Result<&mut Self, ReflectError> {
384 self.inner.begin_inner()?;
385 Ok(self)
386 }
387}
388
389////////////////////////////////////////////////////////////////////////////////////////////////////
390// Shorthands
391////////////////////////////////////////////////////////////////////////////////////////////////////
392impl<'facet, T: ?Sized> TypedPartial<'facet, T> {
393 /// Convenience shortcut: sets the field at index `idx` directly to value, popping after.
394 #[inline]
395 pub fn set_nth_field<U>(&mut self, idx: usize, value: U) -> Result<&mut Self, ReflectError>
396 where
397 U: Facet<'facet>,
398 {
399 self.inner.set_nth_field(idx, value)?;
400 Ok(self)
401 }
402
403 /// Convenience shortcut: sets the named field to value, popping after.
404 #[inline]
405 pub fn set_field<U>(&mut self, field_name: &str, value: U) -> Result<&mut Self, ReflectError>
406 where
407 U: Facet<'facet>,
408 {
409 self.inner.set_field(field_name, value)?;
410 Ok(self)
411 }
412
413 /// Convenience shortcut: sets the key for a map key-value insertion, then pops after.
414 #[inline]
415 pub fn set_key<U>(&mut self, value: U) -> Result<&mut Self, ReflectError>
416 where
417 U: Facet<'facet>,
418 {
419 self.inner.set_key(value)?;
420 Ok(self)
421 }
422
423 /// Convenience shortcut: sets the value for a map key-value insertion, then pops after.
424 #[inline]
425 pub fn set_value<U>(&mut self, value: U) -> Result<&mut Self, ReflectError>
426 where
427 U: Facet<'facet>,
428 {
429 self.inner.set_value(value)?;
430 Ok(self)
431 }
432
433 /// Shorthand for: begin_list_item(), set(), end(), useful when pushing a scalar
434 #[inline]
435 pub fn push<U>(&mut self, value: U) -> Result<&mut Self, ReflectError>
436 where
437 U: Facet<'facet>,
438 {
439 self.inner.push(value)?;
440 Ok(self)
441 }
442}
443
444impl<'facet, T> core::fmt::Debug for TypedPartial<'facet, T> {
445 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
446 f.debug_struct("TypedPartial")
447 .field("shape", &self.inner.frames.last().map(|frame| frame.shape))
448 .finish()
449 }
450}