1 //! YAML Serialization
2 //!
3 //! This module provides YAML serialization with the type `Serializer`.
4 
5 use crate::{error, Error, Result};
6 use serde::{ser, serde_if_integer128};
7 use std::{fmt, io, num, str};
8 use yaml_rust::{yaml, Yaml, YamlEmitter};
9 
10 pub struct Serializer;
11 
12 impl ser::Serializer for Serializer {
13     type Ok = Yaml;
14     type Error = Error;
15 
16     type SerializeSeq = SerializeArray;
17     type SerializeTuple = SerializeArray;
18     type SerializeTupleStruct = SerializeArray;
19     type SerializeTupleVariant = SerializeTupleVariant;
20     type SerializeMap = SerializeMap;
21     type SerializeStruct = SerializeStruct;
22     type SerializeStructVariant = SerializeStructVariant;
23 
serialize_bool(self, v: bool) -> Result<Yaml>24     fn serialize_bool(self, v: bool) -> Result<Yaml> {
25         Ok(Yaml::Boolean(v))
26     }
27 
serialize_i8(self, v: i8) -> Result<Yaml>28     fn serialize_i8(self, v: i8) -> Result<Yaml> {
29         self.serialize_i64(v as i64)
30     }
31 
serialize_i16(self, v: i16) -> Result<Yaml>32     fn serialize_i16(self, v: i16) -> Result<Yaml> {
33         self.serialize_i64(v as i64)
34     }
35 
serialize_i32(self, v: i32) -> Result<Yaml>36     fn serialize_i32(self, v: i32) -> Result<Yaml> {
37         self.serialize_i64(v as i64)
38     }
39 
serialize_i64(self, v: i64) -> Result<Yaml>40     fn serialize_i64(self, v: i64) -> Result<Yaml> {
41         Ok(Yaml::Integer(v))
42     }
43 
44     serde_if_integer128! {
45         #[allow(clippy::cast_possible_truncation)]
46         fn serialize_i128(self, v: i128) -> Result<Yaml> {
47             if v <= i64::max_value() as i128 && v >= i64::min_value() as i128 {
48                 self.serialize_i64(v as i64)
49             } else {
50                 Ok(Yaml::Real(v.to_string()))
51             }
52         }
53     }
54 
serialize_u8(self, v: u8) -> Result<Yaml>55     fn serialize_u8(self, v: u8) -> Result<Yaml> {
56         self.serialize_i64(v as i64)
57     }
58 
serialize_u16(self, v: u16) -> Result<Yaml>59     fn serialize_u16(self, v: u16) -> Result<Yaml> {
60         self.serialize_i64(v as i64)
61     }
62 
serialize_u32(self, v: u32) -> Result<Yaml>63     fn serialize_u32(self, v: u32) -> Result<Yaml> {
64         self.serialize_i64(v as i64)
65     }
66 
serialize_u64(self, v: u64) -> Result<Yaml>67     fn serialize_u64(self, v: u64) -> Result<Yaml> {
68         if v <= i64::max_value() as u64 {
69             self.serialize_i64(v as i64)
70         } else {
71             Ok(Yaml::Real(v.to_string()))
72         }
73     }
74 
75     serde_if_integer128! {
76         #[allow(clippy::cast_possible_truncation)]
77         fn serialize_u128(self, v: u128) -> Result<Yaml> {
78             if v <= i64::max_value() as u128 {
79                 self.serialize_i64(v as i64)
80             } else {
81                 Ok(Yaml::Real(v.to_string()))
82             }
83         }
84     }
85 
serialize_f32(self, v: f32) -> Result<Yaml>86     fn serialize_f32(self, v: f32) -> Result<Yaml> {
87         self.serialize_f64(v as f64)
88     }
89 
serialize_f64(self, v: f64) -> Result<Yaml>90     fn serialize_f64(self, v: f64) -> Result<Yaml> {
91         Ok(Yaml::Real(match v.classify() {
92             num::FpCategory::Infinite if v.is_sign_positive() => ".inf".into(),
93             num::FpCategory::Infinite => "-.inf".into(),
94             num::FpCategory::Nan => ".nan".into(),
95             _ => {
96                 let mut buf = vec![];
97                 ::dtoa::write(&mut buf, v).unwrap();
98                 ::std::str::from_utf8(&buf).unwrap().into()
99             }
100         }))
101     }
102 
serialize_char(self, value: char) -> Result<Yaml>103     fn serialize_char(self, value: char) -> Result<Yaml> {
104         Ok(Yaml::String(value.to_string()))
105     }
106 
serialize_str(self, value: &str) -> Result<Yaml>107     fn serialize_str(self, value: &str) -> Result<Yaml> {
108         Ok(Yaml::String(value.to_owned()))
109     }
110 
serialize_bytes(self, value: &[u8]) -> Result<Yaml>111     fn serialize_bytes(self, value: &[u8]) -> Result<Yaml> {
112         let vec = value.iter().map(|&b| Yaml::Integer(b as i64)).collect();
113         Ok(Yaml::Array(vec))
114     }
115 
serialize_unit(self) -> Result<Yaml>116     fn serialize_unit(self) -> Result<Yaml> {
117         Ok(Yaml::Null)
118     }
119 
serialize_unit_struct(self, _name: &'static str) -> Result<Yaml>120     fn serialize_unit_struct(self, _name: &'static str) -> Result<Yaml> {
121         self.serialize_unit()
122     }
123 
serialize_unit_variant( self, _name: &str, _variant_index: u32, variant: &str, ) -> Result<Yaml>124     fn serialize_unit_variant(
125         self,
126         _name: &str,
127         _variant_index: u32,
128         variant: &str,
129     ) -> Result<Yaml> {
130         Ok(Yaml::String(variant.to_owned()))
131     }
132 
serialize_newtype_struct<T: ?Sized>(self, _name: &'static str, value: &T) -> Result<Yaml> where T: ser::Serialize,133     fn serialize_newtype_struct<T: ?Sized>(self, _name: &'static str, value: &T) -> Result<Yaml>
134     where
135         T: ser::Serialize,
136     {
137         value.serialize(self)
138     }
139 
serialize_newtype_variant<T: ?Sized>( self, _name: &str, _variant_index: u32, variant: &str, value: &T, ) -> Result<Yaml> where T: ser::Serialize,140     fn serialize_newtype_variant<T: ?Sized>(
141         self,
142         _name: &str,
143         _variant_index: u32,
144         variant: &str,
145         value: &T,
146     ) -> Result<Yaml>
147     where
148         T: ser::Serialize,
149     {
150         Ok(singleton_hash(to_yaml(variant)?, to_yaml(value)?))
151     }
152 
serialize_none(self) -> Result<Yaml>153     fn serialize_none(self) -> Result<Yaml> {
154         self.serialize_unit()
155     }
156 
serialize_some<V: ?Sized>(self, value: &V) -> Result<Yaml> where V: ser::Serialize,157     fn serialize_some<V: ?Sized>(self, value: &V) -> Result<Yaml>
158     where
159         V: ser::Serialize,
160     {
161         value.serialize(self)
162     }
163 
serialize_seq(self, len: Option<usize>) -> Result<SerializeArray>164     fn serialize_seq(self, len: Option<usize>) -> Result<SerializeArray> {
165         let array = match len {
166             None => yaml::Array::new(),
167             Some(len) => yaml::Array::with_capacity(len),
168         };
169         Ok(SerializeArray { array })
170     }
171 
serialize_tuple(self, len: usize) -> Result<SerializeArray>172     fn serialize_tuple(self, len: usize) -> Result<SerializeArray> {
173         self.serialize_seq(Some(len))
174     }
175 
serialize_tuple_struct(self, _name: &'static str, len: usize) -> Result<SerializeArray>176     fn serialize_tuple_struct(self, _name: &'static str, len: usize) -> Result<SerializeArray> {
177         self.serialize_seq(Some(len))
178     }
179 
serialize_tuple_variant( self, _enum: &'static str, _idx: u32, variant: &'static str, len: usize, ) -> Result<SerializeTupleVariant>180     fn serialize_tuple_variant(
181         self,
182         _enum: &'static str,
183         _idx: u32,
184         variant: &'static str,
185         len: usize,
186     ) -> Result<SerializeTupleVariant> {
187         Ok(SerializeTupleVariant {
188             name: variant,
189             array: yaml::Array::with_capacity(len),
190         })
191     }
192 
serialize_map(self, _len: Option<usize>) -> Result<SerializeMap>193     fn serialize_map(self, _len: Option<usize>) -> Result<SerializeMap> {
194         Ok(SerializeMap {
195             hash: yaml::Hash::new(),
196             next_key: None,
197         })
198     }
199 
serialize_struct(self, _name: &'static str, _len: usize) -> Result<SerializeStruct>200     fn serialize_struct(self, _name: &'static str, _len: usize) -> Result<SerializeStruct> {
201         Ok(SerializeStruct {
202             hash: yaml::Hash::new(),
203         })
204     }
205 
serialize_struct_variant( self, _enum: &'static str, _idx: u32, variant: &'static str, _len: usize, ) -> Result<SerializeStructVariant>206     fn serialize_struct_variant(
207         self,
208         _enum: &'static str,
209         _idx: u32,
210         variant: &'static str,
211         _len: usize,
212     ) -> Result<SerializeStructVariant> {
213         Ok(SerializeStructVariant {
214             name: variant,
215             hash: yaml::Hash::new(),
216         })
217     }
218 }
219 
220 #[doc(hidden)]
221 pub struct SerializeArray {
222     array: yaml::Array,
223 }
224 
225 #[doc(hidden)]
226 pub struct SerializeTupleVariant {
227     name: &'static str,
228     array: yaml::Array,
229 }
230 
231 #[doc(hidden)]
232 pub struct SerializeMap {
233     hash: yaml::Hash,
234     next_key: Option<yaml::Yaml>,
235 }
236 
237 #[doc(hidden)]
238 pub struct SerializeStruct {
239     hash: yaml::Hash,
240 }
241 
242 #[doc(hidden)]
243 pub struct SerializeStructVariant {
244     name: &'static str,
245     hash: yaml::Hash,
246 }
247 
248 impl ser::SerializeSeq for SerializeArray {
249     type Ok = yaml::Yaml;
250     type Error = Error;
251 
serialize_element<T: ?Sized>(&mut self, elem: &T) -> Result<()> where T: ser::Serialize,252     fn serialize_element<T: ?Sized>(&mut self, elem: &T) -> Result<()>
253     where
254         T: ser::Serialize,
255     {
256         self.array.push(to_yaml(elem)?);
257         Ok(())
258     }
259 
end(self) -> Result<Yaml>260     fn end(self) -> Result<Yaml> {
261         Ok(Yaml::Array(self.array))
262     }
263 }
264 
265 impl ser::SerializeTuple for SerializeArray {
266     type Ok = yaml::Yaml;
267     type Error = Error;
268 
serialize_element<T: ?Sized>(&mut self, elem: &T) -> Result<()> where T: ser::Serialize,269     fn serialize_element<T: ?Sized>(&mut self, elem: &T) -> Result<()>
270     where
271         T: ser::Serialize,
272     {
273         ser::SerializeSeq::serialize_element(self, elem)
274     }
275 
end(self) -> Result<Yaml>276     fn end(self) -> Result<Yaml> {
277         ser::SerializeSeq::end(self)
278     }
279 }
280 
281 impl ser::SerializeTupleStruct for SerializeArray {
282     type Ok = yaml::Yaml;
283     type Error = Error;
284 
serialize_field<V: ?Sized>(&mut self, value: &V) -> Result<()> where V: ser::Serialize,285     fn serialize_field<V: ?Sized>(&mut self, value: &V) -> Result<()>
286     where
287         V: ser::Serialize,
288     {
289         ser::SerializeSeq::serialize_element(self, value)
290     }
291 
end(self) -> Result<Yaml>292     fn end(self) -> Result<Yaml> {
293         ser::SerializeSeq::end(self)
294     }
295 }
296 
297 impl ser::SerializeTupleVariant for SerializeTupleVariant {
298     type Ok = yaml::Yaml;
299     type Error = Error;
300 
serialize_field<V: ?Sized>(&mut self, v: &V) -> Result<()> where V: ser::Serialize,301     fn serialize_field<V: ?Sized>(&mut self, v: &V) -> Result<()>
302     where
303         V: ser::Serialize,
304     {
305         self.array.push(to_yaml(v)?);
306         Ok(())
307     }
308 
end(self) -> Result<Yaml>309     fn end(self) -> Result<Yaml> {
310         Ok(singleton_hash(to_yaml(self.name)?, Yaml::Array(self.array)))
311     }
312 }
313 
314 impl ser::SerializeMap for SerializeMap {
315     type Ok = yaml::Yaml;
316     type Error = Error;
317 
serialize_key<T: ?Sized>(&mut self, key: &T) -> Result<()> where T: ser::Serialize,318     fn serialize_key<T: ?Sized>(&mut self, key: &T) -> Result<()>
319     where
320         T: ser::Serialize,
321     {
322         self.next_key = Some(to_yaml(key)?);
323         Ok(())
324     }
325 
serialize_value<T: ?Sized>(&mut self, value: &T) -> Result<()> where T: ser::Serialize,326     fn serialize_value<T: ?Sized>(&mut self, value: &T) -> Result<()>
327     where
328         T: ser::Serialize,
329     {
330         match self.next_key.take() {
331             Some(key) => self.hash.insert(key, to_yaml(value)?),
332             None => panic!("serialize_value called before serialize_key"),
333         };
334         Ok(())
335     }
336 
serialize_entry<K: ?Sized, V: ?Sized>(&mut self, key: &K, value: &V) -> Result<()> where K: ser::Serialize, V: ser::Serialize,337     fn serialize_entry<K: ?Sized, V: ?Sized>(&mut self, key: &K, value: &V) -> Result<()>
338     where
339         K: ser::Serialize,
340         V: ser::Serialize,
341     {
342         self.hash.insert(to_yaml(key)?, to_yaml(value)?);
343         Ok(())
344     }
345 
end(self) -> Result<Yaml>346     fn end(self) -> Result<Yaml> {
347         Ok(Yaml::Hash(self.hash))
348     }
349 }
350 
351 impl ser::SerializeStruct for SerializeStruct {
352     type Ok = yaml::Yaml;
353     type Error = Error;
354 
serialize_field<V: ?Sized>(&mut self, key: &'static str, value: &V) -> Result<()> where V: ser::Serialize,355     fn serialize_field<V: ?Sized>(&mut self, key: &'static str, value: &V) -> Result<()>
356     where
357         V: ser::Serialize,
358     {
359         self.hash.insert(to_yaml(key)?, to_yaml(value)?);
360         Ok(())
361     }
362 
end(self) -> Result<Yaml>363     fn end(self) -> Result<Yaml> {
364         Ok(Yaml::Hash(self.hash))
365     }
366 }
367 
368 impl ser::SerializeStructVariant for SerializeStructVariant {
369     type Ok = yaml::Yaml;
370     type Error = Error;
371 
serialize_field<V: ?Sized>(&mut self, field: &'static str, v: &V) -> Result<()> where V: ser::Serialize,372     fn serialize_field<V: ?Sized>(&mut self, field: &'static str, v: &V) -> Result<()>
373     where
374         V: ser::Serialize,
375     {
376         self.hash.insert(to_yaml(field)?, to_yaml(v)?);
377         Ok(())
378     }
379 
end(self) -> Result<Yaml>380     fn end(self) -> Result<Yaml> {
381         Ok(singleton_hash(to_yaml(self.name)?, Yaml::Hash(self.hash)))
382     }
383 }
384 
385 /// Serialize the given data structure as YAML into the IO stream.
386 ///
387 /// Serialization can fail if `T`'s implementation of `Serialize` decides to
388 /// return an error.
to_writer<W, T: ?Sized>(writer: W, value: &T) -> Result<()> where W: io::Write, T: ser::Serialize,389 pub fn to_writer<W, T: ?Sized>(writer: W, value: &T) -> Result<()>
390 where
391     W: io::Write,
392     T: ser::Serialize,
393 {
394     let doc = to_yaml(value)?;
395     let mut writer_adapter = FmtToIoWriter { writer };
396     YamlEmitter::new(&mut writer_adapter)
397         .dump(&doc)
398         .map_err(error::emitter)?;
399     Ok(())
400 }
401 
402 /// Serialize the given data structure as a YAML byte vector.
403 ///
404 /// Serialization can fail if `T`'s implementation of `Serialize` decides to
405 /// return an error.
to_vec<T: ?Sized>(value: &T) -> Result<Vec<u8>> where T: ser::Serialize,406 pub fn to_vec<T: ?Sized>(value: &T) -> Result<Vec<u8>>
407 where
408     T: ser::Serialize,
409 {
410     let mut vec = Vec::with_capacity(128);
411     to_writer(&mut vec, value)?;
412     Ok(vec)
413 }
414 
415 /// Serialize the given data structure as a String of YAML.
416 ///
417 /// Serialization can fail if `T`'s implementation of `Serialize` decides to
418 /// return an error.
to_string<T: ?Sized>(value: &T) -> Result<String> where T: ser::Serialize,419 pub fn to_string<T: ?Sized>(value: &T) -> Result<String>
420 where
421     T: ser::Serialize,
422 {
423     Ok(String::from_utf8(to_vec(value)?).map_err(error::string_utf8)?)
424 }
425 
426 /// The yaml-rust library uses `fmt::Write` intead of `io::Write` so this is a
427 /// simple adapter.
428 struct FmtToIoWriter<W> {
429     writer: W,
430 }
431 
432 impl<W> fmt::Write for FmtToIoWriter<W>
433 where
434     W: io::Write,
435 {
write_str(&mut self, s: &str) -> fmt::Result436     fn write_str(&mut self, s: &str) -> fmt::Result {
437         if self.writer.write(s.as_bytes()).is_err() {
438             return Err(fmt::Error);
439         }
440         Ok(())
441     }
442 }
443 
to_yaml<T>(elem: T) -> Result<Yaml> where T: ser::Serialize,444 fn to_yaml<T>(elem: T) -> Result<Yaml>
445 where
446     T: ser::Serialize,
447 {
448     elem.serialize(Serializer)
449 }
450 
singleton_hash(k: Yaml, v: Yaml) -> Yaml451 fn singleton_hash(k: Yaml, v: Yaml) -> Yaml {
452     let mut hash = yaml::Hash::new();
453     hash.insert(k, v);
454     Yaml::Hash(hash)
455 }
456