facet_reflect/peek/
struct_.rs

1use facet_core::{Field, FieldAttribute, FieldError, Struct};
2
3use crate::Peek;
4
5/// Lets you read from a struct (implements read-only struct operations)
6#[derive(Clone, Copy)]
7pub struct PeekStruct<'mem> {
8    /// the underlying value
9    pub(crate) value: Peek<'mem>,
10
11    /// the definition of the struct!
12    pub(crate) def: Struct,
13}
14
15impl<'mem> PeekStruct<'mem> {
16    /// Returns the struct definition
17    #[inline(always)]
18    pub fn def(&self) -> &Struct {
19        &self.def
20    }
21
22    /// Returns the number of fields in this struct
23    #[inline(always)]
24    pub fn field_count(&self) -> usize {
25        self.def.fields.len()
26    }
27
28    /// Returns the value of the field at the given index
29    #[inline(always)]
30    pub fn field(&self, index: usize) -> Result<Peek<'mem>, FieldError> {
31        self.def
32            .fields
33            .get(index)
34            .map(|field| unsafe {
35                let field_data = self.value.data().field(field.offset);
36                Peek {
37                    data: field_data,
38                    shape: field.shape(),
39                }
40            })
41            .ok_or(FieldError::IndexOutOfBounds)
42    }
43
44    /// Gets the value of the field with the given name
45    #[inline]
46    pub fn field_by_name(&self, name: &str) -> Result<Peek<'mem>, FieldError> {
47        for (i, field) in self.def.fields.iter().enumerate() {
48            if field.name == name {
49                return self.field(i);
50            }
51        }
52        Err(FieldError::NoSuchField)
53    }
54
55    /// Iterates over all fields in this struct, providing both name and value
56    #[inline]
57    pub fn fields(&self) -> impl Iterator<Item = (&'static Field, Peek<'mem>)> + '_ {
58        (0..self.field_count()).filter_map(|i| {
59            let field = self.def.fields.get(i)?;
60            let value = self.field(i).ok()?;
61            Some((field, value))
62        })
63    }
64
65    /// Iterates over thos fields in this struct that should be included when it is serialized.
66    #[inline]
67    pub fn fields_for_serialize(&self) -> impl Iterator<Item = (&'static Field, Peek<'mem>)> + '_ {
68        self.fields().filter(|(field, peek)| {
69            for attr in field.attributes {
70                match attr {
71                    FieldAttribute::SkipSerializingIf(fn_ptr) => {
72                        if unsafe { fn_ptr(peek.data()) } {
73                            return false;
74                        }
75                    }
76                    FieldAttribute::SkipSerializing => {
77                        return false;
78                    }
79                    _ => {}
80                }
81            }
82            true
83        })
84    }
85}