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