Skip to main content

x_variant/
serde.rs

1use std::fmt;
2
3use serde::{
4    de::{Error, MapAccess, SeqAccess, Visitor},
5    Deserialize, Deserializer, Serialize, Serializer,
6};
7
8use crate::variant::Variant;
9
10impl Serialize for Variant {
11    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
12    where
13        S: Serializer,
14    {
15        match self {
16            Variant::None => serializer.serialize_none(),
17            Variant::Bool(value) => serializer.serialize_bool(*value),
18            #[cfg(not(feature = "serde-prefix-nums"))]
19            Variant::Int8(value) => serializer.serialize_i8(*value),
20            #[cfg(feature = "serde-prefix-nums")]
21            Variant::Int8(value) => serializer.serialize_str(&format!("@i8:{}", *value)),
22            #[cfg(not(feature = "serde-prefix-nums"))]
23            Variant::UInt8(value) => serializer.serialize_u8(*value),
24            #[cfg(feature = "serde-prefix-nums")]
25            Variant::UInt8(value) => serializer.serialize_str(&format!("@u8:{}", *value)),
26            #[cfg(not(feature = "serde-prefix-nums"))]
27            Variant::Int16(value) => serializer.serialize_i16(*value),
28            #[cfg(feature = "serde-prefix-nums")]
29            Variant::Int16(value) => serializer.serialize_str(&format!("@i16:{}", *value)),
30            #[cfg(not(feature = "serde-prefix-nums"))]
31            Variant::UInt16(value) => serializer.serialize_u16(*value),
32            #[cfg(feature = "serde-prefix-nums")]
33            Variant::UInt16(value) => serializer.serialize_str(&format!("@u16:{}", *value)),
34            #[cfg(not(feature = "serde-prefix-nums"))]
35            Variant::Int32(value) => serializer.serialize_i32(*value),
36            #[cfg(feature = "serde-prefix-nums")]
37            Variant::Int32(value) => serializer.serialize_str(&format!("@i32:{}", *value)),
38            #[cfg(not(feature = "serde-prefix-nums"))]
39            Variant::UInt32(value) => serializer.serialize_u32(*value),
40            #[cfg(feature = "serde-prefix-nums")]
41            Variant::UInt32(value) => serializer.serialize_str(&format!("@u32:{}", *value)),
42            #[cfg(not(feature = "serde-prefix-nums"))]
43            Variant::Int64(value) => serializer.serialize_i64(*value),
44            #[cfg(feature = "serde-prefix-nums")]
45            Variant::Int64(value) => {
46                if *value < 0 {
47                    serializer.serialize_i64(*value)
48                } else {
49                    serializer.serialize_str(&format!("@i64:{}", *value))
50                }
51            }
52            Variant::UInt64(value) => serializer.serialize_u64(*value),
53            #[cfg(not(feature = "serde-prefix-nums"))]
54            Variant::Float(value) => serializer.serialize_f32(*value),
55            #[cfg(feature = "serde-prefix-nums")]
56            Variant::Float(value) => serializer.serialize_str(&format!("@f:{}", *value)),
57            Variant::Double(value) => serializer.serialize_f64(*value),
58            #[cfg(not(feature = "serde-prefix-nums"))]
59            Variant::String(value) => serializer.serialize_str(value),
60            #[cfg(feature = "serde-prefix-nums")]
61            Variant::String(value) => {
62                if value.starts_with("@") {
63                    return serializer.serialize_str(&format!("@{}", value));
64                } else {
65                    return serializer.serialize_str(value);
66                }
67            }
68            Variant::Buffer(value) => serializer.serialize_bytes(value),
69            Variant::Array(value) => value.serialize(serializer),
70            Variant::Dict(value) => value.serialize(serializer),
71        }
72    }
73}
74
75impl<'de> Deserialize<'de> for Variant {
76    fn deserialize<D>(deserializer: D) -> Result<Variant, D::Error>
77    where
78        D: Deserializer<'de>,
79    {
80        struct VariantVisitor;
81
82        impl<'de> Visitor<'de> for VariantVisitor {
83            type Value = Variant;
84
85            fn expecting(&self, formatter: &mut std::fmt::Formatter) -> fmt::Result {
86                formatter.write_str("a valid Variant")
87            }
88
89            fn visit_none<E>(self) -> Result<Variant, E> {
90                Ok(Variant::None)
91            }
92
93            fn visit_bool<E>(self, value: bool) -> Result<Variant, E> {
94                Ok(Variant::Bool(value))
95            }
96
97            #[cfg(not(feature = "serde-prefix-nums"))]
98            fn visit_i8<E>(self, value: i8) -> Result<Variant, E> {
99                Ok(Variant::Int8(value))
100            }
101
102            #[cfg(not(feature = "serde-prefix-nums"))]
103            fn visit_u8<E>(self, value: u8) -> Result<Variant, E> {
104                Ok(Variant::UInt8(value))
105            }
106
107            #[cfg(not(feature = "serde-prefix-nums"))]
108            fn visit_i16<E>(self, value: i16) -> Result<Variant, E> {
109                Ok(Variant::Int16(value))
110            }
111
112            #[cfg(not(feature = "serde-prefix-nums"))]
113            fn visit_u16<E>(self, value: u16) -> Result<Variant, E> {
114                Ok(Variant::UInt16(value))
115            }
116
117            #[cfg(not(feature = "serde-prefix-nums"))]
118            fn visit_i32<E>(self, value: i32) -> Result<Variant, E> {
119                Ok(Variant::Int32(value))
120            }
121
122            #[cfg(not(feature = "serde-prefix-nums"))]
123            fn visit_u32<E>(self, value: u32) -> Result<Variant, E> {
124                Ok(Variant::UInt32(value))
125            }
126
127            fn visit_i64<E>(self, value: i64) -> Result<Variant, E> {
128                Ok(Variant::Int64(value))
129            }
130
131            fn visit_u64<E>(self, value: u64) -> Result<Variant, E> {
132                Ok(Variant::UInt64(value))
133            }
134
135            #[cfg(not(feature = "serde-prefix-nums"))]
136            fn visit_f32<E>(self, value: f32) -> Result<Variant, E> {
137                Ok(Variant::Float(value))
138            }
139
140            fn visit_f64<E>(self, value: f64) -> Result<Variant, E> {
141                Ok(Variant::Double(value))
142            }
143
144            fn visit_str<E>(self, value: &str) -> Result<Variant, E>
145            where
146                E: Error,
147            {
148                #[cfg(feature = "serde-prefix-nums")]
149                if value.starts_with("@") {
150                    let str = &value[1..];
151
152                    let result = match str {
153                        s if s.starts_with("i8:") => s[3..].parse().map(Variant::Int8).map_err(Error::custom),
154                        s if s.starts_with("u8:") => s[3..].parse().map(Variant::UInt8).map_err(Error::custom),
155                        s if s.starts_with("i16:") => s[4..].parse().map(Variant::Int16).map_err(Error::custom),
156                        s if s.starts_with("u16:") => s[4..].parse().map(Variant::UInt16).map_err(Error::custom),
157                        s if s.starts_with("i32:") => s[4..].parse().map(Variant::Int32).map_err(Error::custom),
158                        s if s.starts_with("u32:") => s[4..].parse().map(Variant::UInt32).map_err(Error::custom),
159                        s if s.starts_with("i64:") => s[4..].parse().map(Variant::Int64).map_err(Error::custom),
160                        s if s.starts_with("f:") => s[2..].parse().map(Variant::Float).map_err(Error::custom),
161                        s if s.starts_with("@") => Ok(Variant::String(s.to_string())),
162                        _s => Ok(Variant::String(value.to_string())),
163                    };
164
165                    return result;
166                };
167
168                Ok(Variant::String(value.to_string()))
169            }
170
171            fn visit_bytes<E>(self, v: &[u8]) -> Result<Variant, E> {
172                Ok(Variant::Buffer(v.to_vec()))
173            }
174
175            fn visit_seq<A>(self, mut seq: A) -> Result<Variant, A::Error>
176            where
177                A: SeqAccess<'de>,
178            {
179                let mut vec = Vec::new();
180                while let Some(value) = seq.next_element()? {
181                    vec.push(value);
182                }
183                Ok(Variant::Array(vec))
184            }
185
186            fn visit_map<A>(self, mut map: A) -> Result<Variant, A::Error>
187            where
188                A: MapAccess<'de>,
189            {
190                let mut dict = Variant::new_dict();
191                while let Some((key, value)) = map.next_entry::<&str, Variant>()? {
192                    dict.dict_set(key, value);
193                }
194                Ok(dict)
195            }
196        }
197
198        deserializer.deserialize_any(VariantVisitor)
199    }
200}