1use std::io::Write;
2
3use serde::{Serialize, ser};
4
5use crate::{Error, Result};
6
7pub fn to_string<T>(value: &T) -> Result<String>
9where
10 T: ?Sized + Serialize,
11{
12 let mut output = Vec::new();
13 to_writer(&mut output, value)?;
14 String::from_utf8(output).map_err(|error| Error::message(error.to_string()))
15}
16
17pub fn to_writer<W, T>(writer: W, value: &T) -> Result<()>
19where
20 W: Write,
21 T: ?Sized + Serialize,
22{
23 let mut serializer = Serializer::new(writer);
24 value.serialize(&mut serializer)
25}
26
27pub struct Serializer<W> {
29 writer: W,
30 documents: usize,
31}
32
33impl<W> Serializer<W>
34where
35 W: Write,
36{
37 pub const fn new(writer: W) -> Self {
39 Self {
40 writer,
41 documents: 0,
42 }
43 }
44
45 pub fn flush(&mut self) -> Result<()> {
47 self.writer.flush().map_err(Error::io)
48 }
49
50 pub fn into_inner(mut self) -> Result<W> {
52 self.flush()?;
53 Ok(self.writer)
54 }
55
56 fn write_document(&mut self, value: SerValue) -> Result<()> {
57 if self.documents > 0 {
58 self.writer.write_all(b"---\n").map_err(Error::io)?;
59 }
60 let mut output = String::new();
61 render_value(&value, 0, &mut output);
62 if !output.ends_with('\n') {
63 output.push('\n');
64 }
65 self.writer
66 .write_all(output.as_bytes())
67 .map_err(Error::io)?;
68 self.documents += 1;
69 Ok(())
70 }
71
72 fn collect<T>(&mut self, value: &T) -> Result<()>
73 where
74 T: ?Sized + Serialize,
75 {
76 self.write_document(value.serialize(ValueSerializer)?)
77 }
78}
79
80#[derive(Debug)]
81pub enum SerValue {
82 Null,
83 Bool(bool),
84 Signed(i128),
85 Unsigned(u128),
86 Float(f64),
87 String(String),
88 Sequence(Vec<SerValue>),
89 Mapping(Vec<(SerValue, SerValue)>),
90 Tagged(String, Box<SerValue>),
91}
92
93struct ValueSerializer;
94
95impl ser::Serializer for ValueSerializer {
96 type Ok = SerValue;
97 type Error = Error;
98 type SerializeSeq = ValueSequence;
99 type SerializeTuple = ValueSequence;
100 type SerializeTupleStruct = ValueSequence;
101 type SerializeTupleVariant = ValueSequence;
102 type SerializeMap = ValueMapping;
103 type SerializeStruct = ValueMapping;
104 type SerializeStructVariant = ValueMapping;
105
106 fn serialize_bool(self, value: bool) -> Result<SerValue> {
107 Ok(SerValue::Bool(value))
108 }
109 fn serialize_i8(self, value: i8) -> Result<SerValue> {
110 self.serialize_i128(value.into())
111 }
112 fn serialize_i16(self, value: i16) -> Result<SerValue> {
113 self.serialize_i128(value.into())
114 }
115 fn serialize_i32(self, value: i32) -> Result<SerValue> {
116 self.serialize_i128(value.into())
117 }
118 fn serialize_i64(self, value: i64) -> Result<SerValue> {
119 self.serialize_i128(value.into())
120 }
121 fn serialize_i128(self, value: i128) -> Result<SerValue> {
122 Ok(SerValue::Signed(value))
123 }
124 fn serialize_u8(self, value: u8) -> Result<SerValue> {
125 self.serialize_u128(value.into())
126 }
127 fn serialize_u16(self, value: u16) -> Result<SerValue> {
128 self.serialize_u128(value.into())
129 }
130 fn serialize_u32(self, value: u32) -> Result<SerValue> {
131 self.serialize_u128(value.into())
132 }
133 fn serialize_u64(self, value: u64) -> Result<SerValue> {
134 self.serialize_u128(value.into())
135 }
136 fn serialize_u128(self, value: u128) -> Result<SerValue> {
137 Ok(SerValue::Unsigned(value))
138 }
139 fn serialize_f32(self, value: f32) -> Result<SerValue> {
140 Ok(SerValue::Float(value.into()))
141 }
142 fn serialize_f64(self, value: f64) -> Result<SerValue> {
143 Ok(SerValue::Float(value))
144 }
145 fn serialize_char(self, value: char) -> Result<SerValue> {
146 Ok(SerValue::String(value.to_string()))
147 }
148 fn serialize_str(self, value: &str) -> Result<SerValue> {
149 Ok(SerValue::String(value.to_owned()))
150 }
151 fn serialize_bytes(self, _value: &[u8]) -> Result<SerValue> {
152 Err(Error::message(
153 "serialization and deserialization of bytes in YAML is not implemented",
154 ))
155 }
156 fn serialize_none(self) -> Result<SerValue> {
157 Ok(SerValue::Null)
158 }
159 fn serialize_some<T>(self, value: &T) -> Result<SerValue>
160 where
161 T: ?Sized + Serialize,
162 {
163 value.serialize(self)
164 }
165 fn serialize_unit(self) -> Result<SerValue> {
166 Ok(SerValue::Null)
167 }
168 fn serialize_unit_struct(self, _name: &'static str) -> Result<SerValue> {
169 Ok(SerValue::Null)
170 }
171 fn serialize_unit_variant(
172 self,
173 _name: &'static str,
174 _index: u32,
175 variant: &'static str,
176 ) -> Result<SerValue> {
177 Ok(SerValue::String(variant.to_owned()))
178 }
179 fn serialize_newtype_struct<T>(self, _name: &'static str, value: &T) -> Result<SerValue>
180 where
181 T: ?Sized + Serialize,
182 {
183 value.serialize(self)
184 }
185 fn serialize_newtype_variant<T>(
186 self,
187 _name: &'static str,
188 _index: u32,
189 variant: &'static str,
190 value: &T,
191 ) -> Result<SerValue>
192 where
193 T: ?Sized + Serialize,
194 {
195 let value = value.serialize(self)?;
196 if matches!(value, SerValue::Tagged(..)) {
197 return Err(Error::message(
198 "serializing nested enums in YAML is not supported",
199 ));
200 }
201 Ok(SerValue::Tagged(variant.to_owned(), Box::new(value)))
202 }
203 fn serialize_seq(self, len: Option<usize>) -> Result<ValueSequence> {
204 Ok(ValueSequence::new(len, None))
205 }
206 fn serialize_tuple(self, len: usize) -> Result<ValueSequence> {
207 Ok(ValueSequence::new(Some(len), None))
208 }
209 fn serialize_tuple_struct(self, _name: &'static str, len: usize) -> Result<ValueSequence> {
210 Ok(ValueSequence::new(Some(len), None))
211 }
212 fn serialize_tuple_variant(
213 self,
214 _name: &'static str,
215 _index: u32,
216 variant: &'static str,
217 len: usize,
218 ) -> Result<ValueSequence> {
219 Ok(ValueSequence::new(Some(len), Some(variant.to_owned())))
220 }
221 fn serialize_map(self, len: Option<usize>) -> Result<ValueMapping> {
222 Ok(ValueMapping::new(len, None))
223 }
224 fn serialize_struct(self, _name: &'static str, len: usize) -> Result<ValueMapping> {
225 Ok(ValueMapping::new(Some(len), None))
226 }
227 fn serialize_struct_variant(
228 self,
229 _name: &'static str,
230 _index: u32,
231 variant: &'static str,
232 len: usize,
233 ) -> Result<ValueMapping> {
234 Ok(ValueMapping::new(Some(len), Some(variant.to_owned())))
235 }
236 fn collect_str<T>(self, value: &T) -> Result<SerValue>
237 where
238 T: ?Sized + std::fmt::Display,
239 {
240 Ok(SerValue::String(value.to_string()))
241 }
242 fn is_human_readable(&self) -> bool {
243 true
244 }
245}
246
247pub struct ValueSequence {
248 values: Vec<SerValue>,
249 tag: Option<String>,
250}
251
252impl ValueSequence {
253 fn new(len: Option<usize>, tag: Option<String>) -> Self {
254 Self {
255 values: Vec::with_capacity(len.unwrap_or(0)),
256 tag,
257 }
258 }
259
260 fn push<T>(&mut self, value: &T) -> Result<()>
261 where
262 T: ?Sized + Serialize,
263 {
264 self.values.push(value.serialize(ValueSerializer)?);
265 Ok(())
266 }
267
268 fn finish(self) -> SerValue {
269 let value = SerValue::Sequence(self.values);
270 match self.tag {
271 Some(tag) => SerValue::Tagged(tag, Box::new(value)),
272 None => value,
273 }
274 }
275}
276
277impl ser::SerializeSeq for ValueSequence {
278 type Ok = SerValue;
279 type Error = Error;
280 fn serialize_element<T>(&mut self, value: &T) -> Result<()>
281 where
282 T: ?Sized + Serialize,
283 {
284 self.push(value)
285 }
286 fn end(self) -> Result<SerValue> {
287 Ok(self.finish())
288 }
289}
290impl ser::SerializeTuple for ValueSequence {
291 type Ok = SerValue;
292 type Error = Error;
293 fn serialize_element<T>(&mut self, value: &T) -> Result<()>
294 where
295 T: ?Sized + Serialize,
296 {
297 self.push(value)
298 }
299 fn end(self) -> Result<SerValue> {
300 Ok(self.finish())
301 }
302}
303impl ser::SerializeTupleStruct for ValueSequence {
304 type Ok = SerValue;
305 type Error = Error;
306 fn serialize_field<T>(&mut self, value: &T) -> Result<()>
307 where
308 T: ?Sized + Serialize,
309 {
310 self.push(value)
311 }
312 fn end(self) -> Result<SerValue> {
313 Ok(self.finish())
314 }
315}
316impl ser::SerializeTupleVariant for ValueSequence {
317 type Ok = SerValue;
318 type Error = Error;
319 fn serialize_field<T>(&mut self, value: &T) -> Result<()>
320 where
321 T: ?Sized + Serialize,
322 {
323 self.push(value)
324 }
325 fn end(self) -> Result<SerValue> {
326 Ok(self.finish())
327 }
328}
329
330pub struct ValueMapping {
331 entries: Vec<(SerValue, SerValue)>,
332 pending: Option<SerValue>,
333 tag: Option<String>,
334}
335
336impl ValueMapping {
337 fn new(len: Option<usize>, tag: Option<String>) -> Self {
338 Self {
339 entries: Vec::with_capacity(len.unwrap_or(0)),
340 pending: None,
341 tag,
342 }
343 }
344
345 fn finish(self) -> Result<SerValue> {
346 if self.pending.is_some() {
347 return Err(Error::message("map ended before serializing a value"));
348 }
349 let value = SerValue::Mapping(self.entries);
350 Ok(match self.tag {
351 Some(tag) => SerValue::Tagged(tag, Box::new(value)),
352 None => value,
353 })
354 }
355}
356
357impl ser::SerializeMap for ValueMapping {
358 type Ok = SerValue;
359 type Error = Error;
360 fn serialize_key<T>(&mut self, key: &T) -> Result<()>
361 where
362 T: ?Sized + Serialize,
363 {
364 if self.pending.is_some() {
365 return Err(Error::message("map key serialized before its value"));
366 }
367 self.pending = Some(key.serialize(ValueSerializer)?);
368 Ok(())
369 }
370 fn serialize_value<T>(&mut self, value: &T) -> Result<()>
371 where
372 T: ?Sized + Serialize,
373 {
374 let key = self
375 .pending
376 .take()
377 .ok_or_else(|| Error::message("map value serialized before its key"))?;
378 self.entries.push((key, value.serialize(ValueSerializer)?));
379 Ok(())
380 }
381 fn serialize_entry<K, V>(&mut self, key: &K, value: &V) -> Result<()>
382 where
383 K: ?Sized + Serialize,
384 V: ?Sized + Serialize,
385 {
386 self.entries.push((
387 key.serialize(ValueSerializer)?,
388 value.serialize(ValueSerializer)?,
389 ));
390 Ok(())
391 }
392 fn end(self) -> Result<SerValue> {
393 self.finish()
394 }
395}
396
397impl ser::SerializeStruct for ValueMapping {
398 type Ok = SerValue;
399 type Error = Error;
400 fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<()>
401 where
402 T: ?Sized + Serialize,
403 {
404 self.entries.push((
405 SerValue::String(key.to_owned()),
406 value.serialize(ValueSerializer)?,
407 ));
408 Ok(())
409 }
410 fn end(self) -> Result<SerValue> {
411 self.finish()
412 }
413}
414
415impl ser::SerializeStructVariant for ValueMapping {
416 type Ok = SerValue;
417 type Error = Error;
418 fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<()>
419 where
420 T: ?Sized + Serialize,
421 {
422 self.entries.push((
423 SerValue::String(key.to_owned()),
424 value.serialize(ValueSerializer)?,
425 ));
426 Ok(())
427 }
428 fn end(self) -> Result<SerValue> {
429 self.finish()
430 }
431}
432
433pub enum DocumentSequence<'a, W> {
434 Sequence {
435 serializer: &'a mut Serializer<W>,
436 values: ValueSequence,
437 },
438 Mapping {
439 serializer: &'a mut Serializer<W>,
440 values: ValueMapping,
441 },
442}
443
444impl<'a, W: Write> DocumentSequence<'a, W> {
445 fn sequence(
446 serializer: &'a mut Serializer<W>,
447 len: Option<usize>,
448 tag: Option<String>,
449 ) -> Self {
450 Self::Sequence {
451 serializer,
452 values: ValueSequence::new(len, tag),
453 }
454 }
455 fn mapping(serializer: &'a mut Serializer<W>, len: Option<usize>, tag: Option<String>) -> Self {
456 Self::Mapping {
457 serializer,
458 values: ValueMapping::new(len, tag),
459 }
460 }
461}
462
463impl<W: Write> ser::SerializeSeq for DocumentSequence<'_, W> {
464 type Ok = ();
465 type Error = Error;
466 fn serialize_element<T>(&mut self, value: &T) -> Result<()>
467 where
468 T: ?Sized + Serialize,
469 {
470 match self {
471 Self::Sequence { values, .. } => values.push(value),
472 _ => unreachable!(),
473 }
474 }
475 fn end(self) -> Result<()> {
476 match self {
477 Self::Sequence { serializer, values } => serializer.write_document(values.finish()),
478 _ => unreachable!(),
479 }
480 }
481}
482impl<W: Write> ser::SerializeTuple for DocumentSequence<'_, W> {
483 type Ok = ();
484 type Error = Error;
485 fn serialize_element<T>(&mut self, value: &T) -> Result<()>
486 where
487 T: ?Sized + Serialize,
488 {
489 ser::SerializeSeq::serialize_element(self, value)
490 }
491 fn end(self) -> Result<()> {
492 ser::SerializeSeq::end(self)
493 }
494}
495impl<W: Write> ser::SerializeTupleStruct for DocumentSequence<'_, W> {
496 type Ok = ();
497 type Error = Error;
498 fn serialize_field<T>(&mut self, value: &T) -> Result<()>
499 where
500 T: ?Sized + Serialize,
501 {
502 ser::SerializeSeq::serialize_element(self, value)
503 }
504 fn end(self) -> Result<()> {
505 ser::SerializeSeq::end(self)
506 }
507}
508impl<W: Write> ser::SerializeTupleVariant for DocumentSequence<'_, W> {
509 type Ok = ();
510 type Error = Error;
511 fn serialize_field<T>(&mut self, value: &T) -> Result<()>
512 where
513 T: ?Sized + Serialize,
514 {
515 ser::SerializeSeq::serialize_element(self, value)
516 }
517 fn end(self) -> Result<()> {
518 ser::SerializeSeq::end(self)
519 }
520}
521impl<W: Write> ser::SerializeMap for DocumentSequence<'_, W> {
522 type Ok = ();
523 type Error = Error;
524 fn serialize_key<T>(&mut self, key: &T) -> Result<()>
525 where
526 T: ?Sized + Serialize,
527 {
528 match self {
529 Self::Mapping { values, .. } => ser::SerializeMap::serialize_key(values, key),
530 _ => unreachable!(),
531 }
532 }
533 fn serialize_value<T>(&mut self, value: &T) -> Result<()>
534 where
535 T: ?Sized + Serialize,
536 {
537 match self {
538 Self::Mapping { values, .. } => ser::SerializeMap::serialize_value(values, value),
539 _ => unreachable!(),
540 }
541 }
542 fn serialize_entry<K, V>(&mut self, key: &K, value: &V) -> Result<()>
543 where
544 K: ?Sized + Serialize,
545 V: ?Sized + Serialize,
546 {
547 match self {
548 Self::Mapping { values, .. } => ser::SerializeMap::serialize_entry(values, key, value),
549 _ => unreachable!(),
550 }
551 }
552 fn end(self) -> Result<()> {
553 match self {
554 Self::Mapping { serializer, values } => serializer.write_document(values.finish()?),
555 _ => unreachable!(),
556 }
557 }
558}
559impl<W: Write> ser::SerializeStruct for DocumentSequence<'_, W> {
560 type Ok = ();
561 type Error = Error;
562 fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<()>
563 where
564 T: ?Sized + Serialize,
565 {
566 match self {
567 Self::Mapping { values, .. } => {
568 ser::SerializeStruct::serialize_field(values, key, value)
569 }
570 _ => unreachable!(),
571 }
572 }
573 fn end(self) -> Result<()> {
574 ser::SerializeMap::end(self)
575 }
576}
577impl<W: Write> ser::SerializeStructVariant for DocumentSequence<'_, W> {
578 type Ok = ();
579 type Error = Error;
580 fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<()>
581 where
582 T: ?Sized + Serialize,
583 {
584 match self {
585 Self::Mapping { values, .. } => {
586 ser::SerializeStruct::serialize_field(values, key, value)
587 }
588 _ => unreachable!(),
589 }
590 }
591 fn end(self) -> Result<()> {
592 ser::SerializeMap::end(self)
593 }
594}
595
596impl<'a, W> ser::Serializer for &'a mut Serializer<W>
597where
598 W: Write,
599{
600 type Ok = ();
601 type Error = Error;
602 type SerializeSeq = DocumentSequence<'a, W>;
603 type SerializeTuple = DocumentSequence<'a, W>;
604 type SerializeTupleStruct = DocumentSequence<'a, W>;
605 type SerializeTupleVariant = DocumentSequence<'a, W>;
606 type SerializeMap = DocumentSequence<'a, W>;
607 type SerializeStruct = DocumentSequence<'a, W>;
608 type SerializeStructVariant = DocumentSequence<'a, W>;
609
610 fn serialize_bool(self, value: bool) -> Result<()> {
611 self.write_document(SerValue::Bool(value))
612 }
613 fn serialize_i8(self, value: i8) -> Result<()> {
614 self.serialize_i128(value.into())
615 }
616 fn serialize_i16(self, value: i16) -> Result<()> {
617 self.serialize_i128(value.into())
618 }
619 fn serialize_i32(self, value: i32) -> Result<()> {
620 self.serialize_i128(value.into())
621 }
622 fn serialize_i64(self, value: i64) -> Result<()> {
623 self.serialize_i128(value.into())
624 }
625 fn serialize_i128(self, value: i128) -> Result<()> {
626 self.write_document(SerValue::Signed(value))
627 }
628 fn serialize_u8(self, value: u8) -> Result<()> {
629 self.serialize_u128(value.into())
630 }
631 fn serialize_u16(self, value: u16) -> Result<()> {
632 self.serialize_u128(value.into())
633 }
634 fn serialize_u32(self, value: u32) -> Result<()> {
635 self.serialize_u128(value.into())
636 }
637 fn serialize_u64(self, value: u64) -> Result<()> {
638 self.serialize_u128(value.into())
639 }
640 fn serialize_u128(self, value: u128) -> Result<()> {
641 self.write_document(SerValue::Unsigned(value))
642 }
643 fn serialize_f32(self, value: f32) -> Result<()> {
644 self.write_document(SerValue::Float(value.into()))
645 }
646 fn serialize_f64(self, value: f64) -> Result<()> {
647 self.write_document(SerValue::Float(value))
648 }
649 fn serialize_char(self, value: char) -> Result<()> {
650 self.write_document(SerValue::String(value.to_string()))
651 }
652 fn serialize_str(self, value: &str) -> Result<()> {
653 self.write_document(SerValue::String(value.to_owned()))
654 }
655 fn serialize_bytes(self, _value: &[u8]) -> Result<()> {
656 Err(Error::message(
657 "serialization and deserialization of bytes in YAML is not implemented",
658 ))
659 }
660 fn serialize_none(self) -> Result<()> {
661 self.write_document(SerValue::Null)
662 }
663 fn serialize_some<T>(self, value: &T) -> Result<()>
664 where
665 T: ?Sized + Serialize,
666 {
667 self.collect(value)
668 }
669 fn serialize_unit(self) -> Result<()> {
670 self.write_document(SerValue::Null)
671 }
672 fn serialize_unit_struct(self, _name: &'static str) -> Result<()> {
673 self.serialize_unit()
674 }
675 fn serialize_unit_variant(
676 self,
677 _name: &'static str,
678 _index: u32,
679 variant: &'static str,
680 ) -> Result<()> {
681 self.write_document(SerValue::String(variant.to_owned()))
682 }
683 fn serialize_newtype_struct<T>(self, _name: &'static str, value: &T) -> Result<()>
684 where
685 T: ?Sized + Serialize,
686 {
687 self.collect(value)
688 }
689 fn serialize_newtype_variant<T>(
690 self,
691 _name: &'static str,
692 _index: u32,
693 variant: &'static str,
694 value: &T,
695 ) -> Result<()>
696 where
697 T: ?Sized + Serialize,
698 {
699 let value = value.serialize(ValueSerializer)?;
700 if matches!(value, SerValue::Tagged(..)) {
701 return Err(Error::message(
702 "serializing nested enums in YAML is not supported",
703 ));
704 }
705 self.write_document(SerValue::Tagged(variant.to_owned(), Box::new(value)))
706 }
707 fn serialize_seq(self, len: Option<usize>) -> Result<Self::SerializeSeq> {
708 Ok(DocumentSequence::sequence(self, len, None))
709 }
710 fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple> {
711 Ok(DocumentSequence::sequence(self, Some(len), None))
712 }
713 fn serialize_tuple_struct(
714 self,
715 _name: &'static str,
716 len: usize,
717 ) -> Result<Self::SerializeTupleStruct> {
718 Ok(DocumentSequence::sequence(self, Some(len), None))
719 }
720 fn serialize_tuple_variant(
721 self,
722 _name: &'static str,
723 _index: u32,
724 variant: &'static str,
725 len: usize,
726 ) -> Result<Self::SerializeTupleVariant> {
727 Ok(DocumentSequence::sequence(
728 self,
729 Some(len),
730 Some(variant.to_owned()),
731 ))
732 }
733 fn serialize_map(self, len: Option<usize>) -> Result<Self::SerializeMap> {
734 Ok(DocumentSequence::mapping(self, len, None))
735 }
736 fn serialize_struct(self, _name: &'static str, len: usize) -> Result<Self::SerializeStruct> {
737 Ok(DocumentSequence::mapping(self, Some(len), None))
738 }
739 fn serialize_struct_variant(
740 self,
741 _name: &'static str,
742 _index: u32,
743 variant: &'static str,
744 len: usize,
745 ) -> Result<Self::SerializeStructVariant> {
746 Ok(DocumentSequence::mapping(
747 self,
748 Some(len),
749 Some(variant.to_owned()),
750 ))
751 }
752 fn collect_str<T>(self, value: &T) -> Result<()>
753 where
754 T: ?Sized + std::fmt::Display,
755 {
756 self.serialize_str(&value.to_string())
757 }
758 fn is_human_readable(&self) -> bool {
759 true
760 }
761}
762
763fn render_value(value: &SerValue, indent: usize, output: &mut String) {
764 match value {
765 SerValue::Null
766 | SerValue::Bool(_)
767 | SerValue::Signed(_)
768 | SerValue::Unsigned(_)
769 | SerValue::Float(_)
770 | SerValue::String(_) => {
771 push_indent(output, indent);
772 render_scalar(value, output);
773 }
774 SerValue::Sequence(values) => render_sequence(values, indent, output),
775 SerValue::Mapping(entries) => render_mapping(entries, indent, output),
776 SerValue::Tagged(tag, inner) => {
777 push_indent(output, indent);
778 output.push('!');
779 output.push_str(tag);
780 if is_inline(inner) {
781 output.push(' ');
782 render_inline(inner, output);
783 } else {
784 output.push('\n');
785 render_value(inner, indent, output);
786 }
787 }
788 }
789}
790
791fn render_sequence(values: &[SerValue], indent: usize, output: &mut String) {
792 if values.is_empty() {
793 push_indent(output, indent);
794 output.push_str("[]");
795 return;
796 }
797 for (index, value) in values.iter().enumerate() {
798 if index > 0 {
799 output.push('\n');
800 }
801 push_indent(output, indent);
802 output.push('-');
803 render_nested(value, indent + 2, output);
804 }
805}
806
807fn render_mapping(entries: &[(SerValue, SerValue)], indent: usize, output: &mut String) {
808 if entries.is_empty() {
809 push_indent(output, indent);
810 output.push_str("{}");
811 return;
812 }
813 for (index, (key, value)) in entries.iter().enumerate() {
814 if index > 0 {
815 output.push('\n');
816 }
817 if is_inline(key) {
818 push_indent(output, indent);
819 render_inline(key, output);
820 output.push(':');
821 } else {
822 push_indent(output, indent);
823 output.push('?');
824 render_nested(key, indent + 2, output);
825 output.push('\n');
826 push_indent(output, indent);
827 output.push(':');
828 }
829 render_nested(value, indent + 2, output);
830 }
831}
832
833fn render_nested(value: &SerValue, indent: usize, output: &mut String) {
834 match value {
835 SerValue::Tagged(tag, inner) if !is_inline(inner) => {
836 output.push(' ');
837 output.push('!');
838 output.push_str(tag);
839 output.push('\n');
840 render_value(inner, indent, output);
841 }
842 _ if is_inline(value) => {
843 output.push(' ');
844 render_inline(value, output);
845 }
846 _ => {
847 output.push('\n');
848 render_value(value, indent, output);
849 }
850 }
851}
852
853fn is_inline(value: &SerValue) -> bool {
854 matches!(
855 value,
856 SerValue::Null
857 | SerValue::Bool(_)
858 | SerValue::Signed(_)
859 | SerValue::Unsigned(_)
860 | SerValue::Float(_)
861 | SerValue::String(_)
862 ) || matches!(value, SerValue::Sequence(values) if values.is_empty())
863 || matches!(value, SerValue::Mapping(entries) if entries.is_empty())
864 || matches!(value, SerValue::Tagged(_, inner) if is_inline(inner))
865}
866
867fn render_inline(value: &SerValue, output: &mut String) {
868 match value {
869 SerValue::Sequence(values) if values.is_empty() => output.push_str("[]"),
870 SerValue::Mapping(entries) if entries.is_empty() => output.push_str("{}"),
871 SerValue::Tagged(tag, inner) => {
872 output.push('!');
873 output.push_str(tag);
874 output.push(' ');
875 render_inline(inner, output);
876 }
877 _ => render_scalar(value, output),
878 }
879}
880
881fn render_scalar(value: &SerValue, output: &mut String) {
882 match value {
883 SerValue::Null => output.push_str("null"),
884 SerValue::Bool(value) => output.push_str(if *value { "true" } else { "false" }),
885 SerValue::Signed(value) => output.push_str(&value.to_string()),
886 SerValue::Unsigned(value) => output.push_str(&value.to_string()),
887 SerValue::Float(value) => render_float(*value, output),
888 SerValue::String(value) => render_string(value, output),
889 _ => unreachable!("collections are not scalars"),
890 }
891}
892
893fn render_float(value: f64, output: &mut String) {
894 if value.is_nan() {
895 output.push_str(".nan");
896 } else if value == f64::INFINITY {
897 output.push_str(".inf");
898 } else if value == f64::NEG_INFINITY {
899 output.push_str("-.inf");
900 } else {
901 let text = value.to_string();
902 output.push_str(&text);
903 if !text.contains(['.', 'e', 'E']) {
904 output.push_str(".0");
905 }
906 }
907}
908
909fn render_string(value: &str, output: &mut String) {
910 if is_safe_plain(value) {
911 output.push_str(value);
912 return;
913 }
914 output.push('"');
915 for character in value.chars() {
916 match character {
917 '"' => output.push_str("\\\""),
918 '\\' => output.push_str("\\\\"),
919 '\n' => output.push_str("\\n"),
920 '\r' => output.push_str("\\r"),
921 '\t' => output.push_str("\\t"),
922 '\u{08}' => output.push_str("\\b"),
923 '\u{0C}' => output.push_str("\\f"),
924 character if character.is_control() => {
925 use std::fmt::Write as _;
926 let _ = write!(output, "\\u{:04X}", character as u32);
927 }
928 character => output.push(character),
929 }
930 }
931 output.push('"');
932}
933
934fn is_safe_plain(value: &str) -> bool {
935 if value.is_empty() || value.trim() != value || value.contains(['\n', '\r', '\t']) {
936 return false;
937 }
938 if value.starts_with([
939 '-', '?', ':', ',', '[', ']', '{', '}', '#', '&', '*', '!', '|', '>', '\'', '"', '%', '@',
940 '`',
941 ]) {
942 return false;
943 }
944 if value.contains(": ") || value.contains(" #") || value == "---" || value == "..." {
945 return false;
946 }
947 if matches!(
948 value,
949 "~" | "null"
950 | "Null"
951 | "NULL"
952 | "true"
953 | "True"
954 | "TRUE"
955 | "false"
956 | "False"
957 | "FALSE"
958 | ".inf"
959 | ".Inf"
960 | ".INF"
961 | "-.inf"
962 | "-.Inf"
963 | "-.INF"
964 | ".nan"
965 | ".NaN"
966 | ".NAN"
967 ) {
968 return false;
969 }
970 !looks_numeric(value)
971}
972
973fn looks_numeric(value: &str) -> bool {
974 let value = value.replace('_', "");
975 let unsigned = value.strip_prefix(['+', '-']).unwrap_or(&value);
976 if unsigned
977 .strip_prefix("0x")
978 .is_some_and(|v| !v.is_empty() && v.chars().all(|c| c.is_ascii_hexdigit()))
979 {
980 return true;
981 }
982 if unsigned
983 .strip_prefix("0o")
984 .is_some_and(|v| !v.is_empty() && v.chars().all(|c| matches!(c, '0'..='7')))
985 {
986 return true;
987 }
988 if unsigned
989 .strip_prefix("0b")
990 .is_some_and(|v| !v.is_empty() && v.chars().all(|c| matches!(c, '0' | '1')))
991 {
992 return true;
993 }
994 value.parse::<i128>().is_ok() || value.parse::<u128>().is_ok() || value.parse::<f64>().is_ok()
995}
996
997fn push_indent(output: &mut String, indent: usize) {
998 output.extend(std::iter::repeat_n(' ', indent));
999}