rust_yaml/serde_integration/
value.rs1use 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}