• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

facet-rs / facet / 19774894729

28 Nov 2025 10:22PM UTC coverage: 59.711% (-0.6%) from 60.346%
19774894729

push

github

fasterthanlime
Add DynamicValue support for deserializing into facet_value::Value

This adds support for deserializing JSON (and potentially other formats)
into facet_value::Value without format crates needing to depend on facet-value.

Key changes:
- Add Def::DynamicValue variant with vtable for building dynamic values
- Implement Facet trait for Value in facet-value
- Extend Partial to handle DynamicValue scalars via set_into_dynamic_value
- Add deserialize_dynamic_value handler in facet-json

Currently supports scalar values (null, bool, numbers, strings).
Arrays and objects are stubbed out with TODO errors.

451 of 922 new or added lines in 20 files covered. (48.92%)

29 existing lines in 3 files now uncovered.

16657 of 27896 relevant lines covered (59.71%)

153.76 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

73.76
/facet-reflect/src/partial/partial_api/internal.rs
1
use super::*;
2

3
////////////////////////////////////////////////////////////////////////////////////////////////////
4
// Internal methods
5
////////////////////////////////////////////////////////////////////////////////////////////////////
6
impl<'facet> Partial<'facet> {
7
    /// Preconditions:
8
    ///
9
    /// - `require_active()` check was made
10
    /// - frame.shape.ty is an Enum
11
    /// - `discriminant` is a valid discriminant
12
    ///
13
    /// Panics if current tracker is anything other than `Uninit`
14
    /// (switching variants is not supported for now).
15
    pub(crate) fn select_variant_internal(
208✔
16
        &mut self,
208✔
17
        enum_type: &EnumType,
208✔
18
        variant: &'static Variant,
208✔
19
    ) -> Result<(), ReflectError> {
208✔
20
        // Check all invariants early before making any changes
21
        let frame = self.frames().last().unwrap();
208✔
22

23
        // Check enum representation early
24
        match enum_type.enum_repr {
208✔
25
            EnumRepr::RustNPO => {
26
                return Err(ReflectError::OperationFailed {
×
27
                    shape: frame.shape,
×
28
                    operation: "RustNPO enums are not supported for incremental building",
×
29
                });
×
30
            }
31
            EnumRepr::U8
32
            | EnumRepr::U16
33
            | EnumRepr::U32
34
            | EnumRepr::U64
35
            | EnumRepr::I8
36
            | EnumRepr::I16
37
            | EnumRepr::I32
38
            | EnumRepr::I64
39
            | EnumRepr::USize
40
            | EnumRepr::ISize => {
208✔
41
                // These are supported, continue
208✔
42
            }
208✔
43
        }
44

45
        let Some(discriminant) = variant.discriminant else {
208✔
46
            return Err(ReflectError::OperationFailed {
×
47
                shape: frame.shape,
×
48
                operation: "trying to select an enum variant without a discriminant",
×
49
            });
×
50
        };
51

52
        // All checks passed, now we can safely make changes
53
        let fr = self.frames_mut().last_mut().unwrap();
208✔
54

55
        // Write the discriminant to memory
56
        unsafe {
57
            match enum_type.enum_repr {
208✔
58
                EnumRepr::U8 => {
178✔
59
                    let ptr = fr.data.as_mut_byte_ptr();
178✔
60
                    *ptr = discriminant as u8;
178✔
61
                }
178✔
62
                EnumRepr::U16 => {
2✔
63
                    let ptr = fr.data.as_mut_byte_ptr() as *mut u16;
2✔
64
                    *ptr = discriminant as u16;
2✔
65
                }
2✔
66
                EnumRepr::U32 => {
23✔
67
                    let ptr = fr.data.as_mut_byte_ptr() as *mut u32;
23✔
68
                    *ptr = discriminant as u32;
23✔
69
                }
23✔
70
                EnumRepr::U64 => {
×
71
                    let ptr = fr.data.as_mut_byte_ptr() as *mut u64;
×
72
                    *ptr = discriminant as u64;
×
73
                }
×
74
                EnumRepr::I8 => {
×
75
                    let ptr = fr.data.as_mut_byte_ptr() as *mut i8;
×
76
                    *ptr = discriminant as i8;
×
77
                }
×
78
                EnumRepr::I16 => {
4✔
79
                    let ptr = fr.data.as_mut_byte_ptr() as *mut i16;
4✔
80
                    *ptr = discriminant as i16;
4✔
81
                }
4✔
82
                EnumRepr::I32 => {
1✔
83
                    let ptr = fr.data.as_mut_byte_ptr() as *mut i32;
1✔
84
                    *ptr = discriminant as i32;
1✔
85
                }
1✔
86
                EnumRepr::I64 => {
×
87
                    let ptr = fr.data.as_mut_byte_ptr() as *mut i64;
×
88
                    *ptr = discriminant;
×
89
                }
×
90
                EnumRepr::USize => {
×
91
                    let ptr = fr.data.as_mut_byte_ptr() as *mut usize;
×
92
                    *ptr = discriminant as usize;
×
93
                }
×
94
                EnumRepr::ISize => {
×
95
                    let ptr = fr.data.as_mut_byte_ptr() as *mut isize;
×
96
                    *ptr = discriminant as isize;
×
97
                }
×
98
                _ => unreachable!("Already checked enum representation above"),
×
99
            }
100
        }
101

102
        // Update tracker to track the variant
103
        fr.tracker = Tracker::Enum {
208✔
104
            variant,
208✔
105
            data: ISet::new(variant.data.fields.len()),
208✔
106
            current_child: None,
208✔
107
        };
208✔
108

109
        Ok(())
208✔
110
    }
208✔
111

112
    /// Used by `begin_field` etc. to get a list of fields to look through, errors out
113
    /// if we're not pointing to a struct or an enum with an already-selected variant
114
    pub(crate) fn get_fields(&self) -> Result<&'static [Field], ReflectError> {
1,906✔
115
        let frame = self.frames().last().unwrap();
1,906✔
116
        match frame.shape.ty {
1,906✔
117
            Type::Primitive(_) => Err(ReflectError::OperationFailed {
1✔
118
                shape: frame.shape,
1✔
119
                operation: "cannot select a field from a primitive type",
1✔
120
            }),
1✔
121
            Type::Sequence(_) => Err(ReflectError::OperationFailed {
×
122
                shape: frame.shape,
×
123
                operation: "cannot select a field from a sequence type",
×
124
            }),
×
125
            Type::User(user_type) => match user_type {
1,905✔
126
                UserType::Struct(struct_type) => Ok(struct_type.fields),
1,744✔
127
                UserType::Enum(_) => {
128
                    let Tracker::Enum { variant, .. } = &frame.tracker else {
159✔
129
                        return Err(ReflectError::OperationFailed {
1✔
130
                            shape: frame.shape,
1✔
131
                            operation: "must select variant before selecting enum fields",
1✔
132
                        });
1✔
133
                    };
134
                    Ok(variant.data.fields)
158✔
135
                }
136
                UserType::Union(_) => Err(ReflectError::OperationFailed {
×
137
                    shape: frame.shape,
×
138
                    operation: "cannot select a field from a union type",
×
139
                }),
×
140
                UserType::Opaque => Err(ReflectError::OperationFailed {
2✔
141
                    shape: frame.shape,
2✔
142
                    operation: "opaque types cannot be reflected upon",
2✔
143
                }),
2✔
144
            },
145
            Type::Pointer(_) => Err(ReflectError::OperationFailed {
×
146
                shape: frame.shape,
×
147
                operation: "cannot select a field from a pointer type",
×
148
            }),
×
149
        }
150
    }
1,906✔
151

152
    /// Selects the nth field of a struct by index
153
    pub(crate) fn begin_nth_struct_field(
1,955✔
154
        frame: &mut Frame,
1,955✔
155
        struct_type: StructType,
1,955✔
156
        idx: usize,
1,955✔
157
    ) -> Result<Frame, ReflectError> {
1,955✔
158
        if idx >= struct_type.fields.len() {
1,955✔
159
            return Err(ReflectError::OperationFailed {
×
160
                shape: frame.shape,
×
161
                operation: "field index out of bounds",
×
162
            });
×
163
        }
1,955✔
164
        let field = &struct_type.fields[idx];
1,955✔
165

166
        if !matches!(frame.tracker, Tracker::Struct { .. }) {
1,955✔
167
            // When transitioning from Scalar (fully initialized) to Struct tracker,
168
            // we need to mark all fields as initialized in the iset. Otherwise,
169
            // we'll lose track of which fields were initialized and may double-free.
170
            let was_fully_init = frame.is_init && matches!(frame.tracker, Tracker::Scalar);
1,245✔
171
            let mut iset = ISet::new(struct_type.fields.len());
1,245✔
172
            if was_fully_init {
1,245✔
173
                iset.set_all();
×
174
            }
1,245✔
175
            frame.tracker = Tracker::Struct {
1,245✔
176
                iset,
1,245✔
177
                current_child: None,
1,245✔
178
            }
1,245✔
179
        }
710✔
180

181
        let was_field_init = match &mut frame.tracker {
1,955✔
182
            Tracker::Struct {
183
                iset,
1,955✔
184
                current_child,
1,955✔
185
            } => {
186
                *current_child = Some(idx);
1,955✔
187
                let was_init = iset.get(idx);
1,955✔
188
                iset.unset(idx); // Parent relinquishes responsibility
1,955✔
189
                was_init
1,955✔
190
            }
191
            _ => unreachable!(),
×
192
        };
193

194
        // Push a new frame for this field onto the frames stack.
195
        let field_ptr = unsafe { frame.data.field_uninit_at(field.offset) };
1,955✔
196
        let field_shape = field.shape();
1,955✔
197

198
        let mut next_frame = Frame::new(
1,955✔
199
            field_ptr,
1,955✔
200
            field_shape,
1,955✔
201
            FrameOwnership::Field { field_idx: idx },
1,955✔
202
        );
203
        if was_field_init {
1,955✔
204
            unsafe {
11✔
205
                // the struct field tracker said so!
11✔
206
                next_frame.mark_as_init();
11✔
207
            }
11✔
208
        }
1,944✔
209

210
        Ok(next_frame)
1,955✔
211
    }
1,955✔
212

213
    /// Selects the nth element of an array by index
214
    pub(crate) fn begin_nth_array_element(
93✔
215
        frame: &mut Frame,
93✔
216
        array_type: ArrayType,
93✔
217
        idx: usize,
93✔
218
    ) -> Result<Frame, ReflectError> {
93✔
219
        if idx >= array_type.n {
93✔
220
            return Err(ReflectError::OperationFailed {
1✔
221
                shape: frame.shape,
1✔
222
                operation: "array index out of bounds",
1✔
223
            });
1✔
224
        }
92✔
225

226
        if array_type.n > 63 {
92✔
227
            return Err(ReflectError::OperationFailed {
×
228
                shape: frame.shape,
×
229
                operation: "arrays larger than 63 elements are not yet supported",
×
230
            });
×
231
        }
92✔
232

233
        // Ensure frame is in Array state
234
        match &frame.tracker {
36✔
235
            Tracker::Scalar if !frame.is_init => {
36✔
236
                // this is fine, transition to Array tracker
36✔
237
                frame.tracker = Tracker::Array {
36✔
238
                    iset: ISet::default(),
36✔
239
                    current_child: None,
36✔
240
                };
36✔
241
            }
36✔
242
            Tracker::Array { .. } => {
56✔
243
                // fine too
56✔
244
            }
56✔
245
            _other => {
×
246
                return Err(ReflectError::OperationFailed {
×
247
                    shape: frame.shape,
×
NEW
248
                    operation: "unexpected tracker state: expected uninitialized Scalar or Array",
×
249
                });
×
250
            }
251
        }
252

253
        match &mut frame.tracker {
92✔
254
            Tracker::Array {
255
                iset,
92✔
256
                current_child,
92✔
257
            } => {
258
                *current_child = Some(idx);
92✔
259
                let was_field_init = iset.get(idx);
92✔
260
                iset.unset(idx); // Parent relinquishes responsibility
92✔
261

262
                // Calculate the offset for this array element
263
                let Ok(element_layout) = array_type.t.layout.sized_layout() else {
92✔
264
                    return Err(ReflectError::Unsized {
×
265
                        shape: array_type.t,
×
266
                        operation: "begin_nth_element, calculating array element offset",
×
267
                    });
×
268
                };
269
                let offset = element_layout.size() * idx;
92✔
270
                let element_data = unsafe { frame.data.field_uninit_at(offset) };
92✔
271

272
                let mut next_frame = Frame::new(
92✔
273
                    element_data,
92✔
274
                    array_type.t,
92✔
275
                    FrameOwnership::Field { field_idx: idx },
92✔
276
                );
277
                if was_field_init {
92✔
278
                    // safety: `iset` said it was initialized already
279
                    unsafe {
2✔
280
                        next_frame.mark_as_init();
2✔
281
                    }
2✔
282
                }
90✔
283
                Ok(next_frame)
92✔
284
            }
285
            _ => unreachable!(),
×
286
        }
287
    }
93✔
288

289
    /// Selects the nth field of an enum variant by index
290
    pub(crate) fn begin_nth_enum_field(
208✔
291
        frame: &mut Frame,
208✔
292
        variant: &'static Variant,
208✔
293
        idx: usize,
208✔
294
    ) -> Result<Frame, ReflectError> {
208✔
295
        if idx >= variant.data.fields.len() {
208✔
296
            return Err(ReflectError::OperationFailed {
×
297
                shape: frame.shape,
×
298
                operation: "enum field index out of bounds",
×
299
            });
×
300
        }
208✔
301

302
        let field = &variant.data.fields[idx];
208✔
303

304
        // Update tracker
305
        let was_field_init = match &mut frame.tracker {
208✔
306
            Tracker::Enum {
307
                data,
208✔
308
                current_child,
208✔
309
                ..
310
            } => {
311
                *current_child = Some(idx);
208✔
312
                let was_init = data.get(idx);
208✔
313
                data.unset(idx); // Parent relinquishes responsibility
208✔
314
                was_init
208✔
315
            }
316
            _ => {
317
                return Err(ReflectError::OperationFailed {
×
318
                    shape: frame.shape,
×
319
                    operation: "selecting a field on an enum requires selecting a variant first",
×
320
                });
×
321
            }
322
        };
323

324
        // SAFETY: the field offset comes from an unsafe impl of the Facet trait, we trust it.
325
        // also, we checked that the variant was selected.
326
        let field_ptr = unsafe { frame.data.field_uninit_at(field.offset) };
208✔
327
        let field_shape = field.shape();
208✔
328

329
        let mut next_frame = Frame::new(
208✔
330
            field_ptr,
208✔
331
            field_shape,
208✔
332
            FrameOwnership::Field { field_idx: idx },
208✔
333
        );
334
        if was_field_init {
208✔
335
            // SAFETY: `ISet` told us the field was initialized
336
            unsafe {
1✔
337
                next_frame.mark_as_init();
1✔
338
            }
1✔
339
        }
207✔
340

341
        Ok(next_frame)
208✔
342
    }
208✔
343

344
    /// Require that the partial is active
345
    #[inline]
346
    pub(crate) fn require_active(&self) -> Result<(), ReflectError> {
15,503✔
347
        if self.state == PartialState::Active {
15,503✔
348
            Ok(())
15,502✔
349
        } else {
350
            Err(ReflectError::InvariantViolation {
1✔
351
                invariant: "Cannot use Partial after it has been built or poisoned",
1✔
352
            })
1✔
353
        }
354
    }
15,503✔
355

356
    /// Prepares the current frame for re-initialization by dropping any existing
357
    /// value and unmarking it in the parent's iset.
358
    ///
359
    /// This should be called at the start of `begin_*` methods that support
360
    /// re-initialization (e.g., `begin_some`, `begin_inner`, `begin_smart_ptr`).
361
    ///
362
    /// Returns `true` if cleanup was performed (frame was previously initialized),
363
    /// `false` if the frame was not initialized.
364
    pub(crate) fn prepare_for_reinitialization(&mut self) -> bool {
89✔
365
        let frame = self.frames().last().unwrap();
89✔
366
        if !frame.is_init {
89✔
367
            return false;
86✔
368
        }
3✔
369

370
        // Clean up any partial state (e.g., map key/value buffers mid-insert)
371
        // before dropping the main value
372
        let frame = self.frames_mut().last_mut().unwrap();
3✔
373
        frame.cleanup_partial_state();
3✔
374
        let frame = self.frames().last().unwrap();
3✔
375

376
        // Drop the existing value
377
        if let Some(drop_fn) = frame.shape.vtable.drop_in_place {
3✔
378
            unsafe { drop_fn(frame.data.assume_init()) };
3✔
379
        }
3✔
380

381
        // Note: With the ownership transfer model, parent's iset was already cleared
382
        // when we entered this field, so no need to unmark here.
383

384
        // Reset the frame's state
385
        let frame = self.frames_mut().last_mut().unwrap();
3✔
386
        frame.is_init = false;
3✔
387
        frame.tracker = Tracker::Scalar;
3✔
388

389
        true
3✔
390
    }
89✔
391
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc