Skip to main content

rust_yaml/serde_integration/
value.rs

1//! `Serialize` / `Deserialize` impls for the public `Value` type.
2
3use crate::Value;
4use serde::{
5    de::{Deserialize, Deserializer, MapAccess, SeqAccess, Visitor},
6    ser::{Serialize, SerializeMap, SerializeSeq, Serializer},
7};
8use std::fmt;
9
10impl Serialize for Value {
11    fn serialize<S: Serializer>(&self, ser: S) -> Result<S::Ok, S::Error> {
12        match self {
13            Value::Null => ser.serialize_unit(),
14            Value::Bool(b) => ser.serialize_bool(*b),
15            Value::Int(i) => ser.serialize_i64(*i),
16            Value::Float(f) => ser.serialize_f64(*f),
17            Value::String(s) => ser.serialize_str(s),
18            Value::Sequence(seq) => {
19                let mut s = ser.serialize_seq(Some(seq.len()))?;
20                for item in seq {
21                    s.serialize_element(item)?;
22                }
23                s.end()
24            }
25            Value::Mapping(map) => {
26                let mut m = ser.serialize_map(Some(map.len()))?;
27                for (k, v) in map {
28                    m.serialize_entry(k, v)?;
29                }
30                m.end()
31            }
32        }
33    }
34}
35
36impl<'de> Deserialize<'de> for Value {
37    fn deserialize<D: Deserializer<'de>>(de: D) -> Result<Self, D::Error> {
38        de.deserialize_any(ValueVisitor)
39    }
40}
41
42struct ValueVisitor;
43
44impl<'de> Visitor<'de> for ValueVisitor {
45    type Value = Value;
46
47    fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
48        f.write_str("any YAML-compatible value")
49    }
50
51    fn visit_unit<E>(self) -> Result<Value, E> {
52        Ok(Value::Null)
53    }
54    fn visit_none<E>(self) -> Result<Value, E> {
55        Ok(Value::Null)
56    }
57    fn visit_some<D: Deserializer<'de>>(self, d: D) -> Result<Value, D::Error> {
58        Value::deserialize(d)
59    }
60
61    fn visit_bool<E>(self, b: bool) -> Result<Value, E> {
62        Ok(Value::Bool(b))
63    }
64
65    fn visit_i64<E>(self, i: i64) -> Result<Value, E> {
66        Ok(Value::Int(i))
67    }
68    fn visit_i128<E: serde::de::Error>(self, i: i128) -> Result<Value, E> {
69        i64::try_from(i)
70            .map(Value::Int)
71            .map_err(|_| E::custom("integer out of range for i64"))
72    }
73    fn visit_u64<E: serde::de::Error>(self, u: u64) -> Result<Value, E> {
74        i64::try_from(u)
75            .map(Value::Int)
76            .map_err(|_| E::custom("integer out of range for i64"))
77    }
78    fn visit_u128<E: serde::de::Error>(self, u: u128) -> Result<Value, E> {
79        i64::try_from(u)
80            .map(Value::Int)
81            .map_err(|_| E::custom("integer out of range for i64"))
82    }
83
84    fn visit_f64<E>(self, f: f64) -> Result<Value, E> {
85        Ok(Value::Float(f))
86    }
87
88    fn visit_str<E>(self, s: &str) -> Result<Value, E> {
89        Ok(Value::String(s.to_owned()))
90    }
91    fn visit_string<E>(self, s: String) -> Result<Value, E> {
92        Ok(Value::String(s))
93    }
94    fn visit_borrowed_str<E>(self, s: &'de str) -> Result<Value, E> {
95        Ok(Value::String(s.to_owned()))
96    }
97
98    fn visit_seq<A: SeqAccess<'de>>(self, mut seq: A) -> Result<Value, A::Error> {
99        let mut out = Vec::with_capacity(seq.size_hint().unwrap_or(0));
100        while let Some(elem) = seq.next_element()? {
101            out.push(elem);
102        }
103        Ok(Value::Sequence(out))
104    }
105
106    fn visit_map<A: MapAccess<'de>>(self, mut map: A) -> Result<Value, A::Error> {
107        let mut out = indexmap::IndexMap::with_capacity(map.size_hint().unwrap_or(0));
108        while let Some((k, v)) = map.next_entry()? {
109            out.insert(k, v);
110        }
111        Ok(Value::Mapping(out))
112    }
113}
114
115#[cfg(test)]
116mod ser_tests {
117    use crate::Value;
118    use indexmap::IndexMap;
119
120    #[test]
121    fn value_serializes_through_serde_json() {
122        let mut m = IndexMap::new();
123        m.insert(Value::String("name".into()), Value::String("rust".into()));
124        m.insert(Value::String("ver".into()), Value::Int(11));
125        let v = Value::Mapping(m);
126
127        let j = serde_json::to_string(&v).expect("serialize through serde_json");
128        assert_eq!(j, r#"{"name":"rust","ver":11}"#);
129    }
130
131    #[test]
132    fn null_int_float_bool_seq_serialize() {
133        assert_eq!(serde_json::to_string(&Value::Null).unwrap(), "null");
134        assert_eq!(serde_json::to_string(&Value::Bool(true)).unwrap(), "true");
135        assert_eq!(serde_json::to_string(&Value::Int(42)).unwrap(), "42");
136        assert_eq!(serde_json::to_string(&Value::Float(1.5)).unwrap(), "1.5");
137        let seq = Value::Sequence(vec![Value::Int(1), Value::Int(2)]);
138        assert_eq!(serde_json::to_string(&seq).unwrap(), "[1,2]");
139    }
140}
141
142#[cfg(test)]
143mod de_tests {
144    use crate::Value;
145
146    #[test]
147    fn value_deserializes_from_serde_json() {
148        let json = r#"{"name":"rust","ver":11,"flags":[true,false]}"#;
149        let v: Value = serde_json::from_str(json).expect("parse via serde_json");
150        let map = v.as_mapping().expect("mapping");
151        assert_eq!(
152            map.get(&Value::String("name".into())),
153            Some(&Value::String("rust".into()))
154        );
155        assert_eq!(map.get(&Value::String("ver".into())), Some(&Value::Int(11)));
156    }
157}