Skip to main content

confex_core/
deserialize.rs

1use std::collections::BTreeMap;
2
3use serde::{
4    de::{self, IntoDeserializer as _, Visitor},
5    ser,
6};
7
8use crate::value::ConfigValue;
9
10/// Error produced when deserializing a [`ConfigValue`] tree into a concrete type.
11#[derive(Debug)]
12pub struct DeserializeError(String);
13
14impl std::fmt::Display for DeserializeError {
15    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
16        write!(f, "{}", self.0)
17    }
18}
19
20impl std::error::Error for DeserializeError {}
21
22impl de::Error for DeserializeError {
23    fn custom<T: std::fmt::Display>(msg: T) -> Self {
24        Self(msg.to_string())
25    }
26}
27
28impl ser::Error for DeserializeError {
29    fn custom<T: std::fmt::Display>(msg: T) -> Self {
30        Self(msg.to_string())
31    }
32}
33
34/// Drives serde deserialization directly from a [`ConfigValue`] tree.
35///
36/// Replaces the `ConfigValue → serde_json::Value → S` round-trip with a single
37/// pass that does not require the `serde_json` crate.
38pub struct ConfigValueDeserializer(pub ConfigValue);
39
40type Result<T> = std::result::Result<T, DeserializeError>;
41
42impl<'de> de::Deserializer<'de> for ConfigValueDeserializer {
43    type Error = DeserializeError;
44
45    fn deserialize_any<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
46        match self.0 {
47            ConfigValue::Null => visitor.visit_unit(),
48            ConfigValue::Bool(b) => visitor.visit_bool(b),
49            ConfigValue::Integer(i) => visitor.visit_i64(i),
50            ConfigValue::Float(f) => visitor.visit_f64(f),
51            ConfigValue::String(s) => visitor.visit_string(s),
52            ConfigValue::Array(arr) => visitor.visit_seq(SeqDeserializer(arr.into_iter())),
53            ConfigValue::Table(map) => visitor.visit_map(MapDeserializer::new(map)),
54        }
55    }
56
57    fn deserialize_option<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
58        match self.0 {
59            ConfigValue::Null => visitor.visit_none(),
60            other => visitor.visit_some(Self(other)),
61        }
62    }
63
64    fn deserialize_newtype_struct<V: Visitor<'de>>(
65        self,
66        _name: &'static str,
67        visitor: V,
68    ) -> Result<V::Value> {
69        visitor.visit_newtype_struct(self)
70    }
71
72    fn deserialize_enum<V: Visitor<'de>>(
73        self,
74        _name: &'static str,
75        _variants: &'static [&'static str],
76        visitor: V,
77    ) -> Result<V::Value> {
78        match self.0 {
79            ConfigValue::String(s) => visitor.visit_enum(s.into_deserializer()),
80            ConfigValue::Table(mut map) if map.len() == 1 => {
81                let (variant, payload) = map.pop_first().expect("len == 1 checked");
82                visitor.visit_enum(EnumDeserializer { variant, payload })
83            }
84            other => Err(de::Error::invalid_type(
85                unexpected(&other),
86                &"string or single-key table for enum variant",
87            )),
88        }
89    }
90
91    serde::forward_to_deserialize_any! {
92        bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64
93        char str string bytes byte_buf
94        unit unit_struct
95        seq tuple tuple_struct
96        map struct
97        identifier ignored_any
98    }
99}
100
101fn unexpected(v: &ConfigValue) -> de::Unexpected<'_> {
102    match v {
103        ConfigValue::Null => de::Unexpected::Unit,
104        ConfigValue::Bool(b) => de::Unexpected::Bool(*b),
105        ConfigValue::Integer(i) => de::Unexpected::Signed(*i),
106        ConfigValue::Float(f) => de::Unexpected::Float(*f),
107        ConfigValue::String(s) => de::Unexpected::Str(s),
108        ConfigValue::Array(_) => de::Unexpected::Seq,
109        ConfigValue::Table(_) => de::Unexpected::Map,
110    }
111}
112
113struct SeqDeserializer(std::vec::IntoIter<ConfigValue>);
114
115impl<'de> de::SeqAccess<'de> for SeqDeserializer {
116    type Error = DeserializeError;
117
118    fn next_element_seed<T: de::DeserializeSeed<'de>>(
119        &mut self,
120        seed: T,
121    ) -> Result<Option<T::Value>> {
122        match self.0.next() {
123            Some(v) => seed.deserialize(ConfigValueDeserializer(v)).map(Some),
124            None => Ok(None),
125        }
126    }
127}
128
129struct MapDeserializer {
130    iter: std::collections::btree_map::IntoIter<String, ConfigValue>,
131    pending: Option<ConfigValue>,
132}
133
134impl MapDeserializer {
135    fn new(map: BTreeMap<String, ConfigValue>) -> Self {
136        Self {
137            iter: map.into_iter(),
138            pending: None,
139        }
140    }
141}
142
143impl<'de> de::MapAccess<'de> for MapDeserializer {
144    type Error = DeserializeError;
145
146    fn next_key_seed<K: de::DeserializeSeed<'de>>(&mut self, seed: K) -> Result<Option<K::Value>> {
147        match self.iter.next() {
148            Some((k, v)) => {
149                self.pending = Some(v);
150                seed.deserialize(de::value::StringDeserializer::new(k))
151                    .map(Some)
152            }
153            None => Ok(None),
154        }
155    }
156
157    fn next_value_seed<V: de::DeserializeSeed<'de>>(&mut self, seed: V) -> Result<V::Value> {
158        let v = self.pending.take().expect("called after next_key_seed");
159        seed.deserialize(ConfigValueDeserializer(v))
160    }
161}
162
163struct EnumDeserializer {
164    variant: String,
165    payload: ConfigValue,
166}
167
168impl<'de> de::EnumAccess<'de> for EnumDeserializer {
169    type Error = DeserializeError;
170    type Variant = Self;
171
172    fn variant_seed<V: de::DeserializeSeed<'de>>(
173        self,
174        seed: V,
175    ) -> Result<(V::Value, Self::Variant)> {
176        let tag = seed.deserialize(de::value::StringDeserializer::new(self.variant.clone()))?;
177        Ok((tag, self))
178    }
179}
180
181impl<'de> de::VariantAccess<'de> for EnumDeserializer {
182    type Error = DeserializeError;
183
184    fn unit_variant(self) -> Result<()> {
185        Ok(())
186    }
187
188    fn newtype_variant_seed<T: de::DeserializeSeed<'de>>(self, seed: T) -> Result<T::Value> {
189        seed.deserialize(ConfigValueDeserializer(self.payload))
190    }
191
192    fn tuple_variant<V: Visitor<'de>>(self, _len: usize, visitor: V) -> Result<V::Value> {
193        de::Deserializer::deserialize_seq(ConfigValueDeserializer(self.payload), visitor)
194    }
195
196    fn struct_variant<V: Visitor<'de>>(
197        self,
198        _fields: &'static [&'static str],
199        visitor: V,
200    ) -> Result<V::Value> {
201        de::Deserializer::deserialize_map(ConfigValueDeserializer(self.payload), visitor)
202    }
203}
204
205/// Serializes any `T: Serialize` into a [`ConfigValue`] tree without a `serde_json` dependency.
206pub struct ConfigValueSerializer;
207
208/// Serialize any `T: serde::Serialize` into a [`ConfigValue`].
209///
210/// # Errors
211/// Returns [`DeserializeError`] if `T` produces a type that cannot be
212/// represented as a `ConfigValue` (e.g. maps with non-string keys).
213pub fn to_config_value<T: serde::Serialize>(
214    value: &T,
215) -> std::result::Result<ConfigValue, DeserializeError> {
216    value.serialize(ConfigValueSerializer)
217}
218
219impl ser::Serializer for ConfigValueSerializer {
220    type Ok = ConfigValue;
221    type Error = DeserializeError;
222
223    type SerializeSeq = SeqSerializer;
224    type SerializeTuple = SeqSerializer;
225    type SerializeTupleStruct = SeqSerializer;
226    type SerializeTupleVariant = TupleVariantSerializer;
227    type SerializeMap = MapSerializer;
228    type SerializeStruct = MapSerializer;
229    type SerializeStructVariant = StructVariantSerializer;
230
231    fn serialize_bool(self, v: bool) -> Result<ConfigValue> {
232        Ok(ConfigValue::Bool(v))
233    }
234    fn serialize_i8(self, v: i8) -> Result<ConfigValue> {
235        Ok(ConfigValue::Integer(i64::from(v)))
236    }
237    fn serialize_i16(self, v: i16) -> Result<ConfigValue> {
238        Ok(ConfigValue::Integer(i64::from(v)))
239    }
240    fn serialize_i32(self, v: i32) -> Result<ConfigValue> {
241        Ok(ConfigValue::Integer(i64::from(v)))
242    }
243    fn serialize_i64(self, v: i64) -> Result<ConfigValue> {
244        Ok(ConfigValue::Integer(v))
245    }
246    fn serialize_i128(self, v: i128) -> Result<ConfigValue> {
247        i64::try_from(v)
248            .map(ConfigValue::Integer)
249            .map_err(ser::Error::custom)
250    }
251    fn serialize_u8(self, v: u8) -> Result<ConfigValue> {
252        Ok(ConfigValue::Integer(i64::from(v)))
253    }
254    fn serialize_u16(self, v: u16) -> Result<ConfigValue> {
255        Ok(ConfigValue::Integer(i64::from(v)))
256    }
257    fn serialize_u32(self, v: u32) -> Result<ConfigValue> {
258        Ok(ConfigValue::Integer(i64::from(v)))
259    }
260    fn serialize_u64(self, v: u64) -> Result<ConfigValue> {
261        i64::try_from(v)
262            .map(ConfigValue::Integer)
263            .map_err(ser::Error::custom)
264    }
265    fn serialize_u128(self, v: u128) -> Result<ConfigValue> {
266        i64::try_from(v)
267            .map(ConfigValue::Integer)
268            .map_err(ser::Error::custom)
269    }
270    fn serialize_f32(self, v: f32) -> Result<ConfigValue> {
271        Ok(ConfigValue::Float(f64::from(v)))
272    }
273    fn serialize_f64(self, v: f64) -> Result<ConfigValue> {
274        Ok(ConfigValue::Float(v))
275    }
276    fn serialize_char(self, v: char) -> Result<ConfigValue> {
277        Ok(ConfigValue::String(v.to_string()))
278    }
279    fn serialize_str(self, v: &str) -> Result<ConfigValue> {
280        Ok(ConfigValue::String(v.to_owned()))
281    }
282    fn serialize_bytes(self, v: &[u8]) -> Result<ConfigValue> {
283        Ok(ConfigValue::Array(
284            v.iter()
285                .map(|b| ConfigValue::Integer(i64::from(*b)))
286                .collect(),
287        ))
288    }
289    fn serialize_none(self) -> Result<ConfigValue> {
290        Ok(ConfigValue::Null)
291    }
292    fn serialize_some<T: serde::Serialize + ?Sized>(self, value: &T) -> Result<ConfigValue> {
293        value.serialize(self)
294    }
295    fn serialize_unit(self) -> Result<ConfigValue> {
296        Ok(ConfigValue::Null)
297    }
298    fn serialize_unit_struct(self, _name: &'static str) -> Result<ConfigValue> {
299        Ok(ConfigValue::Null)
300    }
301    fn serialize_unit_variant(
302        self,
303        _name: &'static str,
304        _index: u32,
305        variant: &'static str,
306    ) -> Result<ConfigValue> {
307        Ok(ConfigValue::String(variant.to_owned()))
308    }
309    fn serialize_newtype_struct<T: serde::Serialize + ?Sized>(
310        self,
311        _name: &'static str,
312        value: &T,
313    ) -> Result<ConfigValue> {
314        value.serialize(self)
315    }
316    fn serialize_newtype_variant<T: serde::Serialize + ?Sized>(
317        self,
318        _name: &'static str,
319        _index: u32,
320        variant: &'static str,
321        value: &T,
322    ) -> Result<ConfigValue> {
323        let mut map = BTreeMap::new();
324        map.insert(variant.to_owned(), value.serialize(Self)?);
325        Ok(ConfigValue::Table(map))
326    }
327    fn serialize_seq(self, len: Option<usize>) -> Result<SeqSerializer> {
328        Ok(SeqSerializer(Vec::with_capacity(len.unwrap_or(0))))
329    }
330    fn serialize_tuple(self, len: usize) -> Result<SeqSerializer> {
331        Ok(SeqSerializer(Vec::with_capacity(len)))
332    }
333    fn serialize_tuple_struct(self, _name: &'static str, len: usize) -> Result<SeqSerializer> {
334        Ok(SeqSerializer(Vec::with_capacity(len)))
335    }
336    fn serialize_tuple_variant(
337        self,
338        _name: &'static str,
339        _index: u32,
340        variant: &'static str,
341        len: usize,
342    ) -> Result<TupleVariantSerializer> {
343        Ok(TupleVariantSerializer {
344            variant: variant.to_owned(),
345            items: Vec::with_capacity(len),
346        })
347    }
348    fn serialize_map(self, _len: Option<usize>) -> Result<MapSerializer> {
349        Ok(MapSerializer::default())
350    }
351    fn serialize_struct(self, _name: &'static str, _len: usize) -> Result<MapSerializer> {
352        Ok(MapSerializer::default())
353    }
354    fn serialize_struct_variant(
355        self,
356        _name: &'static str,
357        _index: u32,
358        variant: &'static str,
359        _len: usize,
360    ) -> Result<StructVariantSerializer> {
361        Ok(StructVariantSerializer {
362            variant: variant.to_owned(),
363            fields: BTreeMap::new(),
364        })
365    }
366}
367
368pub struct SeqSerializer(Vec<ConfigValue>);
369
370impl ser::SerializeSeq for SeqSerializer {
371    type Ok = ConfigValue;
372    type Error = DeserializeError;
373    fn serialize_element<T: serde::Serialize + ?Sized>(&mut self, value: &T) -> Result<()> {
374        self.0.push(value.serialize(ConfigValueSerializer)?);
375        Ok(())
376    }
377    fn end(self) -> Result<ConfigValue> {
378        Ok(ConfigValue::Array(self.0))
379    }
380}
381impl ser::SerializeTuple for SeqSerializer {
382    type Ok = ConfigValue;
383    type Error = DeserializeError;
384    fn serialize_element<T: serde::Serialize + ?Sized>(&mut self, value: &T) -> Result<()> {
385        ser::SerializeSeq::serialize_element(self, value)
386    }
387    fn end(self) -> Result<ConfigValue> {
388        ser::SerializeSeq::end(self)
389    }
390}
391impl ser::SerializeTupleStruct for SeqSerializer {
392    type Ok = ConfigValue;
393    type Error = DeserializeError;
394    fn serialize_field<T: serde::Serialize + ?Sized>(&mut self, value: &T) -> Result<()> {
395        ser::SerializeSeq::serialize_element(self, value)
396    }
397    fn end(self) -> Result<ConfigValue> {
398        ser::SerializeSeq::end(self)
399    }
400}
401
402pub struct TupleVariantSerializer {
403    variant: String,
404    items: Vec<ConfigValue>,
405}
406impl ser::SerializeTupleVariant for TupleVariantSerializer {
407    type Ok = ConfigValue;
408    type Error = DeserializeError;
409    fn serialize_field<T: serde::Serialize + ?Sized>(&mut self, value: &T) -> Result<()> {
410        self.items.push(value.serialize(ConfigValueSerializer)?);
411        Ok(())
412    }
413    fn end(self) -> Result<ConfigValue> {
414        let mut map = BTreeMap::new();
415        map.insert(self.variant, ConfigValue::Array(self.items));
416        Ok(ConfigValue::Table(map))
417    }
418}
419
420#[derive(Default)]
421pub struct MapSerializer {
422    map: BTreeMap<String, ConfigValue>,
423    pending_key: Option<String>,
424}
425impl ser::SerializeMap for MapSerializer {
426    type Ok = ConfigValue;
427    type Error = DeserializeError;
428    fn serialize_key<T: serde::Serialize + ?Sized>(&mut self, key: &T) -> Result<()> {
429        let k = match key.serialize(ConfigValueSerializer)? {
430            ConfigValue::String(s) => s,
431            other => {
432                return Err(ser::Error::custom(format!(
433                    "map key must be a string, got {other:?}"
434                )));
435            }
436        };
437        self.pending_key = Some(k);
438        Ok(())
439    }
440    fn serialize_value<T: serde::Serialize + ?Sized>(&mut self, value: &T) -> Result<()> {
441        let k = self
442            .pending_key
443            .take()
444            .expect("serialize_value called after serialize_key");
445        self.map.insert(k, value.serialize(ConfigValueSerializer)?);
446        Ok(())
447    }
448    fn end(self) -> Result<ConfigValue> {
449        Ok(ConfigValue::Table(self.map))
450    }
451}
452impl ser::SerializeStruct for MapSerializer {
453    type Ok = ConfigValue;
454    type Error = DeserializeError;
455    fn serialize_field<T: serde::Serialize + ?Sized>(
456        &mut self,
457        key: &'static str,
458        value: &T,
459    ) -> Result<()> {
460        self.map
461            .insert(key.to_owned(), value.serialize(ConfigValueSerializer)?);
462        Ok(())
463    }
464    fn end(self) -> Result<ConfigValue> {
465        Ok(ConfigValue::Table(self.map))
466    }
467}
468
469pub struct StructVariantSerializer {
470    variant: String,
471    fields: BTreeMap<String, ConfigValue>,
472}
473impl ser::SerializeStructVariant for StructVariantSerializer {
474    type Ok = ConfigValue;
475    type Error = DeserializeError;
476    fn serialize_field<T: serde::Serialize + ?Sized>(
477        &mut self,
478        key: &'static str,
479        value: &T,
480    ) -> Result<()> {
481        self.fields
482            .insert(key.to_owned(), value.serialize(ConfigValueSerializer)?);
483        Ok(())
484    }
485    fn end(self) -> Result<ConfigValue> {
486        let mut map = BTreeMap::new();
487        map.insert(self.variant, ConfigValue::Table(self.fields));
488        Ok(ConfigValue::Table(map))
489    }
490}