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