Skip to main content

agent_first_data/document/
typed.rs

1//! Fallible serde adapters over the format-independent [`Value`] IR.
2
3#![allow(clippy::items_after_test_module)]
4
5use crate::document::{DocumentError, DocumentResult, Value};
6use serde::{
7    Deserializer, Serialize,
8    de::{self, DeserializeOwned},
9    ser,
10};
11
12/// Deserialize a typed configuration from a value view.
13pub fn from_value<T: DeserializeOwned>(value: &Value, path: &str) -> DocumentResult<T> {
14    T::deserialize(ValueDeserializer(value)).map_err(|error| DocumentError::from_serde(path, error))
15}
16
17/// Serialize a typed configuration into the format-independent value view.
18pub fn to_value<T: Serialize>(value: &T) -> DocumentResult<Value> {
19    value
20        .serialize(ValueSerializer)
21        .map_err(|error| DocumentError::ParseError {
22            format: "serde".to_string(),
23            detail: error.to_string(),
24        })
25}
26
27struct ValueSerializer;
28
29#[derive(Debug)]
30struct SerializeError(String);
31
32impl std::fmt::Display for SerializeError {
33    fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
34        formatter.write_str(&self.0)
35    }
36}
37
38impl std::error::Error for SerializeError {}
39
40impl serde::ser::Error for SerializeError {
41    fn custom<T: std::fmt::Display>(message: T) -> Self {
42        Self(message.to_string())
43    }
44}
45
46type Result<T, E = SerializeError> = std::result::Result<T, E>;
47
48impl serde::Serializer for ValueSerializer {
49    type Ok = Value;
50    type Error = SerializeError;
51    type SerializeSeq = SequenceSerializer;
52    type SerializeTuple = SequenceSerializer;
53    type SerializeTupleStruct = SequenceSerializer;
54    type SerializeTupleVariant = VariantSequenceSerializer;
55    type SerializeMap = MapSerializer;
56    type SerializeStruct = MapSerializer;
57    type SerializeStructVariant = VariantMapSerializer;
58
59    fn serialize_bool(self, value: bool) -> Result<Value> {
60        Ok(Value::Bool(value))
61    }
62    fn serialize_i8(self, value: i8) -> Result<Value> {
63        Ok(Value::Integer(i64::from(value)))
64    }
65    fn serialize_i16(self, value: i16) -> Result<Value> {
66        Ok(Value::Integer(i64::from(value)))
67    }
68    fn serialize_i32(self, value: i32) -> Result<Value> {
69        Ok(Value::Integer(i64::from(value)))
70    }
71    fn serialize_i64(self, value: i64) -> Result<Value> {
72        Ok(Value::Integer(value))
73    }
74    fn serialize_u8(self, value: u8) -> Result<Value> {
75        Ok(Value::Unsigned(u64::from(value)))
76    }
77    fn serialize_u16(self, value: u16) -> Result<Value> {
78        Ok(Value::Unsigned(u64::from(value)))
79    }
80    fn serialize_u32(self, value: u32) -> Result<Value> {
81        Ok(Value::Unsigned(u64::from(value)))
82    }
83    fn serialize_u64(self, value: u64) -> Result<Value> {
84        Ok(Value::Unsigned(value))
85    }
86    fn serialize_f32(self, value: f32) -> Result<Value> {
87        self.serialize_f64(f64::from(value))
88    }
89    fn serialize_f64(self, value: f64) -> Result<Value> {
90        if value.is_finite() {
91            Ok(Value::Float(value))
92        } else {
93            Err(SerializeError(
94                "non-finite float is not a document value".to_string(),
95            ))
96        }
97    }
98    fn serialize_char(self, value: char) -> Result<Value> {
99        Ok(Value::String(value.to_string()))
100    }
101    fn serialize_str(self, value: &str) -> Result<Value> {
102        Ok(Value::String(value.to_string()))
103    }
104    fn serialize_bytes(self, _value: &[u8]) -> Result<Value> {
105        Err(SerializeError(
106            "bytes require an explicit string or sequence representation".to_string(),
107        ))
108    }
109    fn serialize_none(self) -> Result<Value> {
110        Ok(Value::Null)
111    }
112    fn serialize_some<T: ?Sized + Serialize>(self, value: &T) -> Result<Value> {
113        value.serialize(self)
114    }
115    fn serialize_unit(self) -> Result<Value> {
116        Ok(Value::Null)
117    }
118    fn serialize_unit_struct(self, _name: &'static str) -> Result<Value> {
119        Ok(Value::Null)
120    }
121    fn serialize_unit_variant(
122        self,
123        _name: &'static str,
124        _index: u32,
125        variant: &'static str,
126    ) -> Result<Value> {
127        Ok(Value::String(variant.to_string()))
128    }
129    fn serialize_newtype_struct<T: ?Sized + Serialize>(
130        self,
131        _name: &'static str,
132        value: &T,
133    ) -> Result<Value> {
134        value.serialize(self)
135    }
136    fn serialize_newtype_variant<T: ?Sized + Serialize>(
137        self,
138        _name: &'static str,
139        _index: u32,
140        variant: &'static str,
141        value: &T,
142    ) -> Result<Value> {
143        let mut map = BTreeMap::new();
144        map.insert(variant.to_string(), value.serialize(ValueSerializer)?);
145        Ok(Value::Object(map))
146    }
147    fn serialize_seq(self, len: Option<usize>) -> Result<SequenceSerializer> {
148        Ok(SequenceSerializer {
149            values: Vec::with_capacity(len.unwrap_or(0)),
150        })
151    }
152    fn serialize_tuple(self, len: usize) -> Result<SequenceSerializer> {
153        self.serialize_seq(Some(len))
154    }
155    fn serialize_tuple_struct(self, _name: &'static str, len: usize) -> Result<SequenceSerializer> {
156        self.serialize_seq(Some(len))
157    }
158    fn serialize_tuple_variant(
159        self,
160        _name: &'static str,
161        _index: u32,
162        variant: &'static str,
163        len: usize,
164    ) -> Result<VariantSequenceSerializer> {
165        Ok(VariantSequenceSerializer {
166            variant: variant.to_string(),
167            values: Vec::with_capacity(len),
168        })
169    }
170    fn serialize_map(self, _len: Option<usize>) -> Result<MapSerializer> {
171        Ok(MapSerializer {
172            values: BTreeMap::new(),
173            next_key: None,
174        })
175    }
176    fn serialize_struct(self, _name: &'static str, len: usize) -> Result<MapSerializer> {
177        self.serialize_map(Some(len))
178    }
179    fn serialize_struct_variant(
180        self,
181        _name: &'static str,
182        _index: u32,
183        variant: &'static str,
184        _len: usize,
185    ) -> Result<VariantMapSerializer> {
186        Ok(VariantMapSerializer {
187            variant: variant.to_string(),
188            map: MapSerializer {
189                values: BTreeMap::new(),
190                next_key: None,
191            },
192        })
193    }
194}
195
196use serde::ser::{
197    SerializeMap, SerializeSeq, SerializeStruct, SerializeStructVariant, SerializeTuple,
198    SerializeTupleStruct, SerializeTupleVariant,
199};
200use std::collections::BTreeMap;
201
202struct SequenceSerializer {
203    values: Vec<Value>,
204}
205impl SerializeSeq for SequenceSerializer {
206    type Ok = Value;
207    type Error = SerializeError;
208    fn serialize_element<T: ?Sized + Serialize>(&mut self, value: &T) -> Result<()> {
209        self.values.push(value.serialize(ValueSerializer)?);
210        Ok(())
211    }
212    fn end(self) -> Result<Value> {
213        Ok(Value::Array(self.values))
214    }
215}
216impl SerializeTuple for SequenceSerializer {
217    type Ok = Value;
218    type Error = SerializeError;
219    fn serialize_element<T: ?Sized + Serialize>(&mut self, value: &T) -> Result<()> {
220        self.values.push(value.serialize(ValueSerializer)?);
221        Ok(())
222    }
223    fn end(self) -> Result<Value> {
224        Ok(Value::Array(self.values))
225    }
226}
227impl SerializeTupleStruct for SequenceSerializer {
228    type Ok = Value;
229    type Error = SerializeError;
230    fn serialize_field<T: ?Sized + Serialize>(&mut self, value: &T) -> Result<()> {
231        self.values.push(value.serialize(ValueSerializer)?);
232        Ok(())
233    }
234    fn end(self) -> Result<Value> {
235        Ok(Value::Array(self.values))
236    }
237}
238
239struct VariantSequenceSerializer {
240    variant: String,
241    values: Vec<Value>,
242}
243impl SerializeTupleVariant for VariantSequenceSerializer {
244    type Ok = Value;
245    type Error = SerializeError;
246    fn serialize_field<T: ?Sized + Serialize>(&mut self, value: &T) -> Result<()> {
247        self.values.push(value.serialize(ValueSerializer)?);
248        Ok(())
249    }
250    fn end(self) -> Result<Value> {
251        let mut map = BTreeMap::new();
252        map.insert(self.variant, Value::Array(self.values));
253        Ok(Value::Object(map))
254    }
255}
256
257struct MapSerializer {
258    values: BTreeMap<String, Value>,
259    next_key: Option<String>,
260}
261impl SerializeMap for MapSerializer {
262    type Ok = Value;
263    type Error = SerializeError;
264    fn serialize_key<T: ?Sized + Serialize>(&mut self, key: &T) -> Result<()> {
265        let Value::String(key) = key.serialize(ValueKeySerializer)? else {
266            return Err(SerializeError("map keys must be strings".to_string()));
267        };
268        self.next_key = Some(key);
269        Ok(())
270    }
271    fn serialize_value<T: ?Sized + Serialize>(&mut self, value: &T) -> Result<()> {
272        let key = self
273            .next_key
274            .take()
275            .ok_or_else(|| SerializeError("map value without key".to_string()))?;
276        self.values.insert(key, value.serialize(ValueSerializer)?);
277        Ok(())
278    }
279    fn end(self) -> Result<Value> {
280        Ok(Value::Object(self.values))
281    }
282}
283impl SerializeStruct for MapSerializer {
284    type Ok = Value;
285    type Error = SerializeError;
286    fn serialize_field<T: ?Sized + Serialize>(
287        &mut self,
288        key: &'static str,
289        value: &T,
290    ) -> Result<()> {
291        self.values
292            .insert(key.to_string(), value.serialize(ValueSerializer)?);
293        Ok(())
294    }
295    fn end(self) -> Result<Value> {
296        Ok(Value::Object(self.values))
297    }
298}
299
300struct VariantMapSerializer {
301    variant: String,
302    map: MapSerializer,
303}
304impl SerializeStructVariant for VariantMapSerializer {
305    type Ok = Value;
306    type Error = SerializeError;
307    fn serialize_field<T: ?Sized + Serialize>(
308        &mut self,
309        key: &'static str,
310        value: &T,
311    ) -> Result<()> {
312        self.map.serialize_field(key, value)
313    }
314    fn end(self) -> Result<Value> {
315        let mut outer = BTreeMap::new();
316        outer.insert(self.variant, Value::Object(self.map.values));
317        Ok(Value::Object(outer))
318    }
319}
320
321struct ValueKeySerializer;
322impl serde::Serializer for ValueKeySerializer {
323    type Ok = Value;
324    type Error = SerializeError;
325    type SerializeSeq = ser::Impossible<Value, SerializeError>;
326    type SerializeTuple = ser::Impossible<Value, SerializeError>;
327    type SerializeTupleStruct = ser::Impossible<Value, SerializeError>;
328    type SerializeTupleVariant = ser::Impossible<Value, SerializeError>;
329    type SerializeMap = ser::Impossible<Value, SerializeError>;
330    type SerializeStruct = ser::Impossible<Value, SerializeError>;
331    type SerializeStructVariant = ser::Impossible<Value, SerializeError>;
332    fn serialize_str(self, value: &str) -> Result<Value> {
333        Ok(Value::String(value.to_string()))
334    }
335    fn serialize_bool(self, _: bool) -> Result<Value> {
336        Err(SerializeError("map keys must be strings".to_string()))
337    }
338    fn serialize_i8(self, _: i8) -> Result<Value> {
339        Err(SerializeError("map keys must be strings".to_string()))
340    }
341    fn serialize_i16(self, _: i16) -> Result<Value> {
342        Err(SerializeError("map keys must be strings".to_string()))
343    }
344    fn serialize_i32(self, _: i32) -> Result<Value> {
345        Err(SerializeError("map keys must be strings".to_string()))
346    }
347    fn serialize_i64(self, _: i64) -> Result<Value> {
348        Err(SerializeError("map keys must be strings".to_string()))
349    }
350    fn serialize_u8(self, _: u8) -> Result<Value> {
351        Err(SerializeError("map keys must be strings".to_string()))
352    }
353    fn serialize_u16(self, _: u16) -> Result<Value> {
354        Err(SerializeError("map keys must be strings".to_string()))
355    }
356    fn serialize_u32(self, _: u32) -> Result<Value> {
357        Err(SerializeError("map keys must be strings".to_string()))
358    }
359    fn serialize_u64(self, _: u64) -> Result<Value> {
360        Err(SerializeError("map keys must be strings".to_string()))
361    }
362    fn serialize_f32(self, _: f32) -> Result<Value> {
363        Err(SerializeError("map keys must be strings".to_string()))
364    }
365    fn serialize_f64(self, _: f64) -> Result<Value> {
366        Err(SerializeError("map keys must be strings".to_string()))
367    }
368    fn serialize_char(self, _: char) -> Result<Value> {
369        Err(SerializeError("map keys must be strings".to_string()))
370    }
371    fn serialize_bytes(self, _: &[u8]) -> Result<Value> {
372        Err(SerializeError("map keys must be strings".to_string()))
373    }
374    fn serialize_none(self) -> Result<Value> {
375        Err(SerializeError("map keys must be strings".to_string()))
376    }
377    fn serialize_some<T: ?Sized + Serialize>(self, _: &T) -> Result<Value> {
378        Err(SerializeError("map keys must be strings".to_string()))
379    }
380    fn serialize_unit(self) -> Result<Value> {
381        Err(SerializeError("map keys must be strings".to_string()))
382    }
383    fn serialize_unit_struct(self, _: &'static str) -> Result<Value> {
384        Err(SerializeError("map keys must be strings".to_string()))
385    }
386    fn serialize_unit_variant(self, _: &'static str, _: u32, _: &'static str) -> Result<Value> {
387        Err(SerializeError("map keys must be strings".to_string()))
388    }
389    fn serialize_newtype_struct<T: ?Sized + Serialize>(
390        self,
391        _: &'static str,
392        _: &T,
393    ) -> Result<Value> {
394        Err(SerializeError("map keys must be strings".to_string()))
395    }
396    fn serialize_newtype_variant<T: ?Sized + Serialize>(
397        self,
398        _: &'static str,
399        _: u32,
400        _: &'static str,
401        _: &T,
402    ) -> Result<Value> {
403        Err(SerializeError("map keys must be strings".to_string()))
404    }
405    fn serialize_seq(self, _: Option<usize>) -> Result<Self::SerializeSeq> {
406        Err(SerializeError("map keys must be strings".to_string()))
407    }
408    fn serialize_tuple(self, _: usize) -> Result<Self::SerializeTuple> {
409        Err(SerializeError("map keys must be strings".to_string()))
410    }
411    fn serialize_tuple_struct(
412        self,
413        _: &'static str,
414        _: usize,
415    ) -> Result<Self::SerializeTupleStruct> {
416        Err(SerializeError("map keys must be strings".to_string()))
417    }
418    fn serialize_tuple_variant(
419        self,
420        _: &'static str,
421        _: u32,
422        _: &'static str,
423        _: usize,
424    ) -> Result<Self::SerializeTupleVariant> {
425        Err(SerializeError("map keys must be strings".to_string()))
426    }
427    fn serialize_map(self, _: Option<usize>) -> Result<Self::SerializeMap> {
428        Err(SerializeError("map keys must be strings".to_string()))
429    }
430    fn serialize_struct(self, _: &'static str, _: usize) -> Result<Self::SerializeStruct> {
431        Err(SerializeError("map keys must be strings".to_string()))
432    }
433    fn serialize_struct_variant(
434        self,
435        _: &'static str,
436        _: u32,
437        _: &'static str,
438        _: usize,
439    ) -> Result<Self::SerializeStructVariant> {
440        Err(SerializeError("map keys must be strings".to_string()))
441    }
442}
443
444/// Best-effort numeric visit for a [`Value::Number`] literal: integer first
445/// (covers a magnitude-only-oversized integer literal), else lossy `f64`.
446fn visit_number_literal<'de, V: de::Visitor<'de>>(
447    text: &str,
448    visitor: V,
449) -> Result<V::Value, serde::de::value::Error> {
450    if let Ok(value) = text.parse::<i64>() {
451        return visitor.visit_i64(value);
452    }
453    if let Ok(value) = text.parse::<u64>() {
454        return visitor.visit_u64(value);
455    }
456    match text.parse::<f64>() {
457        Ok(value) => visitor.visit_f64(value),
458        Err(_) => Err(de::Error::custom(format!(
459            "invalid numeric literal `{text}`"
460        ))),
461    }
462}
463
464struct ValueDeserializer<'a>(&'a Value);
465
466macro_rules! string_number {
467    ($method:ident, $type:ty, $visit:ident) => {
468        fn $method<V: serde::de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
469            match self.0 {
470                Value::String(value) => value
471                    .parse::<$type>()
472                    .map_err(|_| de::Error::custom("invalid numeric string"))
473                    .and_then(|value| visitor.$visit(value)),
474                _ => self.deserialize_any(visitor),
475            }
476        }
477    };
478}
479
480impl<'de, 'a> serde::Deserializer<'de> for ValueDeserializer<'a>
481where
482    'a: 'de,
483{
484    type Error = serde::de::value::Error;
485
486    fn deserialize_any<V: serde::de::Visitor<'de>>(
487        self,
488        visitor: V,
489    ) -> Result<V::Value, Self::Error> {
490        match self.0 {
491            Value::Null => visitor.visit_unit(),
492            Value::Bool(value) => visitor.visit_bool(*value),
493            Value::Integer(value) => visitor.visit_i64(*value),
494            Value::Unsigned(value) => visitor.visit_u64(*value),
495            Value::Float(value) => visitor.visit_f64(*value),
496            // A `Value::Number` literal only exists because it does not fit
497            // `i64`/`u64`/`f64` cleanly at the source-text level (e.g. an
498            // integer beyond `u64::MAX`), but a typed Rust struct field can
499            // only ever hold one of those three widths anyway — so a
500            // best-effort numeric visit (integer first, else lossy `f64`) is
501            // the most faithful a generic typed decode can be here. Callers
502            // that need the exact digits read the untyped `Value` via
503            // `Value::as_number_literal` instead of decoding through serde.
504            Value::Number(text) => visit_number_literal(text, visitor),
505            Value::String(value) => visitor.visit_string(value.clone()),
506            Value::Array(values) => visitor.visit_seq(BorrowedSeqAccess {
507                values: values.iter(),
508            }),
509            Value::Object(values) => visitor.visit_map(BorrowedMapAccess {
510                values: values.iter(),
511                pending: None,
512            }),
513        }
514    }
515
516    fn deserialize_option<V: serde::de::Visitor<'de>>(
517        self,
518        visitor: V,
519    ) -> Result<V::Value, Self::Error> {
520        if self.0.is_null() {
521            visitor.visit_none()
522        } else {
523            visitor.visit_some(self)
524        }
525    }
526
527    fn deserialize_enum<V: serde::de::Visitor<'de>>(
528        self,
529        _name: &'static str,
530        _variants: &'static [&'static str],
531        visitor: V,
532    ) -> Result<V::Value, Self::Error> {
533        match self.0 {
534            Value::String(variant) => visitor.visit_enum(EnumAccess {
535                variant: variant.clone(),
536                value: None,
537            }),
538            Value::Object(values) if values.len() == 1 => {
539                let mut entries = values.iter();
540                if let Some((variant, value)) = entries.next() {
541                    visitor.visit_enum(EnumAccess {
542                        variant: variant.clone(),
543                        value: Some(value),
544                    })
545                } else {
546                    Err(de::Error::custom("missing enum variant"))
547                }
548            }
549            _ => Err(de::Error::custom(
550                "expected enum variant string or single-key object",
551            )),
552        }
553    }
554
555    fn deserialize_bool<V: serde::de::Visitor<'de>>(
556        self,
557        visitor: V,
558    ) -> Result<V::Value, Self::Error> {
559        match self.0 {
560            Value::String(value) => match value.to_ascii_lowercase().as_str() {
561                "true" | "yes" | "on" | "1" => visitor.visit_bool(true),
562                "false" | "no" | "off" | "0" => visitor.visit_bool(false),
563                _ => Err(de::Error::custom("invalid boolean string")),
564            },
565            _ => self.deserialize_any(visitor),
566        }
567    }
568
569    string_number!(deserialize_i8, i8, visit_i8);
570    string_number!(deserialize_i16, i16, visit_i16);
571    string_number!(deserialize_i32, i32, visit_i32);
572    string_number!(deserialize_i64, i64, visit_i64);
573    string_number!(deserialize_i128, i128, visit_i128);
574    string_number!(deserialize_u8, u8, visit_u8);
575    string_number!(deserialize_u16, u16, visit_u16);
576    string_number!(deserialize_u32, u32, visit_u32);
577    string_number!(deserialize_u64, u64, visit_u64);
578    string_number!(deserialize_u128, u128, visit_u128);
579    string_number!(deserialize_f32, f32, visit_f32);
580    string_number!(deserialize_f64, f64, visit_f64);
581
582    serde::forward_to_deserialize_any! {
583        char str string bytes byte_buf
584        unit unit_struct newtype_struct seq tuple tuple_struct map struct identifier ignored_any
585    }
586}
587
588struct BorrowedSeqAccess<'a> {
589    values: std::slice::Iter<'a, Value>,
590}
591
592impl<'de, 'a> serde::de::SeqAccess<'de> for BorrowedSeqAccess<'a>
593where
594    'a: 'de,
595{
596    type Error = serde::de::value::Error;
597    fn next_element_seed<T: serde::de::DeserializeSeed<'de>>(
598        &mut self,
599        seed: T,
600    ) -> Result<Option<T::Value>, Self::Error> {
601        self.values
602            .next()
603            .map(|value| seed.deserialize(ValueDeserializer(value)))
604            .transpose()
605    }
606}
607
608struct BorrowedMapAccess<'a> {
609    values: std::collections::btree_map::Iter<'a, String, Value>,
610    pending: Option<&'a Value>,
611}
612
613impl<'de, 'a> serde::de::MapAccess<'de> for BorrowedMapAccess<'a>
614where
615    'a: 'de,
616{
617    type Error = serde::de::value::Error;
618    fn next_key_seed<K: serde::de::DeserializeSeed<'de>>(
619        &mut self,
620        seed: K,
621    ) -> Result<Option<K::Value>, Self::Error> {
622        match self.values.next() {
623            Some((key, value)) => {
624                self.pending = Some(value);
625                seed.deserialize(serde::de::IntoDeserializer::into_deserializer(key.clone()))
626                    .map(Some)
627            }
628            None => Ok(None),
629        }
630    }
631    fn next_value_seed<V: serde::de::DeserializeSeed<'de>>(
632        &mut self,
633        seed: V,
634    ) -> Result<V::Value, Self::Error> {
635        let value = self
636            .pending
637            .take()
638            .ok_or_else(|| de::Error::custom("map value without key"))?;
639        seed.deserialize(ValueDeserializer(value))
640    }
641}
642
643struct EnumAccess<'a> {
644    variant: String,
645    value: Option<&'a Value>,
646}
647
648impl<'de, 'a> serde::de::EnumAccess<'de> for EnumAccess<'a>
649where
650    'a: 'de,
651{
652    type Error = serde::de::value::Error;
653    type Variant = VariantAccess<'a>;
654    fn variant_seed<V: serde::de::DeserializeSeed<'de>>(
655        self,
656        seed: V,
657    ) -> Result<(V::Value, Self::Variant), Self::Error> {
658        let variant =
659            seed.deserialize(serde::de::IntoDeserializer::into_deserializer(self.variant))?;
660        Ok((variant, VariantAccess { value: self.value }))
661    }
662}
663
664struct VariantAccess<'a> {
665    value: Option<&'a Value>,
666}
667
668#[cfg(test)]
669mod tests {
670    use super::{from_value, to_value};
671    use crate::document::Value;
672    use serde::{Deserialize, Serialize};
673
674    #[derive(Debug, PartialEq, Serialize, Deserialize)]
675    struct Config {
676        name: String,
677        enabled: Option<bool>,
678        #[serde(flatten)]
679        extra: Extra,
680    }
681
682    #[derive(Debug, PartialEq, Serialize, Deserialize)]
683    struct Extra {
684        count: u64,
685    }
686
687    #[derive(Debug, PartialEq, Serialize, Deserialize)]
688    enum Mode {
689        Fast,
690        Custom { level: u32 },
691    }
692
693    #[test]
694    fn round_trips_struct_optional_flatten_and_enum() {
695        let value = Value::Object(std::collections::BTreeMap::from([
696            ("name".to_string(), Value::String("demo".to_string())),
697            ("enabled".to_string(), Value::Null),
698            ("count".to_string(), Value::Unsigned(9)),
699        ]));
700        let config: Config = from_value(&value, "root").unwrap_or_else(|error| panic!("{error}"));
701        assert_eq!(config.name, "demo");
702        assert_eq!(config.enabled, None);
703        assert_eq!(config.extra.count, 9);
704        let mode = Mode::Custom { level: 3 };
705        assert_eq!(
706            from_value(&to_value(&mode).unwrap_or(Value::Null), "mode").unwrap_or(Mode::Fast),
707            mode
708        );
709    }
710
711    #[derive(Debug, Deserialize)]
712    #[serde(deny_unknown_fields)]
713    struct Strict {
714        #[allow(dead_code)]
715        name: String,
716    }
717
718    #[test]
719    fn reports_typed_path_and_unknown_field() {
720        let value = Value::Object(std::collections::BTreeMap::from([
721            ("name".to_string(), Value::String("demo".to_string())),
722            ("extra".to_string(), Value::Bool(true)),
723        ]));
724        let error = from_value::<Strict>(&value, "settings").expect_err("unknown field must fail");
725        assert!(error.to_string().contains("settings"));
726        assert!(error.to_string().contains("unknown field"));
727    }
728
729    #[test]
730    fn directs_string_leaves_into_typed_scalars() {
731        let value = Value::Object(std::collections::BTreeMap::from([
732            ("enabled".to_string(), Value::String("yes".to_string())),
733            ("count".to_string(), Value::String("42".to_string())),
734        ]));
735        #[derive(Debug, Deserialize, PartialEq)]
736        struct StringBacked {
737            enabled: bool,
738            count: u64,
739        }
740        assert_eq!(
741            from_value::<StringBacked>(&value, "env").unwrap_or_else(|error| panic!("{error}")),
742            StringBacked {
743                enabled: true,
744                count: 42
745            }
746        );
747    }
748}
749impl<'de, 'a> serde::de::VariantAccess<'de> for VariantAccess<'a>
750where
751    'a: 'de,
752{
753    type Error = serde::de::value::Error;
754    fn unit_variant(self) -> Result<(), Self::Error> {
755        if self.value.is_none() {
756            Ok(())
757        } else {
758            Err(de::Error::custom("expected unit variant"))
759        }
760    }
761    fn newtype_variant_seed<T: serde::de::DeserializeSeed<'de>>(
762        self,
763        seed: T,
764    ) -> Result<T::Value, Self::Error> {
765        seed.deserialize(ValueDeserializer(
766            self.value
767                .ok_or_else(|| de::Error::custom("missing newtype value"))?,
768        ))
769    }
770    fn tuple_variant<V: serde::de::Visitor<'de>>(
771        self,
772        _len: usize,
773        visitor: V,
774    ) -> Result<V::Value, Self::Error> {
775        ValueDeserializer(
776            self.value
777                .ok_or_else(|| de::Error::custom("missing tuple value"))?,
778        )
779        .deserialize_seq(visitor)
780    }
781    fn struct_variant<V: serde::de::Visitor<'de>>(
782        self,
783        _fields: &'static [&'static str],
784        visitor: V,
785    ) -> Result<V::Value, Self::Error> {
786        ValueDeserializer(
787            self.value
788                .ok_or_else(|| de::Error::custom("missing struct value"))?,
789        )
790        .deserialize_map(visitor)
791    }
792}