serde_aux/
serde_introspection.rs

1use serde::de::{self, Deserialize, Deserializer, Visitor};
2
3/// Gets the serialization names for structs and enums.
4///
5/// # Example
6///
7/// ```rust
8/// use serde_aux::prelude::*;
9///
10/// #[derive(serde::Deserialize, Debug)]
11/// struct AnotherStruct {
12///     #[serde(rename = "a3")]
13///     aaa: Option<i64>,
14///     #[serde(rename = "b3")]
15///     bbb: i128,
16///     #[serde(rename = "c3")]
17///     ccc: u128,
18/// }
19/// let fields = serde_introspect::<AnotherStruct>();
20/// assert_eq!(fields[0], "a3");
21/// assert_eq!(fields[1], "b3");
22/// assert_eq!(fields[2], "c3");
23///
24/// #[derive(serde::Deserialize, Debug)]
25/// enum SomeEnum {
26///       #[serde(rename = "a")]
27///       EnumA,
28///       #[serde(rename = "b")]
29///       EnumB
30/// }
31/// let variants = serde_introspect::<SomeEnum>();
32/// assert_eq!(variants[0], "a");
33/// assert_eq!(variants[1], "b");
34/// ```
35pub fn serde_introspect<'de, T>() -> &'static [&'static str]
36where
37    T: Deserialize<'de>,
38{
39    struct StructFieldsDeserializer<'a> {
40        fields: &'a mut Option<&'static [&'static str]>,
41    }
42
43    impl<'de> Deserializer<'de> for StructFieldsDeserializer<'_> {
44        type Error = serde::de::value::Error;
45
46        fn deserialize_any<V>(self, _visitor: V) -> Result<V::Value, Self::Error>
47        where
48            V: Visitor<'de>,
49        {
50            Err(de::Error::custom("I'm just here for the fields"))
51        }
52
53        fn deserialize_struct<V>(
54            self,
55            _name: &'static str,
56            fields: &'static [&'static str],
57            _visitor: V,
58        ) -> Result<V::Value, Self::Error>
59        where
60            V: Visitor<'de>,
61        {
62            *self.fields = Some(fields); // get the names of the deserialized fields
63            Err(de::Error::custom("I'm just here for the fields"))
64        }
65
66        serde::forward_to_deserialize_any! {
67            bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes
68            byte_buf option unit unit_struct newtype_struct seq tuple
69            tuple_struct map enum identifier ignored_any
70        }
71    }
72
73    struct EnumVariantsDeserializer<'a> {
74        variants: &'a mut Option<&'static [&'static str]>,
75    }
76
77    impl<'de> Deserializer<'de> for EnumVariantsDeserializer<'_> {
78        type Error = serde::de::value::Error;
79
80        fn deserialize_any<V>(self, _visitor: V) -> Result<V::Value, Self::Error>
81        where
82            V: Visitor<'de>,
83        {
84            Err(de::Error::custom("I'm just here for the fields"))
85        }
86
87        fn deserialize_enum<V>(
88            self,
89            _name: &'static str,
90            variants: &'static [&'static str],
91            _visitor: V,
92        ) -> Result<V::Value, Self::Error>
93        where
94            V: Visitor<'de>,
95        {
96            *self.variants = Some(variants);
97            Err(de::Error::custom("I'm just here for the fields"))
98        }
99
100        serde::forward_to_deserialize_any! {
101            bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes
102            byte_buf option unit unit_struct newtype_struct seq tuple
103            tuple_struct map struct identifier ignored_any
104        }
105    }
106
107    let mut serialized_names = None;
108    let _ = T::deserialize(EnumVariantsDeserializer {
109        variants: &mut serialized_names,
110    });
111    let _ = T::deserialize(StructFieldsDeserializer {
112        fields: &mut serialized_names,
113    });
114    serialized_names.unwrap_or_default()
115}
116
117/// Get the default record for a struct implementing the `serde::Deserialize`
118/// trait.
119///
120/// This helper function is useful in particular when the `#[serde(default =
121/// "path")]` field attribute is used to customize the default record
122/// definition, as it avoids the need to implement the `Default` trait manually
123/// for the defined struct, paying attention to keep it aligned with Serde's
124/// attributes configuration.
125///
126/// # Example
127///
128/// ```rust
129/// use serde_aux::prelude::*;
130///
131/// #[derive(serde::Deserialize, PartialEq, Debug)]
132/// struct Record {
133///     #[serde(default = "default_string")]
134///     label: String,
135///     #[serde(default = "default_f64")]
136///     value1: f64,
137///     #[serde(default)]
138///     value2: f64,
139///     #[serde(skip)]
140///     foo: bool,
141/// }
142///
143/// fn default_string() -> String {
144///     String::from("default")
145/// }
146///
147/// fn default_f64() -> f64 {
148///     1.0
149/// }
150///
151/// let empty_record = get_default_serde_record::<Record>().unwrap();
152/// assert_eq!(
153///     empty_record,
154///     Record {
155///         label: String::from("default"),
156///         value1: 1.0,
157///         value2: 0.0,
158///         foo: false
159///     }
160/// );
161/// ```
162pub fn get_default_serde_record<'de, T>() -> Result<T, serde::de::value::Error>
163where
164    T: Deserialize<'de>,
165{
166    let empty_data = std::iter::empty::<((), ())>();
167    let empty_deserializer =
168        serde::de::value::MapDeserializer::<_, serde::de::value::Error>::new(empty_data);
169    T::deserialize(empty_deserializer)
170}
171
172#[cfg(test)]
173mod tests {
174    #![allow(dead_code)]
175
176    use crate::prelude::{get_default_serde_record, serde_introspect};
177
178    #[test]
179    fn serde_introspect_given_struct_introspect_serialization_names() {
180        #[derive(serde::Deserialize, Debug)]
181        enum SomeEnum {
182            #[serde(rename = "a")]
183            EnumA,
184            #[serde(rename = "b")]
185            EnumB,
186        }
187        #[derive(serde::Deserialize, Debug)]
188        struct AnotherStruct {
189            #[serde(rename = "a3")]
190            aaa: Option<i64>,
191            #[serde(rename = "b3")]
192            bbb: i128,
193            #[serde(rename = "c3")]
194            ccc: u128,
195            #[serde(rename = "d3")]
196            ddd: SomeEnum,
197        }
198        let names = serde_introspect::<AnotherStruct>();
199        assert_eq!(names[0], "a3");
200        assert_eq!(names[1], "b3");
201        assert_eq!(names[2], "c3");
202        assert_eq!(names[3], "d3");
203    }
204
205    #[test]
206    fn serde_introspect_enum_struct_introspect_serialization_names() {
207        #[derive(serde::Deserialize, Debug)]
208        enum SomeEnum {
209            #[serde(rename = "a")]
210            EnumA,
211            #[serde(rename = "b")]
212            EnumB,
213        }
214
215        let names = serde_introspect::<SomeEnum>();
216        assert_eq!(names[0], "a");
217        assert_eq!(names[1], "b");
218    }
219
220    #[test]
221    fn get_default_serde_record_from_struct() {
222        #[derive(serde::Deserialize, PartialEq, Debug)]
223        struct Record {
224            #[serde(default = "default_string")]
225            label: String,
226            #[serde(default = "default_f64")]
227            value1: f64,
228            #[serde(default)]
229            value2: f64,
230            #[serde(skip)]
231            foo: bool,
232        }
233
234        fn default_string() -> String {
235            String::from("default")
236        }
237
238        fn default_f64() -> f64 {
239            1.0
240        }
241
242        let empty_record = get_default_serde_record::<Record>().unwrap();
243        assert_eq!(
244            empty_record,
245            Record {
246                label: String::from("default"),
247                value1: 1.0,
248                value2: 0.0,
249                foo: false
250            }
251        );
252    }
253}