1use serde::{Serialize, ser};
4
5use crate::error::{Error, ErrorKind, Result};
6
7pub(crate) fn is_valid_name(name: &str) -> bool {
10 let mut chars = name.chars();
11 match chars.next() {
12 Some(c) if c.is_ascii_alphabetic() || c == '*' => {}
13 _ => return false,
14 }
15 chars.all(|c| c.is_ascii_alphanumeric() || matches!(c, '-' | '_' | '*'))
16}
17
18fn validate_name(name: &str) -> Result<()> {
19 if is_valid_name(name) {
20 Ok(())
21 } else {
22 Err(ErrorKind::InvalidSettingName(name.to_string()).into())
23 }
24}
25
26pub(crate) fn escape_str_into(out: &mut String, s: &str) {
32 out.push('"');
33 for ch in s.chars() {
34 match ch {
35 '"' => out.push_str("\\\""),
36 '\\' => out.push_str("\\\\"),
37 '\n' => out.push_str("\\n"),
38 '\r' => out.push_str("\\r"),
39 '\t' => out.push_str("\\t"),
40 '\x0C' => out.push_str("\\f"),
41 '\x08' => out.push_str("\\b"),
42 '\x0B' => out.push_str("\\v"),
43 '\x07' => out.push_str("\\a"),
44 c if (c as u32) < 0x20 => {
45 out.push_str(&format!("\\x{:02x}", c as u32));
46 }
47 _ => out.push(ch),
48 }
49 }
50 out.push('"');
51}
52
53#[derive(Debug, Clone, PartialEq)]
79#[must_use]
80pub struct WriteOptions {
81 float_precision: Option<u8>,
82 scientific_notation: bool,
83 tab_width: u8,
84 semicolon_separators: bool,
85 colon_assignment_for_groups: bool,
86 colon_assignment_for_non_groups: bool,
87 open_brace_on_separate_line: bool,
88}
89
90impl Default for WriteOptions {
91 fn default() -> Self {
92 WriteOptions {
93 float_precision: None,
94 scientific_notation: false,
95 tab_width: 2,
96 semicolon_separators: true,
97 colon_assignment_for_groups: false,
98 colon_assignment_for_non_groups: false,
99 open_brace_on_separate_line: false,
100 }
101 }
102}
103
104impl WriteOptions {
105 pub fn new() -> Self {
107 WriteOptions::default()
108 }
109
110 pub fn float_precision(mut self, digits: u8) -> Self {
116 self.float_precision = Some(digits.min(17));
117 self
118 }
119
120 pub fn scientific_notation(mut self, enabled: bool) -> Self {
124 self.scientific_notation = enabled;
125 self
126 }
127
128 pub fn tab_width(mut self, width: u8) -> Self {
132 self.tab_width = width.min(15);
133 self
134 }
135
136 pub fn semicolon_separators(mut self, enabled: bool) -> Self {
139 self.semicolon_separators = enabled;
140 self
141 }
142
143 pub fn colon_assignment_for_groups(mut self, enabled: bool) -> Self {
147 self.colon_assignment_for_groups = enabled;
148 self
149 }
150
151 pub fn colon_assignment_for_non_groups(mut self, enabled: bool) -> Self {
154 self.colon_assignment_for_non_groups = enabled;
155 self
156 }
157
158 pub fn open_brace_on_separate_line(mut self, enabled: bool) -> Self {
161 self.open_brace_on_separate_line = enabled;
162 self
163 }
164}
165
166pub(crate) fn write_f64(out: &mut String, v: f64, options: &WriteOptions) -> Result<()> {
170 if !v.is_finite() {
171 return Err(ErrorKind::NonFiniteFloat.into());
172 }
173 let s = match (options.float_precision, options.scientific_notation) {
174 (None, false) => v.to_string(),
175 (None, true) => format!("{:e}", v),
176 (Some(p), false) => format!("{:.*}", p as usize, v),
177 (Some(p), true) => format!("{:.*e}", p as usize, v),
178 };
179 out.push_str(&s);
180 if !s.contains('.') && !s.contains('e') && !s.contains('E') {
181 out.push_str(".0");
182 }
183 Ok(())
184}
185
186pub struct Serializer {
188 output: String,
189 indent_level: usize,
190 options: WriteOptions,
191 at_root: bool,
195}
196
197impl Serializer {
198 pub fn new() -> Self {
200 Serializer::with_options(WriteOptions::default())
201 }
202
203 pub fn with_options(options: WriteOptions) -> Self {
205 Serializer {
206 output: String::new(),
207 indent_level: 0,
208 options,
209 at_root: true,
210 }
211 }
212
213 pub fn into_output(self) -> String {
215 self.output
216 }
217
218 fn indent(&mut self) {
219 self.indent_level += 1;
220 }
221
222 fn dedent(&mut self) {
223 self.indent_level = self.indent_level.saturating_sub(1);
224 }
225
226 fn write_indent(&mut self) {
227 if self.options.tab_width == 0 {
228 for _ in 0..self.indent_level {
229 self.output.push('\t');
230 }
231 } else {
232 for _ in 0..(self.indent_level * self.options.tab_width as usize) {
233 self.output.push(' ');
234 }
235 }
236 }
237}
238
239impl Default for Serializer {
240 fn default() -> Self {
241 Serializer::new()
242 }
243}
244
245pub fn to_string<T>(value: &T) -> Result<String>
253where
254 T: ?Sized + Serialize,
255{
256 to_string_with_options(value, &WriteOptions::default())
257}
258
259pub fn to_string_with_options<T>(value: &T, options: &WriteOptions) -> Result<String>
266where
267 T: ?Sized + Serialize,
268{
269 let mut serializer = Serializer::with_options(options.clone());
270 value.serialize(&mut serializer)?;
271 Ok(serializer.output)
272}
273
274pub fn to_writer<W, T>(mut writer: W, value: &T) -> Result<()>
281where
282 W: std::io::Write,
283 T: ?Sized + Serialize,
284{
285 let s = to_string(value)?;
286 writer
287 .write_all(s.as_bytes())
288 .map_err(|e| ErrorKind::Io(e.to_string()))?;
289 Ok(())
290}
291
292struct NoneProbe;
294
295fn value_is_none<T: ?Sized + Serialize>(value: &T) -> bool {
296 value.serialize(NoneProbe).unwrap_or(false)
297}
298
299struct GroupProbe<'a> {
303 is_group: &'a mut bool,
304}
305
306fn value_is_group<T: ?Sized + Serialize>(value: &T) -> bool {
307 let mut is_group = false;
308 let _ = value.serialize(GroupProbe {
309 is_group: &mut is_group,
310 });
311 is_group
312}
313
314macro_rules! group_probe_false {
315 ($($method:ident: $ty:ty,)*) => {
316 $(fn $method(self, _v: $ty) -> Result<()> { Ok(()) })*
317 };
318}
319
320impl ser::Serializer for GroupProbe<'_> {
321 type Ok = ();
322 type Error = Error;
323
324 type SerializeSeq = ser::Impossible<(), Error>;
325 type SerializeTuple = ser::Impossible<(), Error>;
326 type SerializeTupleStruct = ser::Impossible<(), Error>;
327 type SerializeTupleVariant = ser::Impossible<(), Error>;
328 type SerializeMap = ser::Impossible<(), Error>;
329 type SerializeStruct = ser::Impossible<(), Error>;
330 type SerializeStructVariant = ser::Impossible<(), Error>;
331
332 group_probe_false! {
333 serialize_bool: bool, serialize_i8: i8, serialize_i16: i16,
334 serialize_i32: i32, serialize_i64: i64, serialize_u8: u8,
335 serialize_u16: u16, serialize_u32: u32, serialize_u64: u64,
336 serialize_f32: f32, serialize_f64: f64, serialize_char: char,
337 serialize_str: &str, serialize_bytes: &[u8],
338 }
339
340 fn serialize_none(self) -> Result<()> {
341 Ok(())
342 }
343
344 fn serialize_some<T: ?Sized + Serialize>(self, value: &T) -> Result<()> {
345 value.serialize(GroupProbe {
347 is_group: self.is_group,
348 })
349 }
350
351 fn serialize_unit(self) -> Result<()> {
352 Ok(())
353 }
354
355 fn serialize_unit_struct(self, _name: &'static str) -> Result<()> {
356 Ok(())
357 }
358
359 fn serialize_unit_variant(
360 self,
361 _name: &'static str,
362 _variant_index: u32,
363 _variant: &'static str,
364 ) -> Result<()> {
365 Ok(())
366 }
367
368 fn serialize_newtype_struct<T: ?Sized + Serialize>(
369 self,
370 _name: &'static str,
371 value: &T,
372 ) -> Result<()> {
373 value.serialize(GroupProbe {
374 is_group: self.is_group,
375 })
376 }
377
378 fn serialize_newtype_variant<T: ?Sized + Serialize>(
379 self,
380 _name: &'static str,
381 _variant_index: u32,
382 _variant: &'static str,
383 _value: &T,
384 ) -> Result<()> {
385 *self.is_group = true;
387 Ok(())
388 }
389
390 fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq> {
391 Err(ErrorKind::Message("probe".to_string()).into())
392 }
393
394 fn serialize_tuple(self, _len: usize) -> Result<Self::SerializeTuple> {
395 Err(ErrorKind::Message("probe".to_string()).into())
396 }
397
398 fn serialize_tuple_struct(
399 self,
400 _name: &'static str,
401 _len: usize,
402 ) -> Result<Self::SerializeTupleStruct> {
403 Err(ErrorKind::Message("probe".to_string()).into())
404 }
405
406 fn serialize_tuple_variant(
407 self,
408 _name: &'static str,
409 _variant_index: u32,
410 _variant: &'static str,
411 _len: usize,
412 ) -> Result<Self::SerializeTupleVariant> {
413 *self.is_group = true;
414 Err(ErrorKind::Message("probe".to_string()).into())
415 }
416
417 fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap> {
418 *self.is_group = true;
419 Err(ErrorKind::Message("probe".to_string()).into())
420 }
421
422 fn serialize_struct(self, _name: &'static str, _len: usize) -> Result<Self::SerializeStruct> {
423 *self.is_group = true;
424 Err(ErrorKind::Message("probe".to_string()).into())
425 }
426
427 fn serialize_struct_variant(
428 self,
429 _name: &'static str,
430 _variant_index: u32,
431 _variant: &'static str,
432 _len: usize,
433 ) -> Result<Self::SerializeStructVariant> {
434 *self.is_group = true;
435 Err(ErrorKind::Message("probe".to_string()).into())
436 }
437}
438
439macro_rules! probe_false {
440 ($($method:ident: $ty:ty,)*) => {
441 $(fn $method(self, _v: $ty) -> Result<bool> { Ok(false) })*
442 };
443}
444
445impl ser::Serializer for NoneProbe {
446 type Ok = bool;
447 type Error = Error;
448
449 type SerializeSeq = ser::Impossible<bool, Error>;
450 type SerializeTuple = ser::Impossible<bool, Error>;
451 type SerializeTupleStruct = ser::Impossible<bool, Error>;
452 type SerializeTupleVariant = ser::Impossible<bool, Error>;
453 type SerializeMap = ser::Impossible<bool, Error>;
454 type SerializeStruct = ser::Impossible<bool, Error>;
455 type SerializeStructVariant = ser::Impossible<bool, Error>;
456
457 fn serialize_none(self) -> Result<bool> {
458 Ok(true)
459 }
460
461 fn serialize_some<T: ?Sized + Serialize>(self, _value: &T) -> Result<bool> {
462 Ok(false)
463 }
464
465 probe_false! {
466 serialize_bool: bool, serialize_i8: i8, serialize_i16: i16,
467 serialize_i32: i32, serialize_i64: i64, serialize_u8: u8,
468 serialize_u16: u16, serialize_u32: u32, serialize_u64: u64,
469 serialize_f32: f32, serialize_f64: f64, serialize_char: char,
470 serialize_str: &str, serialize_bytes: &[u8],
471 }
472
473 fn serialize_unit(self) -> Result<bool> {
474 Ok(false)
475 }
476
477 fn serialize_unit_struct(self, _name: &'static str) -> Result<bool> {
478 Ok(false)
479 }
480
481 fn serialize_unit_variant(
482 self,
483 _name: &'static str,
484 _variant_index: u32,
485 _variant: &'static str,
486 ) -> Result<bool> {
487 Ok(false)
488 }
489
490 fn serialize_newtype_struct<T: ?Sized + Serialize>(
491 self,
492 _name: &'static str,
493 _value: &T,
494 ) -> Result<bool> {
495 Ok(false)
496 }
497
498 fn serialize_newtype_variant<T: ?Sized + Serialize>(
499 self,
500 _name: &'static str,
501 _variant_index: u32,
502 _variant: &'static str,
503 _value: &T,
504 ) -> Result<bool> {
505 Ok(false)
506 }
507
508 fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq> {
509 Err(ErrorKind::Message("probe".to_string()).into())
510 }
511
512 fn serialize_tuple(self, _len: usize) -> Result<Self::SerializeTuple> {
513 Err(ErrorKind::Message("probe".to_string()).into())
514 }
515
516 fn serialize_tuple_struct(
517 self,
518 _name: &'static str,
519 _len: usize,
520 ) -> Result<Self::SerializeTupleStruct> {
521 Err(ErrorKind::Message("probe".to_string()).into())
522 }
523
524 fn serialize_tuple_variant(
525 self,
526 _name: &'static str,
527 _variant_index: u32,
528 _variant: &'static str,
529 _len: usize,
530 ) -> Result<Self::SerializeTupleVariant> {
531 Err(ErrorKind::Message("probe".to_string()).into())
532 }
533
534 fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap> {
535 Err(ErrorKind::Message("probe".to_string()).into())
536 }
537
538 fn serialize_struct(self, _name: &'static str, _len: usize) -> Result<Self::SerializeStruct> {
539 Err(ErrorKind::Message("probe".to_string()).into())
540 }
541
542 fn serialize_struct_variant(
543 self,
544 _name: &'static str,
545 _variant_index: u32,
546 _variant: &'static str,
547 _len: usize,
548 ) -> Result<Self::SerializeStructVariant> {
549 Err(ErrorKind::Message("probe".to_string()).into())
550 }
551}
552
553impl<'a> ser::Serializer for &'a mut Serializer {
554 type Ok = ();
555 type Error = Error;
556
557 type SerializeSeq = SeqSerializer<'a>;
558 type SerializeTuple = Self;
559 type SerializeTupleStruct = Self;
560 type SerializeTupleVariant = TupleVariantSerializer<'a>;
561 type SerializeMap = MapSerializer<'a>;
562 type SerializeStruct = MapSerializer<'a>;
563 type SerializeStructVariant = StructVariantSerializer<'a>;
564
565 fn serialize_bool(self, v: bool) -> Result<()> {
566 self.output += if v { "true" } else { "false" };
567 Ok(())
568 }
569
570 fn serialize_i8(self, v: i8) -> Result<()> {
571 self.serialize_i32(i32::from(v))
572 }
573
574 fn serialize_i16(self, v: i16) -> Result<()> {
575 self.serialize_i32(i32::from(v))
576 }
577
578 fn serialize_i32(self, v: i32) -> Result<()> {
579 self.output += &v.to_string();
580 Ok(())
581 }
582
583 fn serialize_i64(self, v: i64) -> Result<()> {
584 self.output += &v.to_string();
585 self.output += "L";
586 Ok(())
587 }
588
589 fn serialize_u8(self, v: u8) -> Result<()> {
590 self.serialize_u32(u32::from(v))
591 }
592
593 fn serialize_u16(self, v: u16) -> Result<()> {
594 self.serialize_u32(u32::from(v))
595 }
596
597 fn serialize_u32(self, v: u32) -> Result<()> {
598 self.output += &v.to_string();
599 if v > i32::MAX as u32 {
603 self.output += "L";
604 }
605 Ok(())
606 }
607
608 fn serialize_u64(self, v: u64) -> Result<()> {
609 if v > i64::MAX as u64 {
612 return Err(ErrorKind::IntegerOutOfRange.into());
613 }
614 self.output += &v.to_string();
615 self.output += "L";
616 Ok(())
617 }
618
619 fn serialize_f32(self, v: f32) -> Result<()> {
620 self.serialize_f64(f64::from(v))
621 }
622
623 fn serialize_f64(self, v: f64) -> Result<()> {
624 write_f64(&mut self.output, v, &self.options)
625 }
626
627 fn serialize_char(self, v: char) -> Result<()> {
628 self.serialize_str(&v.to_string())
629 }
630
631 fn serialize_str(self, v: &str) -> Result<()> {
632 escape_str_into(&mut self.output, v);
633 Ok(())
634 }
635
636 fn serialize_bytes(self, v: &[u8]) -> Result<()> {
637 use ser::SerializeSeq;
638 let mut seq = self.serialize_seq(Some(v.len()))?;
639 for byte in v {
640 seq.serialize_element(byte)?;
641 }
642 seq.end()
643 }
644
645 fn serialize_none(self) -> Result<()> {
646 Err(ErrorKind::TypeNotSupported("Option::None".to_string()).into())
647 }
648
649 fn serialize_some<T>(self, value: &T) -> Result<()>
650 where
651 T: ?Sized + Serialize,
652 {
653 value.serialize(self)
654 }
655
656 fn serialize_unit(self) -> Result<()> {
657 Err(ErrorKind::UnitNotSupported.into())
658 }
659
660 fn serialize_unit_struct(self, _name: &'static str) -> Result<()> {
661 self.serialize_unit()
662 }
663
664 fn serialize_unit_variant(
665 self,
666 _name: &'static str,
667 _variant_index: u32,
668 variant: &'static str,
669 ) -> Result<()> {
670 self.serialize_str(variant)
671 }
672
673 fn serialize_newtype_struct<T>(self, _name: &'static str, value: &T) -> Result<()>
674 where
675 T: ?Sized + Serialize,
676 {
677 value.serialize(self)
678 }
679
680 fn serialize_newtype_variant<T>(
681 self,
682 _name: &'static str,
683 _variant_index: u32,
684 variant: &'static str,
685 value: &T,
686 ) -> Result<()>
687 where
688 T: ?Sized + Serialize,
689 {
690 validate_name(variant)?;
693 self.at_root = false;
694 self.output += "{ ";
695 self.output += variant;
696 self.output += " = ";
697 value.serialize(&mut *self)?;
698 self.output += "; }";
699 Ok(())
700 }
701
702 fn serialize_seq(self, len: Option<usize>) -> Result<Self::SerializeSeq> {
703 self.at_root = false;
704 Ok(SeqSerializer {
705 elements: Vec::with_capacity(len.unwrap_or(0)),
706 ser: self,
707 })
708 }
709
710 fn serialize_tuple(self, _len: usize) -> Result<Self::SerializeTuple> {
711 self.at_root = false;
712 self.output.push('(');
713 Ok(self)
714 }
715
716 fn serialize_tuple_struct(
717 self,
718 _name: &'static str,
719 _len: usize,
720 ) -> Result<Self::SerializeTupleStruct> {
721 self.at_root = false;
722 self.output.push('(');
723 Ok(self)
724 }
725
726 fn serialize_tuple_variant(
727 self,
728 _name: &'static str,
729 _variant_index: u32,
730 variant: &'static str,
731 _len: usize,
732 ) -> Result<Self::SerializeTupleVariant> {
733 validate_name(variant)?;
734 self.at_root = false;
735 self.output += "{ ";
736 self.output += variant;
737 self.output += " = (";
738 Ok(TupleVariantSerializer { ser: self })
739 }
740
741 fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap> {
742 let root = std::mem::replace(&mut self.at_root, false);
743 if !root {
744 if self.options.open_brace_on_separate_line {
745 self.output.push('\n');
746 self.write_indent();
747 }
748 self.output.push('{');
749 self.indent();
750 }
751 Ok(MapSerializer {
752 ser: self,
753 root,
754 first: true,
755 pending_key: None,
756 })
757 }
758
759 fn serialize_struct(self, _name: &'static str, len: usize) -> Result<Self::SerializeStruct> {
760 self.serialize_map(Some(len))
761 }
762
763 fn serialize_struct_variant(
764 self,
765 _name: &'static str,
766 _variant_index: u32,
767 variant: &'static str,
768 _len: usize,
769 ) -> Result<Self::SerializeStructVariant> {
770 validate_name(variant)?;
771 self.at_root = false;
772 self.output += "{ ";
773 self.output += variant;
774 self.output += " = {";
775 self.indent();
776 Ok(StructVariantSerializer { ser: self })
777 }
778}
779
780#[doc(hidden)]
784pub struct MapSerializer<'a> {
785 ser: &'a mut Serializer,
786 root: bool,
787 first: bool,
788 pending_key: Option<String>,
789}
790
791impl MapSerializer<'_> {
792 fn begin_field(&mut self) {
793 let sep = self.ser.options.semicolon_separators;
794 if self.root {
795 if !self.first {
796 if sep {
797 self.ser.output.push(';');
798 }
799 self.ser.output.push('\n');
800 }
801 } else {
802 if !self.first && sep {
803 self.ser.output.push(';');
804 }
805 self.ser.output.push('\n');
806 self.ser.write_indent();
807 }
808 self.first = false;
809 }
810
811 fn write_assignment(&mut self, key: &str, value_is_group: bool) {
814 self.ser.output += key;
815 let colon = if value_is_group {
816 self.ser.options.colon_assignment_for_groups
817 } else {
818 self.ser.options.colon_assignment_for_non_groups
819 };
820 self.ser.output += if colon { " :" } else { " =" };
821 if !(value_is_group && self.ser.options.open_brace_on_separate_line) {
824 self.ser.output.push(' ');
825 }
826 }
827
828 fn finish(self) -> Result<()> {
829 let sep = self.ser.options.semicolon_separators;
830 if self.root {
831 if !self.first && sep {
832 self.ser.output.push(';');
833 }
834 } else {
835 self.ser.dedent();
836 if !self.first && sep {
837 self.ser.output.push(';');
838 }
839 self.ser.output.push('\n');
840 self.ser.write_indent();
841 self.ser.output.push('}');
842 }
843 Ok(())
844 }
845}
846
847impl ser::SerializeMap for MapSerializer<'_> {
848 type Ok = ();
849 type Error = Error;
850
851 fn serialize_key<T>(&mut self, key: &T) -> Result<()>
852 where
853 T: ?Sized + Serialize,
854 {
855 let mut key_capture = KeyCapture { key: String::new() };
858 key.serialize(&mut key_capture)?;
859 self.pending_key = Some(key_capture.key);
860 Ok(())
861 }
862
863 fn serialize_value<T>(&mut self, value: &T) -> Result<()>
864 where
865 T: ?Sized + Serialize,
866 {
867 let key = self.pending_key.take().ok_or_else(|| {
868 Error::from(ErrorKind::Message(
869 "serialize_value called without serialize_key".to_string(),
870 ))
871 })?;
872 if value_is_none(value) {
875 return Ok(());
876 }
877 self.begin_field();
878 self.write_assignment(&key, value_is_group(value));
879 value.serialize(&mut *self.ser)
880 }
881
882 fn end(self) -> Result<()> {
883 self.finish()
884 }
885}
886
887impl ser::SerializeStruct for MapSerializer<'_> {
888 type Ok = ();
889 type Error = Error;
890
891 fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<()>
892 where
893 T: ?Sized + Serialize,
894 {
895 validate_name(key)?;
896 if value_is_none(value) {
897 return Ok(());
898 }
899 self.begin_field();
900 self.write_assignment(key, value_is_group(value));
901 value.serialize(&mut *self.ser)
902 }
903
904 fn end(self) -> Result<()> {
905 self.finish()
906 }
907}
908
909#[derive(Clone, Copy, PartialEq)]
913enum ElemKind {
914 Bool,
915 Integer,
916 Integer64,
917 Float,
918 Str,
919 NonScalar,
920}
921
922impl ElemKind {
923 fn classify(rendered: &str) -> ElemKind {
924 match rendered.as_bytes().first() {
925 Some(b'"') => ElemKind::Str,
926 Some(b'{' | b'(' | b'[' | b'\n') => ElemKind::NonScalar,
927 Some(b't' | b'f') => ElemKind::Bool,
928 _ if rendered.contains('.') || rendered.contains('e') || rendered.contains('E') => {
931 ElemKind::Float
932 }
933 _ if rendered.ends_with('L') => ElemKind::Integer64,
934 _ => ElemKind::Integer,
935 }
936 }
937
938 fn same_scalar_type(self, other: ElemKind) -> bool {
941 let fold = |k| match k {
942 ElemKind::Integer64 => ElemKind::Integer,
943 k => k,
944 };
945 fold(self) == fold(other)
946 }
947}
948
949#[doc(hidden)]
953pub struct SeqSerializer<'a> {
954 ser: &'a mut Serializer,
955 elements: Vec<(ElemKind, String)>,
956}
957
958impl ser::SerializeSeq for SeqSerializer<'_> {
959 type Ok = ();
960 type Error = Error;
961
962 fn serialize_element<T>(&mut self, value: &T) -> Result<()>
963 where
964 T: ?Sized + Serialize,
965 {
966 let mut tmp = Serializer {
967 output: String::new(),
968 indent_level: self.ser.indent_level,
969 options: self.ser.options.clone(),
970 at_root: false,
971 };
972 value.serialize(&mut tmp)?;
973 let kind = ElemKind::classify(&tmp.output);
974 self.elements.push((kind, tmp.output));
975 Ok(())
976 }
977
978 fn end(self) -> Result<()> {
979 let as_array = self.elements.iter().all(|(k, _)| *k != ElemKind::NonScalar)
980 && self
981 .elements
982 .windows(2)
983 .all(|w| w[0].0.same_scalar_type(w[1].0));
984
985 if as_array {
986 let promote = self.elements.iter().any(|(k, _)| *k == ElemKind::Integer64)
989 && self.elements.iter().any(|(k, _)| *k == ElemKind::Integer);
990 self.ser.output.push('[');
991 for (i, (kind, rendered)) in self.elements.iter().enumerate() {
992 if i > 0 {
993 self.ser.output.push_str(", ");
994 }
995 self.ser.output.push_str(rendered);
996 if promote && *kind == ElemKind::Integer {
997 self.ser.output.push('L');
998 }
999 }
1000 self.ser.output.push(']');
1001 } else {
1002 self.ser.output.push('(');
1003 for (i, (_, rendered)) in self.elements.iter().enumerate() {
1004 if i > 0 {
1005 self.ser.output.push_str(", ");
1006 }
1007 self.ser.output.push_str(rendered);
1008 }
1009 self.ser.output.push(')');
1010 }
1011 Ok(())
1012 }
1013}
1014
1015#[doc(hidden)]
1017pub struct TupleVariantSerializer<'a> {
1018 ser: &'a mut Serializer,
1019}
1020
1021impl ser::SerializeTupleVariant for TupleVariantSerializer<'_> {
1022 type Ok = ();
1023 type Error = Error;
1024
1025 fn serialize_field<T>(&mut self, value: &T) -> Result<()>
1026 where
1027 T: ?Sized + Serialize,
1028 {
1029 if !self.ser.output.ends_with('(') {
1030 self.ser.output += ", ";
1031 }
1032 value.serialize(&mut *self.ser)
1033 }
1034
1035 fn end(self) -> Result<()> {
1036 self.ser.output += "); }";
1037 Ok(())
1038 }
1039}
1040
1041#[doc(hidden)]
1043pub struct StructVariantSerializer<'a> {
1044 ser: &'a mut Serializer,
1045}
1046
1047impl ser::SerializeStructVariant for StructVariantSerializer<'_> {
1048 type Ok = ();
1049 type Error = Error;
1050
1051 fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<()>
1052 where
1053 T: ?Sized + Serialize,
1054 {
1055 validate_name(key)?;
1056 if !self.ser.output.ends_with('{') {
1057 self.ser.output.push(';');
1058 }
1059 self.ser.output.push('\n');
1060 self.ser.write_indent();
1061 self.ser.output += key;
1062 self.ser.output += " = ";
1063 value.serialize(&mut *self.ser)
1064 }
1065
1066 fn end(self) -> Result<()> {
1067 self.ser.dedent();
1068 if !self.ser.output.ends_with('{') {
1069 self.ser.output.push(';');
1070 }
1071 self.ser.output.push('\n');
1072 self.ser.write_indent();
1073 self.ser.output += "}; }";
1074 Ok(())
1075 }
1076}
1077
1078impl ser::SerializeTuple for &mut Serializer {
1079 type Ok = ();
1080 type Error = Error;
1081
1082 fn serialize_element<T>(&mut self, value: &T) -> Result<()>
1083 where
1084 T: ?Sized + Serialize,
1085 {
1086 if !self.output.ends_with('(') {
1087 self.output += ", ";
1088 }
1089 value.serialize(&mut **self)
1090 }
1091
1092 fn end(self) -> Result<()> {
1093 self.output.push(')');
1094 Ok(())
1095 }
1096}
1097
1098impl ser::SerializeTupleStruct for &mut Serializer {
1099 type Ok = ();
1100 type Error = Error;
1101
1102 fn serialize_field<T>(&mut self, value: &T) -> Result<()>
1103 where
1104 T: ?Sized + Serialize,
1105 {
1106 if !self.output.ends_with('(') {
1107 self.output += ", ";
1108 }
1109 value.serialize(&mut **self)
1110 }
1111
1112 fn end(self) -> Result<()> {
1113 self.output.push(')');
1114 Ok(())
1115 }
1116}
1117
1118pub(crate) struct KeyCapture {
1120 pub(crate) key: String,
1121}
1122
1123impl ser::Serializer for &mut KeyCapture {
1124 type Ok = ();
1125 type Error = Error;
1126
1127 type SerializeSeq = ser::Impossible<(), Error>;
1128 type SerializeTuple = ser::Impossible<(), Error>;
1129 type SerializeTupleStruct = ser::Impossible<(), Error>;
1130 type SerializeTupleVariant = ser::Impossible<(), Error>;
1131 type SerializeMap = ser::Impossible<(), Error>;
1132 type SerializeStruct = ser::Impossible<(), Error>;
1133 type SerializeStructVariant = ser::Impossible<(), Error>;
1134
1135 fn serialize_str(self, v: &str) -> Result<()> {
1136 validate_name(v)?;
1137 self.key = v.to_string();
1138 Ok(())
1139 }
1140
1141 fn serialize_unit_variant(
1142 self,
1143 _name: &'static str,
1144 _variant_index: u32,
1145 variant: &'static str,
1146 ) -> Result<()> {
1147 validate_name(variant)?;
1148 self.key = variant.to_string();
1149 Ok(())
1150 }
1151
1152 fn serialize_newtype_struct<T>(self, _name: &'static str, value: &T) -> Result<()>
1153 where
1154 T: ?Sized + Serialize,
1155 {
1156 value.serialize(self)
1157 }
1158
1159 fn serialize_bool(self, _v: bool) -> Result<()> {
1160 Err(ErrorKind::KeyMustBeAString.into())
1161 }
1162
1163 fn serialize_i8(self, _v: i8) -> Result<()> {
1164 Err(ErrorKind::KeyMustBeAString.into())
1165 }
1166
1167 fn serialize_i16(self, _v: i16) -> Result<()> {
1168 Err(ErrorKind::KeyMustBeAString.into())
1169 }
1170
1171 fn serialize_i32(self, _v: i32) -> Result<()> {
1172 Err(ErrorKind::KeyMustBeAString.into())
1173 }
1174
1175 fn serialize_i64(self, _v: i64) -> Result<()> {
1176 Err(ErrorKind::KeyMustBeAString.into())
1177 }
1178
1179 fn serialize_u8(self, _v: u8) -> Result<()> {
1180 Err(ErrorKind::KeyMustBeAString.into())
1181 }
1182
1183 fn serialize_u16(self, _v: u16) -> Result<()> {
1184 Err(ErrorKind::KeyMustBeAString.into())
1185 }
1186
1187 fn serialize_u32(self, _v: u32) -> Result<()> {
1188 Err(ErrorKind::KeyMustBeAString.into())
1189 }
1190
1191 fn serialize_u64(self, _v: u64) -> Result<()> {
1192 Err(ErrorKind::KeyMustBeAString.into())
1193 }
1194
1195 fn serialize_f32(self, _v: f32) -> Result<()> {
1196 Err(ErrorKind::KeyMustBeAString.into())
1197 }
1198
1199 fn serialize_f64(self, _v: f64) -> Result<()> {
1200 Err(ErrorKind::KeyMustBeAString.into())
1201 }
1202
1203 fn serialize_char(self, _v: char) -> Result<()> {
1204 Err(ErrorKind::KeyMustBeAString.into())
1205 }
1206
1207 fn serialize_bytes(self, _v: &[u8]) -> Result<()> {
1208 Err(ErrorKind::KeyMustBeAString.into())
1209 }
1210
1211 fn serialize_none(self) -> Result<()> {
1212 Err(ErrorKind::KeyMustBeAString.into())
1213 }
1214
1215 fn serialize_some<T>(self, _value: &T) -> Result<()>
1216 where
1217 T: ?Sized + Serialize,
1218 {
1219 Err(ErrorKind::KeyMustBeAString.into())
1220 }
1221
1222 fn serialize_unit(self) -> Result<()> {
1223 Err(ErrorKind::KeyMustBeAString.into())
1224 }
1225
1226 fn serialize_unit_struct(self, _name: &'static str) -> Result<()> {
1227 Err(ErrorKind::KeyMustBeAString.into())
1228 }
1229
1230 fn serialize_newtype_variant<T>(
1231 self,
1232 _name: &'static str,
1233 _variant_index: u32,
1234 _variant: &'static str,
1235 _value: &T,
1236 ) -> Result<()>
1237 where
1238 T: ?Sized + Serialize,
1239 {
1240 Err(ErrorKind::KeyMustBeAString.into())
1241 }
1242
1243 fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq> {
1244 Err(ErrorKind::KeyMustBeAString.into())
1245 }
1246
1247 fn serialize_tuple(self, _len: usize) -> Result<Self::SerializeTuple> {
1248 Err(ErrorKind::KeyMustBeAString.into())
1249 }
1250
1251 fn serialize_tuple_struct(
1252 self,
1253 _name: &'static str,
1254 _len: usize,
1255 ) -> Result<Self::SerializeTupleStruct> {
1256 Err(ErrorKind::KeyMustBeAString.into())
1257 }
1258
1259 fn serialize_tuple_variant(
1260 self,
1261 _name: &'static str,
1262 _variant_index: u32,
1263 _variant: &'static str,
1264 _len: usize,
1265 ) -> Result<Self::SerializeTupleVariant> {
1266 Err(ErrorKind::KeyMustBeAString.into())
1267 }
1268
1269 fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap> {
1270 Err(ErrorKind::KeyMustBeAString.into())
1271 }
1272
1273 fn serialize_struct(self, _name: &'static str, _len: usize) -> Result<Self::SerializeStruct> {
1274 Err(ErrorKind::KeyMustBeAString.into())
1275 }
1276
1277 fn serialize_struct_variant(
1278 self,
1279 _name: &'static str,
1280 _variant_index: u32,
1281 _variant: &'static str,
1282 _len: usize,
1283 ) -> Result<Self::SerializeStructVariant> {
1284 Err(ErrorKind::KeyMustBeAString.into())
1285 }
1286}
1287
1288#[cfg(test)]
1289mod tests {
1290 use super::*;
1291 use serde::Serialize;
1292
1293 #[test]
1294 fn test_serialize_primitives() {
1295 assert_eq!(to_string(&42u32).unwrap(), "42");
1296 assert_eq!(to_string(&42i64).unwrap(), "42L");
1297 assert_eq!(to_string(&2.25f64).unwrap(), "2.25");
1298 assert_eq!(to_string(&true).unwrap(), "true");
1299 assert_eq!(to_string(&"hello".to_string()).unwrap(), "\"hello\"");
1300 }
1301
1302 #[test]
1303 fn test_serialize_array() {
1304 let arr = vec![1, 2, 3];
1305 assert_eq!(to_string(&arr).unwrap(), "[1, 2, 3]");
1306 }
1307
1308 #[test]
1309 fn test_serialize_struct() {
1310 #[derive(Serialize)]
1311 struct Test {
1312 a: i32,
1313 b: String,
1314 }
1315
1316 let test = Test {
1317 a: 42,
1318 b: "hello".to_string(),
1319 };
1320 let result = to_string(&test).unwrap();
1321 assert!(result.contains("a = 42"));
1322 assert!(result.contains("b = \"hello\""));
1323 }
1324
1325 #[test]
1326 fn test_serialize_i8_no_l_suffix() {
1327 assert_eq!(to_string(&42i8).unwrap(), "42");
1328 assert_eq!(to_string(&42i16).unwrap(), "42");
1329 assert_eq!(to_string(&42i32).unwrap(), "42");
1330 assert_eq!(to_string(&42i64).unwrap(), "42L");
1331 }
1332
1333 #[test]
1334 fn test_serialize_u64_has_l_suffix() {
1335 assert_eq!(to_string(&42u8).unwrap(), "42");
1336 assert_eq!(to_string(&42u16).unwrap(), "42");
1337 assert_eq!(to_string(&42u32).unwrap(), "42");
1338 assert_eq!(to_string(&42u64).unwrap(), "42L");
1339 }
1340
1341 #[test]
1342 fn test_serialize_u32_beyond_i32_gets_l_suffix() {
1343 assert_eq!(to_string(&(i32::MAX as u32)).unwrap(), "2147483647");
1346 assert_eq!(to_string(&(i32::MAX as u32 + 1)).unwrap(), "2147483648L");
1347 assert_eq!(to_string(&u32::MAX).unwrap(), "4294967295L");
1348 }
1349
1350 #[test]
1351 fn test_serialize_float_always_has_decimal() {
1352 assert_eq!(to_string(&1.0f64).unwrap(), "1.0");
1354 assert_eq!(to_string(&0.0f64).unwrap(), "0.0");
1355 assert_eq!(to_string(&2.25f64).unwrap(), "2.25");
1357 }
1358
1359 #[test]
1360 fn test_serialize_non_finite_floats_error() {
1361 assert!(matches!(
1363 to_string(&f64::INFINITY),
1364 Err(e) if *e.kind() == ErrorKind::NonFiniteFloat
1365 ));
1366 assert!(matches!(
1367 to_string(&f64::NEG_INFINITY),
1368 Err(e) if *e.kind() == ErrorKind::NonFiniteFloat
1369 ));
1370 assert!(matches!(to_string(&f64::NAN), Err(e) if *e.kind() == ErrorKind::NonFiniteFloat));
1371 assert!(matches!(to_string(&f32::NAN), Err(e) if *e.kind() == ErrorKind::NonFiniteFloat));
1372 }
1373
1374 #[test]
1375 fn test_serialize_u64_out_of_range_errors() {
1376 assert_eq!(to_string(&(i64::MAX as u64)).unwrap(), "9223372036854775807L");
1378 assert!(matches!(
1379 to_string(&(i64::MAX as u64 + 1)),
1380 Err(e) if *e.kind() == ErrorKind::IntegerOutOfRange
1381 ));
1382 assert!(matches!(to_string(&u64::MAX), Err(e) if *e.kind() == ErrorKind::IntegerOutOfRange));
1383 }
1384
1385 #[test]
1386 fn test_serialize_invalid_map_key_errors() {
1387 use indexmap::IndexMap;
1388 for bad in ["my key", "2bad", "", "quoted\"", "dot.ted"] {
1389 let mut map = IndexMap::new();
1390 map.insert(bad.to_string(), 1i32);
1391 assert!(
1392 matches!(to_string(&map), Err(e) if matches!(e.kind(), ErrorKind::InvalidSettingName(_))),
1393 "key {bad:?} should be rejected"
1394 );
1395 }
1396 let mut map = IndexMap::new();
1398 map.insert("*wild-card_2*".to_string(), 1i32);
1399 assert!(to_string(&map).is_ok());
1400 }
1401
1402 #[test]
1403 fn test_serialize_control_chars_escaped() {
1404 assert_eq!(to_string(&"a\x01b").unwrap(), "\"a\\x01b\"");
1406 assert_eq!(to_string(&"bell\x07").unwrap(), "\"bell\\a\"");
1407 assert_eq!(to_string(&"tab\tnl\n").unwrap(), "\"tab\\tnl\\n\"");
1408 let s = "\x01\x02\x07\x08\x0b\x1f ok";
1410 let out = to_string(&s.to_string()).unwrap();
1411 let back: String = crate::from_str(&out).unwrap();
1412 assert_eq!(back, s);
1413 }
1414
1415 #[test]
1416 fn test_serialize_seq_of_groups_becomes_list() {
1417 #[derive(Serialize)]
1418 struct P {
1419 x: i32,
1420 }
1421 let out = to_string(&vec![P { x: 1 }, P { x: 2 }]).unwrap();
1423 assert!(out.starts_with('('), "expected list, got: {out}");
1424 assert!(out.ends_with(')'));
1425
1426 let nested = to_string(&vec![vec![1, 2], vec![3]]).unwrap();
1427 assert_eq!(nested, "([1, 2], [3])");
1428
1429 assert_eq!(to_string(&vec![1, 2, 3]).unwrap(), "[1, 2, 3]");
1431 assert_eq!(to_string(&vec!["a", "b"]).unwrap(), "[\"a\", \"b\"]");
1432 }
1433
1434 #[test]
1435 fn test_serialize_mixed_int_widths_promote_to_i64() {
1436 use crate::Value;
1437 let v = Value::Array(vec![Value::Integer(1), Value::Integer64(5_000_000_000)]);
1438 assert_eq!(to_string(&v).unwrap(), "[1L, 5000000000L]");
1439 }
1440
1441 #[test]
1442 fn test_write_options_assignment_and_layout() {
1443 use crate::{Config, WriteOptions};
1444
1445 let config = Config::from_str("port = 80;\ndb = {\n host = \"h\";\n};").unwrap();
1446
1447 let opts = WriteOptions::new()
1449 .colon_assignment_for_groups(true)
1450 .open_brace_on_separate_line(true);
1451 let text = config.to_string_with_options(&opts).unwrap();
1452 assert_eq!(text, "port = 80;\ndb :\n{\n host = \"h\";\n};");
1453 assert_eq!(Config::from_str(&text).unwrap(), config);
1455
1456 let opts = WriteOptions::new()
1458 .colon_assignment_for_groups(true)
1459 .colon_assignment_for_non_groups(true);
1460 let text = config.to_string_with_options(&opts).unwrap();
1461 assert!(text.contains("port : 80"));
1462 assert_eq!(Config::from_str(&text).unwrap(), config);
1463
1464 let opts = WriteOptions::new().semicolon_separators(false);
1466 let text = config.to_string_with_options(&opts).unwrap();
1467 assert!(!text.contains(';'), "got: {text}");
1468 assert_eq!(Config::from_str(&text).unwrap(), config);
1469
1470 let opts = WriteOptions::new().tab_width(4);
1472 let text = config.to_string_with_options(&opts).unwrap();
1473 assert!(text.contains("\n host"), "got: {text}");
1474 let opts = WriteOptions::new().tab_width(0);
1475 let text = config.to_string_with_options(&opts).unwrap();
1476 assert!(text.contains("\n\thost"), "got: {text}");
1477 assert_eq!(Config::from_str(&text).unwrap(), config);
1478
1479 assert_eq!(
1481 config.to_string_with_options(&WriteOptions::default()).unwrap(),
1482 config.to_string().unwrap()
1483 );
1484 }
1485
1486 #[test]
1487 fn test_write_options_floats() {
1488 use crate::{Value, WriteOptions};
1489
1490 let opts = WriteOptions::new().float_precision(3);
1492 assert_eq!(to_string_with_options(&2.5f64, &opts).unwrap(), "2.500");
1493 let opts = WriteOptions::new().float_precision(0);
1495 assert_eq!(to_string_with_options(&3.0f64, &opts).unwrap(), "3.0");
1496
1497 let opts = WriteOptions::new().scientific_notation(true);
1499 let text = to_string_with_options(&2500.0f64, &opts).unwrap();
1500 assert_eq!(text, "2.5e3");
1501 assert_eq!(crate::from_str::<f64>(&text).unwrap(), 2500.0);
1502
1503 let text = to_string_with_options(&vec![100000.0f64, 2.5], &opts).unwrap();
1505 assert_eq!(text, "[1e5, 2.5e0]");
1506 let v: Value = crate::from_str(&format!("x = {};", text)).unwrap();
1507 assert!(v["x"].is_array());
1508 assert_eq!(v["x"].get_index(0).unwrap().as_f64(), Some(1e5));
1509
1510 assert!(to_string_with_options(&f64::NAN, &opts).is_err());
1512 }
1513
1514 #[test]
1515 fn test_serialize_enum_variants() {
1516 #[derive(Serialize)]
1517 enum E {
1518 Unit,
1519 Newtype(i32),
1520 Tuple(i32, bool),
1521 Struct { x: i32 },
1522 }
1523
1524 assert_eq!(to_string(&E::Unit).unwrap(), "\"Unit\"");
1525 assert_eq!(to_string(&E::Newtype(5)).unwrap(), "{ Newtype = 5; }");
1526 assert_eq!(to_string(&E::Tuple(7, true)).unwrap(), "{ Tuple = (7, true); }");
1527 let s = to_string(&E::Struct { x: 9 }).unwrap();
1528 assert!(s.starts_with("{ Struct = {"), "got: {s}");
1529 assert!(s.ends_with("}; }"), "got: {s}");
1530 }
1531
1532 #[test]
1533 fn test_serialize_tuple_as_list() {
1534 let tup = (1, 2, 3);
1535 assert_eq!(to_string(&tup).unwrap(), "(1, 2, 3)");
1536 }
1537
1538 #[test]
1539 fn test_serialize_map_bare_keys() {
1540 use indexmap::IndexMap;
1541 let mut map = IndexMap::new();
1542 map.insert("key".to_string(), 42i32);
1543 let result = to_string(&map).unwrap();
1544 assert!(result.contains("key = 42"));
1546 assert!(!result.contains("\"key\""));
1547 }
1548}