vector_core/
serde.rs

1use std::{fmt, marker::PhantomData};
2
3use serde::{de, Deserialize, Deserializer};
4
5/// Answers "Is this value in it's default state?" which can be used to skip serializing the value.
6#[inline]
7pub fn is_default<E: Default + PartialEq>(e: &E) -> bool {
8    e == &E::default()
9}
10
11/// Enables deserializing from a value that could be a bool or a struct.
12///
13/// Example:
14/// healthcheck: bool
15/// healthcheck.enabled: bool
16/// Both are accepted.
17///
18/// # Errors
19///
20/// Returns the error from deserializing the underlying struct.
21pub fn bool_or_struct<'de, T, D>(deserializer: D) -> Result<T, D::Error>
22where
23    T: Deserialize<'de> + From<bool>,
24    D: Deserializer<'de>,
25{
26    struct BoolOrStruct<T>(PhantomData<fn() -> T>);
27
28    impl<'de, T> de::Visitor<'de> for BoolOrStruct<T>
29    where
30        T: Deserialize<'de> + From<bool>,
31    {
32        type Value = T;
33
34        fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
35            formatter.write_str("bool or map")
36        }
37
38        fn visit_bool<E>(self, value: bool) -> Result<T, E>
39        where
40            E: de::Error,
41        {
42            Ok(value.into())
43        }
44
45        fn visit_map<M>(self, map: M) -> Result<T, M::Error>
46        where
47            M: de::MapAccess<'de>,
48        {
49            Deserialize::deserialize(de::value::MapAccessDeserializer::new(map))
50        }
51    }
52
53    deserializer.deserialize_any(BoolOrStruct(PhantomData))
54}
55
56/// Handling of ASCII characters in `u8` fields via `serde`s `with` attribute.
57///
58/// ```rust
59/// # use serde::{Deserialize, Serialize};
60/// use vector_core::serde::ascii_char;
61///
62/// #[derive(Deserialize, Serialize)]
63/// struct Foo {
64///    #[serde(with = "ascii_char")]
65///    character: u8,
66/// }
67/// ```
68pub mod ascii_char {
69    use serde::{de, Deserialize, Deserializer, Serializer};
70
71    /// Deserialize an ASCII character as `u8`.
72    ///
73    /// # Errors
74    ///
75    /// If the item fails to be deserialized as a character, of the character to
76    /// be deserialized is not part of the ASCII range, an error is returned.
77    pub fn deserialize<'de, D>(deserializer: D) -> Result<u8, D::Error>
78    where
79        D: Deserializer<'de>,
80    {
81        let character = char::deserialize(deserializer)?;
82        if character.is_ascii() {
83            Ok(character as u8)
84        } else {
85            Err(de::Error::custom(format!(
86                "invalid character: {character}, expected character in ASCII range"
87            )))
88        }
89    }
90
91    /// Serialize an `u8` as ASCII character.
92    ///
93    /// # Errors
94    ///
95    /// Does not error.
96    pub fn serialize<S>(character: &u8, serializer: S) -> Result<S::Ok, S::Error>
97    where
98        S: Serializer,
99    {
100        serializer.serialize_char(*character as char)
101    }
102
103    #[cfg(test)]
104    mod tests {
105        use serde::{Deserialize, Serialize};
106
107        #[derive(Deserialize, Serialize)]
108        struct Foo {
109            #[serde(with = "super")]
110            character: u8,
111        }
112
113        #[test]
114        fn test_deserialize_ascii_valid() {
115            let foo = serde_json::from_str::<Foo>(r#"{ "character": "\n" }"#).unwrap();
116            assert_eq!(foo.character, b'\n');
117        }
118
119        #[test]
120        fn test_deserialize_ascii_invalid_range() {
121            assert!(serde_json::from_str::<Foo>(r#"{ "character": "ß" }"#).is_err());
122        }
123
124        #[test]
125        fn test_deserialize_ascii_invalid_character() {
126            assert!(serde_json::from_str::<Foo>(r#"{ "character": 0 }"#).is_err());
127        }
128
129        #[test]
130        fn test_serialize_ascii() {
131            let foo = Foo { character: b'\n' };
132            assert_eq!(
133                serde_json::to_string(&foo).unwrap(),
134                r#"{"character":"\n"}"#
135            );
136        }
137    }
138}