1use indexmap::IndexMap;
4use serde::de::{self, MapAccess, SeqAccess};
5use serde::ser::SerializeMap;
6use serde::{Deserialize, Deserializer, Serialize, Serializer};
7
8pub type NodeMap = IndexMap<String, Node>;
10
11#[derive(Debug, Clone, PartialEq, Default)]
20pub enum Node {
21 #[default]
23 Null,
24 Bool(bool),
26 Int(i64),
28 UInt(u64),
30 Float(f64),
32 String(String),
34 Array(Vec<Node>),
36 Object(NodeMap),
38}
39
40fn small_uint(value: u64) -> Node {
44 if value <= i64::MAX as u64 {
45 Node::Int(value as i64)
46 } else {
47 Node::UInt(value)
48 }
49}
50
51impl Serialize for Node {
52 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
53 match self {
54 Self::Null => serializer.serialize_none(),
55 Self::Bool(value) => serializer.serialize_bool(*value),
56 Self::Int(value) => serializer.serialize_i64(*value),
57 Self::UInt(value) => serializer.serialize_u64(*value),
58 Self::Float(value) => serializer.serialize_f64(*value),
59 Self::String(value) => serializer.serialize_str(value),
60 Self::Array(items) => items.serialize(serializer),
61 Self::Object(map) => {
62 let mut map_serializer = serializer.serialize_map(Some(map.len()))?;
63 for (key, value) in map {
64 map_serializer.serialize_entry(key, value)?;
65 }
66 map_serializer.end()
67 }
68 }
69 }
70}
71
72impl<'de> Deserialize<'de> for Node {
73 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
74 struct NodeVisitor;
75
76 impl<'de> de::Visitor<'de> for NodeVisitor {
77 type Value = Node;
78
79 fn expecting(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
80 f.write_str("any YAML or JSON value")
81 }
82
83 fn visit_bool<E: de::Error>(self, value: bool) -> Result<Node, E> {
84 Ok(Node::Bool(value))
85 }
86
87 fn visit_i64<E: de::Error>(self, value: i64) -> Result<Node, E> {
88 Ok(Node::Int(value))
89 }
90
91 fn visit_i128<E: de::Error>(self, value: i128) -> Result<Node, E> {
92 if value >= i64::MIN as i128 && value <= i64::MAX as i128 {
93 Ok(Node::Int(value as i64))
94 } else if value >= 0 && value <= u64::MAX as i128 {
95 Ok(Node::UInt(value as u64))
96 } else {
97 Err(E::custom("integer out of range"))
98 }
99 }
100
101 fn visit_u64<E: de::Error>(self, value: u64) -> Result<Node, E> {
102 Ok(small_uint(value))
103 }
104
105 fn visit_u128<E: de::Error>(self, value: u128) -> Result<Node, E> {
106 if value <= u64::MAX as u128 {
107 Ok(small_uint(value as u64))
108 } else {
109 Err(E::custom("integer out of range"))
110 }
111 }
112
113 fn visit_f64<E: de::Error>(self, value: f64) -> Result<Node, E> {
114 Ok(Node::Float(value))
115 }
116
117 fn visit_str<E: de::Error>(self, value: &str) -> Result<Node, E> {
118 Ok(Node::String(value.to_owned()))
119 }
120
121 fn visit_string<E: de::Error>(self, value: String) -> Result<Node, E> {
122 Ok(Node::String(value))
123 }
124
125 fn visit_none<E: de::Error>(self) -> Result<Node, E> {
126 Ok(Node::Null)
127 }
128
129 fn visit_unit<E: de::Error>(self) -> Result<Node, E> {
130 Ok(Node::Null)
131 }
132
133 fn visit_some<D: Deserializer<'de>>(self, deserializer: D) -> Result<Node, D::Error> {
134 deserializer.deserialize_any(self)
135 }
136
137 fn visit_seq<A: SeqAccess<'de>>(self, mut seq: A) -> Result<Node, A::Error> {
138 let mut items = Vec::new();
139 while let Some(item) = seq.next_element::<Node>()? {
140 items.push(item);
141 }
142 Ok(Node::Array(items))
143 }
144
145 fn visit_map<A: MapAccess<'de>>(self, mut map: A) -> Result<Node, A::Error> {
146 let mut entries = NodeMap::new();
147 while let Some((key, value)) = map.next_entry::<String, Node>()? {
148 entries.insert(key, value);
149 }
150 Ok(Node::Object(entries))
151 }
152 }
153
154 deserializer.deserialize_any(NodeVisitor)
155 }
156}
157
158impl Node {
159 pub fn as_str(&self) -> Option<&str> {
161 match self {
162 Self::String(value) => Some(value),
163 _ => None,
164 }
165 }
166
167 pub fn as_i64(&self) -> Option<i64> {
169 match self {
170 Self::Int(value) => Some(*value),
171 Self::UInt(value) => i64::try_from(*value).ok(),
172 _ => None,
173 }
174 }
175
176 pub fn as_bool(&self) -> Option<bool> {
178 match self {
179 Self::Bool(value) => Some(*value),
180 _ => None,
181 }
182 }
183
184 pub fn as_object(&self) -> Option<&NodeMap> {
186 match self {
187 Self::Object(map) => Some(map),
188 _ => None,
189 }
190 }
191
192 pub fn as_array(&self) -> Option<&[Node]> {
194 match self {
195 Self::Array(items) => Some(items),
196 _ => None,
197 }
198 }
199
200 pub fn is_null(&self) -> bool {
202 matches!(self, Self::Null)
203 }
204}
205
206impl From<bool> for Node {
207 fn from(value: bool) -> Self {
208 Self::Bool(value)
209 }
210}
211
212impl From<i8> for Node {
213 fn from(value: i8) -> Self {
214 Self::Int(value as i64)
215 }
216}
217
218impl From<i16> for Node {
219 fn from(value: i16) -> Self {
220 Self::Int(value as i64)
221 }
222}
223
224impl From<i32> for Node {
225 fn from(value: i32) -> Self {
226 Self::Int(value as i64)
227 }
228}
229
230impl From<isize> for Node {
231 fn from(value: isize) -> Self {
232 Self::Int(value as i64)
233 }
234}
235
236impl From<u8> for Node {
237 fn from(value: u8) -> Self {
238 Self::Int(value as i64)
239 }
240}
241
242impl From<u16> for Node {
243 fn from(value: u16) -> Self {
244 Self::Int(value as i64)
245 }
246}
247
248impl From<u32> for Node {
249 fn from(value: u32) -> Self {
250 Self::Int(value as i64)
251 }
252}
253
254impl From<i64> for Node {
255 fn from(value: i64) -> Self {
256 Self::Int(value)
257 }
258}
259
260impl From<u64> for Node {
261 fn from(value: u64) -> Self {
262 small_uint(value)
263 }
264}
265
266impl From<f64> for Node {
267 fn from(value: f64) -> Self {
268 Self::Float(value)
269 }
270}
271
272impl From<usize> for Node {
273 fn from(value: usize) -> Self {
274 small_uint(value as u64)
275 }
276}
277
278impl std::ops::Index<&str> for Node {
283 type Output = Node;
284
285 fn index(&self, key: &str) -> &Node {
286 static NULL: Node = Node::Null;
287 self.as_object()
288 .and_then(|map| map.get(key))
289 .unwrap_or(&NULL)
290 }
291}
292
293impl From<&str> for Node {
294 fn from(value: &str) -> Self {
295 Self::String(value.to_owned())
296 }
297}
298
299impl From<String> for Node {
300 fn from(value: String) -> Self {
301 Self::String(value)
302 }
303}
304
305impl From<Vec<Node>> for Node {
306 fn from(value: Vec<Node>) -> Self {
307 Self::Array(value)
308 }
309}
310
311impl From<NodeMap> for Node {
312 fn from(value: NodeMap) -> Self {
313 Self::Object(value)
314 }
315}
316
317impl FromIterator<(String, Node)> for Node {
318 fn from_iter<I: IntoIterator<Item = (String, Node)>>(iter: I) -> Self {
319 Self::Object(NodeMap::from_iter(iter))
320 }
321}
322
323#[cfg(test)]
324mod tests {
325 use super::*;
326
327 #[test]
328 fn yaml_round_trip_preserves_key_order() {
329 let node: Node = serde_yaml_ng::from_str("b: 1\na: 2\nc: [x, y]").unwrap();
330 let text = serde_yaml_ng::to_string(&node).unwrap();
331 assert!(text.contains("b: 1"), "{text}");
332 assert!(text.contains("a: 2"), "{text}");
333 let back: Node = serde_yaml_ng::from_str(&text).unwrap();
334 assert_eq!(node, back);
335 }
336
337 #[test]
338 fn json_round_trip_preserves_key_order() {
339 let node: Node = serde_json::from_str(r#"{"b":1,"a":2,"c":[1,2.5,true,null]}"#).unwrap();
340 let text = serde_json::to_string(&node).unwrap();
341 assert_eq!(text, r#"{"b":1,"a":2,"c":[1,2.5,true,null]}"#);
342 let back: Node = serde_json::from_str(&text).unwrap();
343 assert_eq!(node, back);
344 }
345
346 #[test]
347 fn wide_integers_survive() {
348 let node: Node = serde_yaml_ng::from_str("big: 18446744073709551615").unwrap();
349 let Node::Object(map) = &node else {
350 panic!("expected object");
351 };
352 assert_eq!(map["big"], Node::UInt(u64::MAX));
353 let text = serde_yaml_ng::to_string(&node).unwrap();
354 assert!(text.contains("18446744073709551615"), "{text}");
355 }
356}