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

facet-rs / facet / 19746156966

27 Nov 2025 07:23PM UTC coverage: 57.343% (+1.2%) from 56.098%
19746156966

push

github

fasterthanlime
Gate proptest fuzz tests behind fuzz-tests feature

These tests are very slow (1000+ cases with complex operations) and
shouldn't run in CI. Run manually with:
  cargo nextest run -p facet-reflect --features fuzz-tests

6825 of 11902 relevant lines covered (57.34%)

75.41 hits per line

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

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

3
////////////////////////////////////////////////////////////////////////////////////////////////////
4
// Field selection
5
////////////////////////////////////////////////////////////////////////////////////////////////////
6
impl Partial<'_> {
7
    /// Find the index of a field by name in the current struct
8
    ///
9
    /// If the current frame isn't a struct or an enum (with a selected variant)
10
    /// then this returns `None` for sure.
11
    pub fn field_index(&self, field_name: &str) -> Option<usize> {
×
12
        let frame = self.frames().last()?;
×
13

14
        match frame.shape.ty {
×
15
            Type::User(UserType::Struct(struct_def)) => {
×
16
                struct_def.fields.iter().position(|f| f.name == field_name)
×
17
            }
18
            Type::User(UserType::Enum(_)) => {
19
                // If we're in an enum variant, check its fields
20
                if let Tracker::Enum { variant, .. } = &frame.tracker {
×
21
                    variant
×
22
                        .data
×
23
                        .fields
×
24
                        .iter()
×
25
                        .position(|f| f.name == field_name)
×
26
                } else {
27
                    None
×
28
                }
29
            }
30
            _ => None,
×
31
        }
32
    }
×
33

34
    /// Check if a struct field at the given index has been set
35
    pub fn is_field_set(&self, index: usize) -> Result<bool, ReflectError> {
22✔
36
        let frame = self.frames().last().ok_or(ReflectError::NoActiveFrame)?;
22✔
37

38
        match &frame.tracker {
22✔
39
            Tracker::Uninit => Ok(false),
13✔
40
            Tracker::Init => Ok(true),
2✔
41
            Tracker::Struct { iset, .. } => Ok(iset.get(index)),
7✔
42
            Tracker::Enum { data, variant, .. } => {
×
43
                // Check if the field is already marked as set
44
                if data.get(index) {
×
45
                    return Ok(true);
×
46
                }
×
47

48
                // For enum variant fields that are empty structs, they are always initialized
49
                if let Some(field) = variant.data.fields.get(index) {
×
50
                    if let Type::User(UserType::Struct(field_struct)) = field.shape().ty {
×
51
                        if field_struct.fields.is_empty() {
×
52
                            return Ok(true);
×
53
                        }
×
54
                    }
×
55
                }
×
56

57
                Ok(false)
×
58
            }
59
            Tracker::Option { building_inner } => {
×
60
                // For Options, index 0 represents the inner value
61
                if index == 0 {
×
62
                    Ok(!building_inner)
×
63
                } else {
64
                    Err(ReflectError::InvalidOperation {
×
65
                        operation: "is_field_set",
×
66
                        reason: "Option only has one field (index 0)",
×
67
                    })
×
68
                }
69
            }
70
            _ => Err(ReflectError::InvalidOperation {
×
71
                operation: "is_field_set",
×
72
                reason: "Current frame is not a struct, enum variant, or option",
×
73
            }),
×
74
        }
75
    }
22✔
76

77
    /// Selects a field (by name) of a struct or enum data.
78
    ///
79
    /// For enums, the variant needs to be selected first, see [Self::select_nth_variant]
80
    /// and friends.
81
    pub fn begin_field(&mut self, field_name: &str) -> Result<&mut Self, ReflectError> {
401✔
82
        self.require_active()?;
401✔
83

84
        let frame = self.frames().last().unwrap();
401✔
85
        let fields = self.get_fields()?;
401✔
86
        let Some(idx) = fields.iter().position(|f| f.name == field_name) else {
611✔
87
            return Err(ReflectError::FieldError {
4✔
88
                shape: frame.shape,
4✔
89
                field_error: facet_core::FieldError::NoSuchField,
4✔
90
            });
4✔
91
        };
92
        self.begin_nth_field(idx)
395✔
93
    }
401✔
94

95
    /// Begins the nth field of a struct, enum variant, or array, by index.
96
    ///
97
    /// On success, this pushes a new frame which must be ended with a call to [Partial::end]
98
    pub fn begin_nth_field(&mut self, idx: usize) -> Result<&mut Self, ReflectError> {
507✔
99
        self.require_active()?;
507✔
100

101
        // In deferred mode, get the field name for path tracking and check for stored frames.
102
        // Only track the path if we're at a "navigable" level - i.e., the path length matches
103
        // the expected depth (frames.len() - 1). If we're inside a collection item, the path
104
        // will be shorter than expected, so we shouldn't add to it.
105
        let field_name = self.get_field_name_for_path(idx);
507✔
106

107
        // Update current_path in deferred mode
108
        if let FrameMode::Deferred {
109
            stack,
229✔
110
            start_depth,
229✔
111
            current_path,
229✔
112
            stored_frames,
229✔
113
            ..
114
        } = &mut self.mode
507✔
115
        {
116
            // Only track path if we're at the expected navigable depth
117
            // Path should have (frames.len() - start_depth) entries before we add this field
118
            let relative_depth = stack.len() - *start_depth;
229✔
119
            let should_track = current_path.len() == relative_depth;
229✔
120

121
            if let Some(name) = field_name {
229✔
122
                if should_track {
223✔
123
                    current_path.push(name);
215✔
124

125
                    // Check if we have a stored frame for this path
126
                    if let Some(stored_frame) = stored_frames.remove(current_path) {
215✔
127
                        trace!("begin_nth_field: Restoring stored frame for path {current_path:?}");
128

129
                        // Update parent's current_child tracking
130
                        let frame = stack.last_mut().unwrap();
47✔
131
                        frame.tracker.set_current_child(idx);
47✔
132

133
                        stack.push(stored_frame);
47✔
134
                        return Ok(self);
47✔
135
                    }
168✔
136
                }
8✔
137
            }
6✔
138
        }
278✔
139

140
        let frame = self.frames_mut().last_mut().unwrap();
460✔
141

142
        let next_frame = match frame.shape.ty {
460✔
143
            Type::User(user_type) => match user_type {
416✔
144
                UserType::Struct(struct_type) => {
354✔
145
                    Self::begin_nth_struct_field(frame, struct_type, idx)?
354✔
146
                }
147
                UserType::Enum(_) => {
148
                    // Check if we have a variant selected
149
                    match &frame.tracker {
62✔
150
                        Tracker::Enum { variant, .. } => {
62✔
151
                            Self::begin_nth_enum_field(frame, variant, idx)?
62✔
152
                        }
153
                        _ => {
154
                            return Err(ReflectError::OperationFailed {
×
155
                                shape: frame.shape,
×
156
                                operation: "must call select_variant before selecting enum fields",
×
157
                            });
×
158
                        }
159
                    }
160
                }
161
                UserType::Union(_) => {
162
                    return Err(ReflectError::OperationFailed {
×
163
                        shape: frame.shape,
×
164
                        operation: "cannot select a field from a union",
×
165
                    });
×
166
                }
167
                UserType::Opaque => {
168
                    return Err(ReflectError::OperationFailed {
×
169
                        shape: frame.shape,
×
170
                        operation: "cannot select a field from an opaque type",
×
171
                    });
×
172
                }
173
            },
174
            Type::Sequence(sequence_type) => match sequence_type {
44✔
175
                SequenceType::Array(array_type) => {
44✔
176
                    Self::begin_nth_array_element(frame, array_type, idx)?
44✔
177
                }
178
                SequenceType::Slice(_) => {
179
                    return Err(ReflectError::OperationFailed {
×
180
                        shape: frame.shape,
×
181
                        operation: "cannot select a field from slices yet",
×
182
                    });
×
183
                }
184
            },
185
            _ => {
186
                return Err(ReflectError::OperationFailed {
×
187
                    shape: frame.shape,
×
188
                    operation: "cannot select a field from this type",
×
189
                });
×
190
            }
191
        };
192

193
        self.frames_mut().push(next_frame);
459✔
194
        Ok(self)
459✔
195
    }
507✔
196

197
    /// Get the field name for path tracking (used in deferred mode)
198
    fn get_field_name_for_path(&self, idx: usize) -> Option<&'static str> {
507✔
199
        let frame = self.frames().last()?;
507✔
200
        match frame.shape.ty {
463✔
201
            Type::User(UserType::Struct(struct_type)) => {
401✔
202
                struct_type.fields.get(idx).map(|f| f.name)
401✔
203
            }
204
            Type::User(UserType::Enum(_)) => {
205
                if let Tracker::Enum { variant, .. } = &frame.tracker {
62✔
206
                    variant.data.fields.get(idx).map(|f| f.name)
62✔
207
                } else {
208
                    None
×
209
                }
210
            }
211
            // For arrays, we could use index as string, but for now return None
212
            _ => None,
44✔
213
        }
214
    }
507✔
215

216
    /// Sets the given field to its default value, preferring:
217
    ///
218
    ///   * A `default = some_fn()` function
219
    ///   * The field's `Default` implementation if any
220
    ///
221
    /// But without going all the way up to the parent struct's `Default` impl.
222
    ///
223
    /// Errors out if idx is out of bound, if the field has no default method or Default impl.
224
    pub fn set_nth_field_to_default(&mut self, idx: usize) -> Result<&mut Self, ReflectError> {
×
225
        self.require_active()?;
×
226

227
        let frame = self.frames().last().unwrap();
×
228
        let fields = self.get_fields()?;
×
229

230
        if idx >= fields.len() {
×
231
            return Err(ReflectError::OperationFailed {
×
232
                shape: frame.shape,
×
233
                operation: "field index out of bounds",
×
234
            });
×
235
        }
×
236

237
        let field = fields[idx];
×
238

239
        // Check for field-level default function first, then type-level default
240
        if let Some(field_default_fn) = field.vtable.default_fn {
×
241
            self.begin_nth_field(idx)?;
×
242
            // the field default fn should be well-behaved
243
            unsafe {
244
                self.set_from_function(|ptr| {
×
245
                    field_default_fn(ptr);
×
246
                    Ok(())
×
247
                })?;
×
248
            }
249
            self.end()
×
250
        } else if field.shape().is(Characteristic::Default) {
×
251
            self.begin_nth_field(idx)?;
×
252
            self.set_default()?;
×
253
            self.end()
×
254
        } else {
255
            return Err(ReflectError::DefaultAttrButNoDefaultImpl {
×
256
                shape: field.shape(),
×
257
            });
×
258
        }
259
    }
×
260

261
    /// Given a `Partial` for the same shape, and assuming that partial has the nth
262
    /// field initialized, move the value from `src` to `self`, marking it as deinitialized
263
    /// in `src`.
264
    pub fn steal_nth_field(
2✔
265
        &mut self,
2✔
266
        src: &mut Partial,
2✔
267
        field_index: usize,
2✔
268
    ) -> Result<&mut Self, ReflectError> {
2✔
269
        let dst_shape = self.shape();
2✔
270
        let src_shape = src.shape();
2✔
271
        if dst_shape != src_shape {
2✔
272
            return Err(ReflectError::HeistCancelledDifferentShapes {
×
273
                src_shape,
×
274
                dst_shape,
×
275
            });
×
276
        }
2✔
277

278
        // FIXME: what about enums? we don't check that the right variant is
279
        // selected here.
280
        if !src.is_field_set(field_index)? {
2✔
281
            return Err(ReflectError::InvariantViolation {
×
282
                invariant: "stolen field must be initialized",
×
283
            });
×
284
        }
2✔
285

286
        let maybe_fields = match src_shape.ty {
2✔
287
            Type::Primitive(_primitive_type) => None,
×
288
            Type::Sequence(_sequence_type) => None,
×
289
            Type::User(user_type) => match user_type {
2✔
290
                UserType::Struct(struct_type) => Some(struct_type.fields),
2✔
291
                UserType::Enum(_enum_type) => match self.selected_variant() {
×
292
                    Some(variant) => Some(variant.data.fields),
×
293
                    None => {
294
                        return Err(ReflectError::InvariantViolation {
×
295
                            invariant: "enum field thief must have variant selected",
×
296
                        });
×
297
                    }
298
                },
299
                UserType::Union(_union_type) => None,
×
300
                UserType::Opaque => None,
×
301
            },
302
            Type::Pointer(_pointer_type) => None,
×
303
        };
304

305
        let Some(fields) = maybe_fields else {
2✔
306
            return Err(ReflectError::OperationFailed {
×
307
                shape: src_shape,
×
308
                operation: "fetching field list for steal_nth_field",
×
309
            });
×
310
        };
311

312
        if field_index >= fields.len() {
2✔
313
            return Err(ReflectError::OperationFailed {
×
314
                shape: src_shape,
×
315
                operation: "field index out of bounds",
×
316
            });
×
317
        }
2✔
318
        let field = fields[field_index];
2✔
319

320
        let src_frame = src.frames_mut().last_mut().unwrap();
2✔
321

322
        self.begin_nth_field(field_index)?;
2✔
323
        unsafe {
324
            self.set_from_function(|dst_field_ptr| {
2✔
325
                let src_field_ptr = src_frame.data.field_init_at(field.offset).as_const();
2✔
326
                dst_field_ptr
2✔
327
                    .copy_from(src_field_ptr, field.shape())
2✔
328
                    .unwrap();
2✔
329
                Ok(())
2✔
330
            })?;
2✔
331
        }
332
        self.end()?;
2✔
333

334
        // now mark field as uninitialized in `src`
335
        match &mut src_frame.tracker {
2✔
336
            Tracker::Uninit => {
337
                unreachable!("we just stole a field from src, it couldn't have been fully uninit")
×
338
            }
339
            Tracker::Init => {
340
                // all struct fields were init so we don't even have a struct tracker,
341
                // let's make one!
342
                let mut iset = ISet::new(fields.len());
1✔
343
                iset.set_all();
1✔
344
                iset.unset(field_index);
1✔
345
                src_frame.tracker = Tracker::Struct {
1✔
346
                    iset,
1✔
347
                    current_child: None,
1✔
348
                }
1✔
349
            }
350
            Tracker::Array { .. } => unreachable!("can't steal fields from arrays"),
×
351
            Tracker::Struct { iset, .. } => {
1✔
352
                iset.unset(field_index);
1✔
353
            }
1✔
354
            Tracker::SmartPointer { .. } => {
355
                unreachable!("can't steal fields from smart pointers")
×
356
            }
357
            Tracker::SmartPointerSlice { .. } => {
358
                unreachable!("can't steal fields from smart pointer slices")
×
359
            }
360
            Tracker::Enum { data, .. } => {
×
361
                data.unset(field_index);
×
362
            }
×
363
            Tracker::List { .. } => {
364
                unreachable!("can't steal fields from lists")
×
365
            }
366
            Tracker::Map { .. } => {
367
                unreachable!("can't steal fields from maps")
×
368
            }
369
            Tracker::Set { .. } => {
370
                unreachable!("can't steal fields from sets")
×
371
            }
372
            Tracker::Option { .. } => {
373
                unreachable!("can't steal fields from options")
×
374
            }
375
        }
376

377
        Ok(self)
2✔
378
    }
2✔
379
}
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