Skip to main content

serde_yaml/
ser.rs

1//! YAML Serialization
2//!
3//! This module provides YAML serialization with the type `Serializer`.
4
5use std::{
6    fmt::{self, Display},
7    io,
8    marker::PhantomData,
9    mem, num, str,
10};
11
12use serde::{
13    de::Visitor,
14    ser::{self, Serializer as _},
15};
16
17use crate::{
18    error::{self, Error, ErrorImpl},
19    libyaml,
20    libyaml::emitter::{Emitter, Event, Mapping, Scalar, ScalarStyle, Sequence},
21    value::tagged::{self, MaybeTag},
22};
23
24type Result<T, E = Error> = std::result::Result<T, E>;
25
26/// A structure for serializing Rust values into YAML.
27///
28/// # Example
29///
30/// ```
31/// use anyhow::Result;
32/// use serde::Serialize;
33/// use std::collections::BTreeMap;
34///
35/// fn main() -> Result<()> {
36///     let mut buffer = Vec::new();
37///     let mut ser = serde_yaml::Serializer::new(&mut buffer);
38///
39///     let mut object = BTreeMap::new();
40///     object.insert("k", 107);
41///     object.serialize(&mut ser)?;
42///
43///     object.insert("J", 74);
44///     object.serialize(&mut ser)?;
45///
46///     assert_eq!(buffer, b"k: 107\n---\nJ: 74\nk: 107\n");
47///     Ok(())
48/// }
49/// ```
50pub struct Serializer<W> {
51    depth: usize,
52    state: State,
53    emitter: Emitter<'static>,
54    writer: PhantomData<W>,
55}
56
57enum State {
58    NothingInParticular,
59    CheckForTag,
60    CheckForDuplicateTag,
61    FoundTag(String),
62    AlreadyTagged,
63}
64
65impl<W> Serializer<W>
66where
67    W: io::Write,
68{
69    /// Creates a new YAML serializer.
70    pub fn new(writer: W) -> Self {
71        let mut emitter = Emitter::new({
72            let writer = Box::new(writer);
73            unsafe { mem::transmute::<Box<dyn io::Write>, Box<dyn io::Write>>(writer) }
74        });
75        emitter.emit(Event::StreamStart).unwrap();
76        Serializer {
77            depth: 0,
78            state: State::NothingInParticular,
79            emitter,
80            writer: PhantomData,
81        }
82    }
83
84    /// Calls [`.flush()`](io::Write::flush) on the underlying `io::Write`
85    /// object.
86    pub fn flush(&mut self) -> Result<()> {
87        self.emitter.flush()?;
88        Ok(())
89    }
90
91    /// Unwrap the underlying `io::Write` object from the `Serializer`.
92    pub fn into_inner(mut self) -> Result<W> {
93        self.emitter.emit(Event::StreamEnd)?;
94        self.emitter.flush()?;
95        let writer = self.emitter.into_inner();
96        Ok(*unsafe { Box::from_raw(Box::into_raw(writer).cast::<W>()) })
97    }
98
99    fn emit_scalar(&mut self, mut scalar: Scalar) -> Result<()> {
100        self.flush_mapping_start()?;
101        if let Some(tag) = self.take_tag() {
102            scalar.tag = Some(tag);
103        }
104        self.value_start()?;
105        self.emitter.emit(Event::Scalar(scalar))?;
106        self.value_end()
107    }
108
109    fn emit_sequence_start(&mut self) -> Result<()> {
110        self.flush_mapping_start()?;
111        self.value_start()?;
112        let tag = self.take_tag();
113        self.emitter.emit(Event::SequenceStart(Sequence {
114            tag,
115        }))?;
116        Ok(())
117    }
118
119    fn emit_sequence_end(&mut self) -> Result<()> {
120        self.emitter.emit(Event::SequenceEnd)?;
121        self.value_end()
122    }
123
124    fn emit_mapping_start(&mut self) -> Result<()> {
125        self.flush_mapping_start()?;
126        self.value_start()?;
127        let tag = self.take_tag();
128        self.emitter.emit(Event::MappingStart(Mapping {
129            tag,
130        }))?;
131        Ok(())
132    }
133
134    fn emit_mapping_end(&mut self) -> Result<()> {
135        self.emitter.emit(Event::MappingEnd)?;
136        self.value_end()
137    }
138
139    fn value_start(&mut self) -> Result<()> {
140        if self.depth == 0 {
141            self.emitter.emit(Event::DocumentStart)?;
142        }
143        self.depth += 1;
144        Ok(())
145    }
146
147    fn value_end(&mut self) -> Result<()> {
148        self.depth -= 1;
149        if self.depth == 0 {
150            self.emitter.emit(Event::DocumentEnd)?;
151        }
152        Ok(())
153    }
154
155    fn take_tag(&mut self) -> Option<String> {
156        let state = mem::replace(&mut self.state, State::NothingInParticular);
157        if let State::FoundTag(mut tag) = state {
158            if !tag.starts_with('!') {
159                tag.insert(0, '!');
160            }
161            Some(tag)
162        } else {
163            self.state = state;
164            None
165        }
166    }
167
168    fn flush_mapping_start(&mut self) -> Result<()> {
169        if let State::CheckForTag = self.state {
170            self.state = State::NothingInParticular;
171            self.emit_mapping_start()?;
172        } else if let State::CheckForDuplicateTag = self.state {
173            self.state = State::NothingInParticular;
174        }
175        Ok(())
176    }
177}
178
179impl<'a, W> ser::Serializer for &'a mut Serializer<W>
180where
181    W: io::Write,
182{
183    type Ok = ();
184    type Error = Error;
185
186    type SerializeSeq = Self;
187    type SerializeTuple = Self;
188    type SerializeTupleStruct = Self;
189    type SerializeTupleVariant = Self;
190    type SerializeMap = Self;
191    type SerializeStruct = Self;
192    type SerializeStructVariant = Self;
193
194    fn serialize_bool(self, v: bool) -> Result<()> {
195        self.emit_scalar(Scalar {
196            tag: None,
197            value: if v { "true" } else { "false" },
198            style: ScalarStyle::Plain,
199        })
200    }
201
202    fn serialize_i8(self, v: i8) -> Result<()> {
203        self.emit_scalar(Scalar {
204            tag: None,
205            value: itoa::Buffer::new().format(v),
206            style: ScalarStyle::Plain,
207        })
208    }
209
210    fn serialize_i16(self, v: i16) -> Result<()> {
211        self.emit_scalar(Scalar {
212            tag: None,
213            value: itoa::Buffer::new().format(v),
214            style: ScalarStyle::Plain,
215        })
216    }
217
218    fn serialize_i32(self, v: i32) -> Result<()> {
219        self.emit_scalar(Scalar {
220            tag: None,
221            value: itoa::Buffer::new().format(v),
222            style: ScalarStyle::Plain,
223        })
224    }
225
226    fn serialize_i64(self, v: i64) -> Result<()> {
227        self.emit_scalar(Scalar {
228            tag: None,
229            value: itoa::Buffer::new().format(v),
230            style: ScalarStyle::Plain,
231        })
232    }
233
234    fn serialize_i128(self, v: i128) -> Result<()> {
235        self.emit_scalar(Scalar {
236            tag: None,
237            value: itoa::Buffer::new().format(v),
238            style: ScalarStyle::Plain,
239        })
240    }
241
242    fn serialize_u8(self, v: u8) -> Result<()> {
243        self.emit_scalar(Scalar {
244            tag: None,
245            value: itoa::Buffer::new().format(v),
246            style: ScalarStyle::Plain,
247        })
248    }
249
250    fn serialize_u16(self, v: u16) -> Result<()> {
251        self.emit_scalar(Scalar {
252            tag: None,
253            value: itoa::Buffer::new().format(v),
254            style: ScalarStyle::Plain,
255        })
256    }
257
258    fn serialize_u32(self, v: u32) -> Result<()> {
259        self.emit_scalar(Scalar {
260            tag: None,
261            value: itoa::Buffer::new().format(v),
262            style: ScalarStyle::Plain,
263        })
264    }
265
266    fn serialize_u64(self, v: u64) -> Result<()> {
267        self.emit_scalar(Scalar {
268            tag: None,
269            value: itoa::Buffer::new().format(v),
270            style: ScalarStyle::Plain,
271        })
272    }
273
274    fn serialize_u128(self, v: u128) -> Result<()> {
275        self.emit_scalar(Scalar {
276            tag: None,
277            value: itoa::Buffer::new().format(v),
278            style: ScalarStyle::Plain,
279        })
280    }
281
282    fn serialize_f32(self, v: f32) -> Result<()> {
283        let mut buffer = ryu::Buffer::new();
284        self.emit_scalar(Scalar {
285            tag: None,
286            value: match v.classify() {
287                num::FpCategory::Infinite if v.is_sign_positive() => ".inf",
288                num::FpCategory::Infinite => "-.inf",
289                num::FpCategory::Nan => ".nan",
290                _ => buffer.format_finite(v),
291            },
292            style: ScalarStyle::Plain,
293        })
294    }
295
296    fn serialize_f64(self, v: f64) -> Result<()> {
297        let mut buffer = ryu::Buffer::new();
298        self.emit_scalar(Scalar {
299            tag: None,
300            value: match v.classify() {
301                num::FpCategory::Infinite if v.is_sign_positive() => ".inf",
302                num::FpCategory::Infinite => "-.inf",
303                num::FpCategory::Nan => ".nan",
304                _ => buffer.format_finite(v),
305            },
306            style: ScalarStyle::Plain,
307        })
308    }
309
310    fn serialize_char(self, value: char) -> Result<()> {
311        self.emit_scalar(Scalar {
312            tag: None,
313            value: value.encode_utf8(&mut [0u8; 4]),
314            style: ScalarStyle::SingleQuoted,
315        })
316    }
317
318    fn serialize_str(self, value: &str) -> Result<()> {
319        struct InferScalarStyle;
320
321        impl<'de> Visitor<'de> for InferScalarStyle {
322            type Value = ScalarStyle;
323
324            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
325                formatter.write_str("I wonder")
326            }
327
328            fn visit_bool<E>(self, _v: bool) -> Result<Self::Value, E> {
329                Ok(ScalarStyle::SingleQuoted)
330            }
331
332            fn visit_i64<E>(self, _v: i64) -> Result<Self::Value, E> {
333                Ok(ScalarStyle::SingleQuoted)
334            }
335
336            fn visit_i128<E>(self, _v: i128) -> Result<Self::Value, E> {
337                Ok(ScalarStyle::SingleQuoted)
338            }
339
340            fn visit_u64<E>(self, _v: u64) -> Result<Self::Value, E> {
341                Ok(ScalarStyle::SingleQuoted)
342            }
343
344            fn visit_u128<E>(self, _v: u128) -> Result<Self::Value, E> {
345                Ok(ScalarStyle::SingleQuoted)
346            }
347
348            fn visit_f64<E>(self, _v: f64) -> Result<Self::Value, E> {
349                Ok(ScalarStyle::SingleQuoted)
350            }
351
352            fn visit_str<E>(self, v: &str) -> Result<Self::Value, E> {
353                Ok(if crate::de::digits_but_not_number(v) {
354                    ScalarStyle::SingleQuoted
355                } else {
356                    ScalarStyle::Any
357                })
358            }
359
360            fn visit_unit<E>(self) -> Result<Self::Value, E> {
361                Ok(ScalarStyle::SingleQuoted)
362            }
363        }
364
365        let style = if value.contains('\n') {
366            ScalarStyle::Literal
367        } else {
368            let result =
369                crate::de::visit_untagged_scalar(InferScalarStyle, value, None, libyaml::parser::ScalarStyle::Plain);
370            result.unwrap_or(ScalarStyle::Any)
371        };
372
373        self.emit_scalar(Scalar {
374            tag: None,
375            value,
376            style,
377        })
378    }
379
380    fn serialize_bytes(self, _value: &[u8]) -> Result<()> {
381        Err(error::new(ErrorImpl::BytesUnsupported))
382    }
383
384    fn serialize_unit(self) -> Result<()> {
385        self.emit_scalar(Scalar {
386            tag: None,
387            value: "null",
388            style: ScalarStyle::Plain,
389        })
390    }
391
392    fn serialize_unit_struct(self, _name: &'static str) -> Result<()> {
393        self.serialize_unit()
394    }
395
396    fn serialize_unit_variant(self, _name: &'static str, _variant_index: u32, variant: &'static str) -> Result<()> {
397        self.serialize_str(variant)
398    }
399
400    fn serialize_newtype_struct<T>(self, _name: &'static str, value: &T) -> Result<()>
401    where
402        T: ?Sized + ser::Serialize,
403    {
404        value.serialize(self)
405    }
406
407    fn serialize_newtype_variant<T>(
408        self,
409        _name: &'static str,
410        _variant_index: u32,
411        variant: &'static str,
412        value: &T,
413    ) -> Result<()>
414    where
415        T: ?Sized + ser::Serialize,
416    {
417        if let State::FoundTag(_) = self.state {
418            return Err(error::new(ErrorImpl::SerializeNestedEnum));
419        }
420        self.state = State::FoundTag(variant.to_owned());
421        value.serialize(&mut *self)
422    }
423
424    fn serialize_none(self) -> Result<()> {
425        self.serialize_unit()
426    }
427
428    fn serialize_some<V>(self, value: &V) -> Result<()>
429    where
430        V: ?Sized + ser::Serialize,
431    {
432        value.serialize(self)
433    }
434
435    fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq> {
436        self.emit_sequence_start()?;
437        Ok(self)
438    }
439
440    fn serialize_tuple(self, _len: usize) -> Result<Self::SerializeTuple> {
441        self.emit_sequence_start()?;
442        Ok(self)
443    }
444
445    fn serialize_tuple_struct(self, _name: &'static str, _len: usize) -> Result<Self::SerializeTupleStruct> {
446        self.emit_sequence_start()?;
447        Ok(self)
448    }
449
450    fn serialize_tuple_variant(
451        self,
452        _enm: &'static str,
453        _idx: u32,
454        variant: &'static str,
455        _len: usize,
456    ) -> Result<Self::SerializeTupleVariant> {
457        if let State::FoundTag(_) = self.state {
458            return Err(error::new(ErrorImpl::SerializeNestedEnum));
459        }
460        self.state = State::FoundTag(variant.to_owned());
461        self.emit_sequence_start()?;
462        Ok(self)
463    }
464
465    fn serialize_map(self, len: Option<usize>) -> Result<Self::SerializeMap> {
466        if len == Some(1) {
467            self.state = if let State::FoundTag(_) = self.state {
468                self.emit_mapping_start()?;
469                State::CheckForDuplicateTag
470            } else {
471                State::CheckForTag
472            };
473        } else {
474            self.emit_mapping_start()?;
475        }
476        Ok(self)
477    }
478
479    fn serialize_struct(self, _name: &'static str, _len: usize) -> Result<Self::SerializeStruct> {
480        self.emit_mapping_start()?;
481        Ok(self)
482    }
483
484    fn serialize_struct_variant(
485        self,
486        _enm: &'static str,
487        _idx: u32,
488        variant: &'static str,
489        _len: usize,
490    ) -> Result<Self::SerializeStructVariant> {
491        if let State::FoundTag(_) = self.state {
492            return Err(error::new(ErrorImpl::SerializeNestedEnum));
493        }
494        self.state = State::FoundTag(variant.to_owned());
495        self.emit_mapping_start()?;
496        Ok(self)
497    }
498
499    fn collect_str<T>(self, value: &T) -> Result<Self::Ok>
500    where
501        T: ?Sized + Display,
502    {
503        let string = if let State::CheckForTag | State::CheckForDuplicateTag = self.state {
504            match tagged::check_for_tag(value) {
505                MaybeTag::NotTag(string) => string,
506                MaybeTag::Tag(string) => {
507                    return if let State::CheckForDuplicateTag = self.state {
508                        Err(error::new(ErrorImpl::SerializeNestedEnum))
509                    } else {
510                        self.state = State::FoundTag(string);
511                        Ok(())
512                    };
513                }
514            }
515        } else {
516            value.to_string()
517        };
518
519        self.serialize_str(&string)
520    }
521}
522
523impl<'a, W> ser::SerializeSeq for &'a mut Serializer<W>
524where
525    W: io::Write,
526{
527    type Ok = ();
528    type Error = Error;
529
530    fn serialize_element<T>(&mut self, elem: &T) -> Result<()>
531    where
532        T: ?Sized + ser::Serialize,
533    {
534        elem.serialize(&mut **self)
535    }
536
537    fn end(self) -> Result<()> {
538        self.emit_sequence_end()
539    }
540}
541
542impl<'a, W> ser::SerializeTuple for &'a mut Serializer<W>
543where
544    W: io::Write,
545{
546    type Ok = ();
547    type Error = Error;
548
549    fn serialize_element<T>(&mut self, elem: &T) -> Result<()>
550    where
551        T: ?Sized + ser::Serialize,
552    {
553        elem.serialize(&mut **self)
554    }
555
556    fn end(self) -> Result<()> {
557        self.emit_sequence_end()
558    }
559}
560
561impl<'a, W> ser::SerializeTupleStruct for &'a mut Serializer<W>
562where
563    W: io::Write,
564{
565    type Ok = ();
566    type Error = Error;
567
568    fn serialize_field<V>(&mut self, value: &V) -> Result<()>
569    where
570        V: ?Sized + ser::Serialize,
571    {
572        value.serialize(&mut **self)
573    }
574
575    fn end(self) -> Result<()> {
576        self.emit_sequence_end()
577    }
578}
579
580impl<'a, W> ser::SerializeTupleVariant for &'a mut Serializer<W>
581where
582    W: io::Write,
583{
584    type Ok = ();
585    type Error = Error;
586
587    fn serialize_field<V>(&mut self, v: &V) -> Result<()>
588    where
589        V: ?Sized + ser::Serialize,
590    {
591        v.serialize(&mut **self)
592    }
593
594    fn end(self) -> Result<()> {
595        self.emit_sequence_end()
596    }
597}
598
599impl<'a, W> ser::SerializeMap for &'a mut Serializer<W>
600where
601    W: io::Write,
602{
603    type Ok = ();
604    type Error = Error;
605
606    fn serialize_key<T>(&mut self, key: &T) -> Result<()>
607    where
608        T: ?Sized + ser::Serialize,
609    {
610        self.flush_mapping_start()?;
611        key.serialize(&mut **self)
612    }
613
614    fn serialize_value<T>(&mut self, value: &T) -> Result<()>
615    where
616        T: ?Sized + ser::Serialize,
617    {
618        value.serialize(&mut **self)
619    }
620
621    fn serialize_entry<K, V>(&mut self, key: &K, value: &V) -> Result<(), Self::Error>
622    where
623        K: ?Sized + ser::Serialize,
624        V: ?Sized + ser::Serialize,
625    {
626        key.serialize(&mut **self)?;
627        let tagged = matches!(self.state, State::FoundTag(_));
628        value.serialize(&mut **self)?;
629        if tagged {
630            self.state = State::AlreadyTagged;
631        }
632        Ok(())
633    }
634
635    fn end(self) -> Result<()> {
636        if let State::CheckForTag = self.state {
637            self.emit_mapping_start()?;
638        }
639        if !matches!(self.state, State::AlreadyTagged) {
640            self.emit_mapping_end()?;
641        }
642        self.state = State::NothingInParticular;
643        Ok(())
644    }
645}
646
647impl<'a, W> ser::SerializeStruct for &'a mut Serializer<W>
648where
649    W: io::Write,
650{
651    type Ok = ();
652    type Error = Error;
653
654    fn serialize_field<V>(&mut self, key: &'static str, value: &V) -> Result<()>
655    where
656        V: ?Sized + ser::Serialize,
657    {
658        self.serialize_str(key)?;
659        value.serialize(&mut **self)
660    }
661
662    fn end(self) -> Result<()> {
663        self.emit_mapping_end()
664    }
665}
666
667impl<'a, W> ser::SerializeStructVariant for &'a mut Serializer<W>
668where
669    W: io::Write,
670{
671    type Ok = ();
672    type Error = Error;
673
674    fn serialize_field<V>(&mut self, field: &'static str, v: &V) -> Result<()>
675    where
676        V: ?Sized + ser::Serialize,
677    {
678        self.serialize_str(field)?;
679        v.serialize(&mut **self)
680    }
681
682    fn end(self) -> Result<()> {
683        self.emit_mapping_end()
684    }
685}
686
687/// Serialize the given data structure as YAML into the IO stream.
688///
689/// Serialization can fail if `T`'s implementation of `Serialize` decides to
690/// return an error.
691pub fn to_writer<W, T>(writer: W, value: &T) -> Result<()>
692where
693    W: io::Write,
694    T: ?Sized + ser::Serialize,
695{
696    let mut serializer = Serializer::new(writer);
697    value.serialize(&mut serializer)
698}
699
700/// Serialize the given data structure as a String of YAML.
701///
702/// Serialization can fail if `T`'s implementation of `Serialize` decides to
703/// return an error.
704pub fn to_string<T>(value: &T) -> Result<String>
705where
706    T: ?Sized + ser::Serialize,
707{
708    let mut vec = Vec::with_capacity(128);
709    to_writer(&mut vec, value)?;
710    String::from_utf8(vec).map_err(|error| error::new(ErrorImpl::FromUtf8(error)))
711}