1use serde::{ser, Serialize};
2use crate::parser::{TrailingComma};
3use std::fmt;
4use crate::utils::{escape_double_quoted};
5
6#[derive(Debug)]
7pub enum SerdeJSON5Error {
8 Custom(String),
9}
10
11impl std::error::Error for SerdeJSON5Error {}
12impl fmt::Display for SerdeJSON5Error {
13 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
14 match self {
15 SerdeJSON5Error::Custom(msg) => write!(f, "{}", msg),
16 }
17 }
18}
19
20impl ser::Error for SerdeJSON5Error {
21 fn custom<T: fmt::Display>(msg: T) -> Self {
22 SerdeJSON5Error::Custom(msg.to_string())
23 }
24}
25
26use crate::parser::FormatConfiguration;
27
28pub struct Serializer {
30 output: String,
32 style: FormatConfiguration
33}
34
35type Result<T> = std::result::Result<T, SerdeJSON5Error>;
36
37pub fn to_string<T>(value: &T) -> Result<String>
58where
59 T: Serialize,
60{
61 let mut serializer = Serializer {
62 output: String::new(),
63 style: FormatConfiguration::default()
64 };
65 value.serialize(&mut serializer)?;
66 Ok(serializer.output)
67}
68
69pub fn to_string_formatted<T>(value: &T, style: FormatConfiguration) -> Result<String>
70where
71 T: Serialize
72{
73 let mut serializer = Serializer {
74 output: String::new(),
75 style: style
76 };
77 value.serialize(&mut serializer)?;
78 Ok(serializer.output)
79}
80
81impl<'a> ser::Serializer for &'a mut Serializer {
82 type Ok = ();
89
90 type Error = SerdeJSON5Error;
92
93 type SerializeSeq = Self;
98 type SerializeTuple = Self;
99 type SerializeTupleStruct = Self;
100 type SerializeTupleVariant = Self;
101 type SerializeMap = Self;
102 type SerializeStruct = Self;
103 type SerializeStructVariant = Self;
104
105 fn serialize_bool(self, v: bool) -> Result<()> {
109 self.output += if v { "true" } else { "false" };
110 Ok(())
111 }
112
113 fn serialize_i8(self, v: i8) -> Result<()> {
118 self.serialize_i64(i64::from(v))
119 }
120
121 fn serialize_i16(self, v: i16) -> Result<()> {
122 self.serialize_i64(i64::from(v))
123 }
124
125 fn serialize_i32(self, v: i32) -> Result<()> {
126 self.serialize_i64(i64::from(v))
127 }
128
129 fn serialize_i64(self, v: i64) -> Result<()> {
132 self.output += &v.to_string();
133 Ok(())
134 }
135
136 fn serialize_u8(self, v: u8) -> Result<()> {
137 self.serialize_u64(u64::from(v))
138 }
139
140 fn serialize_u16(self, v: u16) -> Result<()> {
141 self.serialize_u64(u64::from(v))
142 }
143
144 fn serialize_u32(self, v: u32) -> Result<()> {
145 self.serialize_u64(u64::from(v))
146 }
147
148 fn serialize_u64(self, v: u64) -> Result<()> {
149 self.output += &v.to_string();
150 Ok(())
151 }
152
153 fn serialize_f32(self, v: f32) -> Result<()> {
154 self.serialize_f64(f64::from(v))
155 }
156
157 fn serialize_f64(self, v: f64) -> Result<()> {
158 self.output += &v.to_string();
159 Ok(())
160 }
161
162 fn serialize_char(self, v: char) -> Result<()> {
165 self.serialize_str(&v.to_string())
166 }
167
168 fn serialize_str(self, v: &str) -> Result<()> {
172 self.output += "\"";
173 self.output += escape_double_quoted(v).as_str();
174 self.output += "\"";
175 Ok(())
176 }
177
178 fn serialize_bytes(self, v: &[u8]) -> Result<()> {
182 use serde::ser::SerializeSeq;
183 let mut seq = self.serialize_seq(Some(v.len()))?;
184 for byte in v {
185 seq.serialize_element(byte)?;
186 }
187 seq.end()
188 }
189
190 fn serialize_none(self) -> Result<()> {
192 self.serialize_unit()
193 }
194
195 fn serialize_some<T>(self, value: &T) -> Result<()>
201 where
202 T: ?Sized + Serialize,
203 {
204 value.serialize(self)
205 }
206
207 fn serialize_unit(self) -> Result<()> {
210 self.output += "null";
211 Ok(())
212 }
213
214 fn serialize_unit_struct(self, _name: &'static str) -> Result<()> {
218 self.serialize_unit()
219 }
220
221 fn serialize_unit_variant(
226 self,
227 _name: &'static str,
228 _variant_index: u32,
229 variant: &'static str,
230 ) -> Result<()> {
231 self.serialize_str(variant)
232 }
233
234 fn serialize_newtype_struct<T>(
237 self,
238 _name: &'static str,
239 value: &T,
240 ) -> Result<()>
241 where
242 T: ?Sized + Serialize,
243 {
244 value.serialize(self)
245 }
246
247 fn serialize_newtype_variant<T>(
253 self,
254 _name: &'static str,
255 _variant_index: u32,
256 variant: &'static str,
257 value: &T,
258 ) -> Result<()>
259 where
260 T: ?Sized + Serialize,
261 {
262 self.output.push('{');
263 variant.serialize(&mut *self)?;
264 self.output.push_str(self.style.key_separator.as_str());
265 value.serialize(&mut *self)?;
266 self.output.push('}');
267 Ok(())
268 }
269
270 fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq> {
281 self.output += "[";
282 Ok(self)
283 }
284
285 fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple> {
290 self.serialize_seq(Some(len))
291 }
292
293 fn serialize_tuple_struct(
295 self,
296 _name: &'static str,
297 len: usize,
298 ) -> Result<Self::SerializeTupleStruct> {
299 self.serialize_seq(Some(len))
300 }
301
302 fn serialize_tuple_variant(
305 self,
306 _name: &'static str,
307 _variant_index: u32,
308 variant: &'static str,
309 _len: usize,
310 ) -> Result<Self::SerializeTupleVariant> {
311 self.output.push('{');
312 variant.serialize(&mut *self)?;
313 self.output.push_str(format!("{}[", self.style.key_separator).as_str());
314 Ok(self)
315 }
316
317 fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap> {
319 self.output.push('{');
320 Ok(self)
321 }
322
323 fn serialize_struct(
329 self,
330 _name: &'static str,
331 len: usize,
332 ) -> Result<Self::SerializeStruct> {
333 self.serialize_map(Some(len))
334 }
335
336 fn serialize_struct_variant(
339 self,
340 _name: &'static str,
341 _variant_index: u32,
342 variant: &'static str,
343 _len: usize,
344 ) -> Result<Self::SerializeStructVariant> {
345 self.output.push('{');
346 variant.serialize(&mut *self)?;
347 self.output.push_str(format!("{}{{", self.style.key_separator).as_str());
348 Ok(self)
349 }
350}
351
352impl<'a> ser::SerializeSeq for &'a mut Serializer {
360 type Ok = ();
362 type Error = SerdeJSON5Error;
364
365 fn serialize_element<T>(&mut self, value: &T) -> Result<()>
367 where
368 T: ?Sized + Serialize,
369 {
370 if !self.output.ends_with('[') {
371 match self.style.indent {
372 Some(_) => {
373 self.output.reserve(self.style.current_indent.len() + 2);
374 self.output += ",\n";
375 self.output.push_str(self.style.current_indent.as_str());
376 }
377 None => {
378 self.output.push_str(self.style.item_separator.as_str())
379 }
380 }
381 } else {
382 match self.style.indent {
383 Some(ident) => {
384 self.output.push('\n');
385 self.style.current_indent.reserve(ident);
386 for _ in 0 .. ident {
387 self.style.current_indent.push(' ');
388 }
389 self.output.push_str(self.style.current_indent.as_str());
390 }
391 None => {}
392 }
393 }
394 value.serialize(&mut **self)
395 }
396
397 fn end(self) -> Result<()> {
399 match self.style.trailing_comma {
400 TrailingComma::ALL | TrailingComma::OBJECTS => {
401 self.output.push(',')
402 }
403 _ => {}
404 }
405 match self.style.indent {
406 Some(ident) => {
407 self.style.current_indent.truncate(self.style.current_indent.len() - ident);
408 self.output.reserve(self.style.current_indent.len() + 1);
409 self.output.push('\n');
410 self.output.push_str(self.style.current_indent.as_str());
411 }
412 None => {}
413 }
414 self.output.push(']');
415 Ok(())
416 }
417}
418
419impl<'a> ser::SerializeTuple for &'a mut Serializer {
421 type Ok = ();
422 type Error = SerdeJSON5Error;
423
424 fn serialize_element<T>(&mut self, value: &T) -> Result<()>
425 where
426 T: ?Sized + Serialize,
427 {
428 if !self.output.ends_with('[') {
429 match self.style.indent {
430 Some(_) => {
431 self.output.reserve(self.style.current_indent.len() + 2);
432 self.output += ",\n";
433 self.output.push_str(self.style.current_indent.as_str());
434 }
435 None => {
436 self.output.push_str(self.style.item_separator.as_str())
437 }
438 }
439 } else {
440 match self.style.indent {
441 Some(ident) => {
442 self.output.push('\n');
443 self.style.current_indent.reserve(ident);
444 for _ in 0 .. ident {
445 self.style.current_indent.push(' ');
446 }
447 self.output.push_str(self.style.current_indent.as_str());
448 }
449 None => {}
450 }
451 }
452 value.serialize(&mut **self)
453 }
454
455 fn end(self) -> Result<()> {
456 match self.style.trailing_comma {
457 TrailingComma::ALL | TrailingComma::OBJECTS => {
458 self.output.push(',')
459 }
460 _ => {}
461 }
462 match self.style.indent {
463 Some(ident) => {
464 self.style.current_indent.truncate(self.style.current_indent.len() - ident);
465 self.output.reserve(self.style.current_indent.len() + 1);
466 self.output.push('\n');
467 self.output.push_str(self.style.current_indent.as_str());
468 }
469 None => {}
470 }
471 self.output.push(']');
472 Ok(())
473 }
474}
475
476impl<'a> ser::SerializeTupleStruct for &'a mut Serializer {
478 type Ok = ();
479 type Error = SerdeJSON5Error;
480
481 fn serialize_field<T>(&mut self, value: &T) -> Result<()>
482 where
483 T: ?Sized + Serialize,
484 {
485 if !self.output.ends_with('[') {
486 match self.style.indent {
487 Some(_) => {
488 self.output.reserve(self.style.current_indent.len() + 2);
489 self.output += ",\n";
490 self.output.push_str(self.style.current_indent.as_str());
491 }
492 None => {
493 self.output.push_str(self.style.item_separator.as_str())
494 }
495 }
496 } else {
497 match self.style.indent {
498 Some(ident) => {
499 self.output.push('\n');
500 self.style.current_indent.reserve(ident);
501 for _ in 0 .. ident {
502 self.style.current_indent.push(' ');
503 }
504 self.output.push_str(self.style.current_indent.as_str());
505 }
506 None => {}
507 }
508 }
509 value.serialize(&mut **self)
510 }
511
512 fn end(self) -> Result<()> {
513 match self.style.trailing_comma {
514 TrailingComma::ALL | TrailingComma::OBJECTS => {
515 self.output.push(',')
516 }
517 _ => {}
518 }
519 match self.style.indent {
520 Some(ident) => {
521 self.style.current_indent.truncate(self.style.current_indent.len() - ident);
522 self.output.reserve(self.style.current_indent.len() + 1);
523 self.output.push('\n');
524 self.output.push_str(self.style.current_indent.as_str());
525 }
526 None => {}
527 }
528 self.output.push(']');
529 Ok(())
530 }
531}
532
533impl<'a> ser::SerializeTupleVariant for &'a mut Serializer {
543 type Ok = ();
544 type Error = SerdeJSON5Error;
545
546 fn serialize_field<T>(&mut self, value: &T) -> Result<()>
547 where
548 T: ?Sized + Serialize,
549 {
550 if !self.output.ends_with('[') {
551 match self.style.indent {
552 Some(_) => {
553 self.output.reserve(self.style.current_indent.len() + 2);
554 self.output += ",\n";
555 self.output.push_str(self.style.current_indent.as_str());
556 }
557 None => {
558 self.output.push_str(self.style.item_separator.as_str())
559 }
560 }
561 } else {
562 match self.style.indent {
563 Some(ident) => {
564 self.output.push('\n');
565 self.style.current_indent.reserve(ident);
566 for _ in 0 .. ident {
567 self.style.current_indent.push(' ');
568 }
569 self.output.push_str(self.style.current_indent.as_str());
570 }
571 None => {}
572 }
573 }
574 value.serialize(&mut **self)
575 }
576
577 fn end(self) -> Result<()> {
578 match self.style.trailing_comma {
579 TrailingComma::ALL | TrailingComma::OBJECTS => {
580 self.output.push(',')
581 }
582 _ => {}
583 }
584 match self.style.indent {
585 Some(ident) => {
586 self.style.current_indent.truncate(self.style.current_indent.len() - ident);
587 self.output.reserve(self.style.current_indent.len() + 1);
588 self.output.push('\n');
589 self.output.push_str(self.style.current_indent.as_str());
590 }
591 None => {}
592 }
593 self.output.push(']');
594 match self.style.trailing_comma {
595 TrailingComma::ALL | TrailingComma::OBJECTS => {
596 self.output.push(',')
597 }
598 _ => {}
599 }
600 match self.style.indent {
601 Some(ident) => {
602 self.style.current_indent.truncate(self.style.current_indent.len() - ident);
603 self.output.reserve(self.style.current_indent.len() + 1);
604 self.output.push('\n');
605 self.output.push_str(self.style.current_indent.as_str());
606 }
607 None => {}
608 }
609 self.output.push('}');
610 Ok(())
611 }
612}
613
614impl<'a> ser::SerializeMap for &'a mut Serializer {
623 type Ok = ();
624 type Error = SerdeJSON5Error;
625
626 fn serialize_key<T>(&mut self, key: &T) -> Result<()>
635 where
636 T: ?Sized + Serialize,
637 {
638 if !self.output.ends_with('{') {
639 match self.style.indent {
640 Some(_) => {
641 self.output.reserve(self.style.current_indent.len() + 2);
642 self.output += ",\n";
643 self.output.push_str(self.style.current_indent.as_str());
644 }
645 None => {
646 self.output.push_str(self.style.item_separator.as_str())
647 }
648 }
649 } else {
650 match self.style.indent {
651 Some(ident) => {
652 self.output.push('\n');
653 self.style.current_indent.reserve(ident);
654 for _ in 0 .. ident {
655 self.style.current_indent.push(' ');
656 }
657 self.output.push_str(self.style.current_indent.as_str());
658 }
659 None => {}
660 }
661 }
662 key.serialize(&mut **self)
663 }
664
665 fn serialize_value<T>(&mut self, value: &T) -> Result<()>
669 where
670 T: ?Sized + Serialize,
671 {
672 self.output.push_str(self.style.key_separator.as_str());
673 value.serialize(&mut **self)
674 }
675
676 fn end(self) -> Result<()> {
677 match self.style.trailing_comma {
678 TrailingComma::ALL | TrailingComma::OBJECTS => {
679 self.output.push(',')
680 }
681 _ => {}
682 }
683 match self.style.indent {
684 Some(ident) => {
685 self.style.current_indent.truncate(self.style.current_indent.len() - ident);
686 self.output.reserve(self.style.current_indent.len() + 1);
687 self.output.push('\n');
688 self.output.push_str(self.style.current_indent.as_str());
689 }
690 None => {}
691 }
692 self.output.push('}');
693 Ok(())
694 }
695}
696
697impl<'a> ser::SerializeStruct for &'a mut Serializer {
700 type Ok = ();
701 type Error = SerdeJSON5Error;
702
703 fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<()>
704 where
705 T: ?Sized + Serialize,
706 {
707 if !self.output.ends_with('{') {
708 match self.style.indent {
709 Some(_) => {
710 self.output.reserve(self.style.current_indent.len() + 2);
711 self.output += ",\n";
712 self.output.push_str(self.style.current_indent.as_str());
713 }
714 None => {
715 self.output.push_str(self.style.item_separator.as_str())
716 }
717 }
718 } else {
719 match self.style.indent {
720 Some(ident) => {
721 self.output.push('\n');
722 self.style.current_indent.reserve(ident);
723 for _ in 0 .. ident {
724 self.style.current_indent.push(' ');
725 }
726 self.output.push_str(self.style.current_indent.as_str());
727 }
728 None => {}
729 }
730 }
731 key.serialize(&mut **self)?;
732 self.output.push_str(self.style.key_separator.as_str());
733 value.serialize(&mut **self)
734 }
735
736 fn end(self) -> Result<()> {
737 match self.style.trailing_comma {
738 TrailingComma::ALL | TrailingComma::OBJECTS => {
739 self.output.push(',')
740 }
741 _ => {}
742 }
743 match self.style.indent {
744 Some(ident) => {
745 self.style.current_indent.truncate(self.style.current_indent.len() - ident);
746 self.output.reserve(self.style.current_indent.len() + 1);
747 self.output.push('\n');
748 self.output.push_str(self.style.current_indent.as_str());
749 }
750 None => {}
751 }
752
753 self.output.push('}');
754 Ok(())
755 }
756}
757
758
759
760impl<'a> ser::SerializeStructVariant for &'a mut Serializer {
763 type Ok = ();
764 type Error = SerdeJSON5Error;
765
766 fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<()>
767 where
768 T: ?Sized + Serialize,
769 {
770 if !self.output.ends_with('{') {
771 match self.style.indent {
772 Some(_) => {
773 self.output.reserve(self.style.current_indent.len() + 2);
774 self.output += ",\n";
775 self.output.push_str(self.style.current_indent.as_str());
776 }
777 None => {
778 self.output.push_str(self.style.item_separator.as_str())
779 }
780 }
781 } else {
782 match self.style.indent {
783 Some(ident) => {
784 self.output.push('\n');
785 self.style.current_indent.reserve(ident);
786 for _ in 0 .. ident {
787 self.style.current_indent.push(' ');
788 }
789 self.output.push_str(self.style.current_indent.as_str());
790 }
791 None => {}
792 }
793 }
794 key.serialize(&mut **self)?;
795 self.output.push_str(self.style.key_separator.as_str());
796 value.serialize(&mut **self)
797 }
798
799 fn end(self) -> Result<()> {
800 match self.style.trailing_comma {
801 TrailingComma::ALL | TrailingComma::OBJECTS => {
802 self.output.push(',')
803 }
804 _ => {}
805 }
806 match self.style.indent {
807 Some(ident) => {
808 self.style.current_indent.truncate(self.style.current_indent.len() - ident);
809 self.output.reserve(self.style.current_indent.len() + 1);
810 self.output.push('\n');
811 self.output.push_str(self.style.current_indent.as_str());
812 }
813 None => {}
814 }
815 self.output.push('}');
816
817
818 match self.style.trailing_comma {
819 TrailingComma::ALL | TrailingComma::OBJECTS => {
820 self.output.push(',')
821 }
822 _ => {}
823 }
824 match self.style.indent {
825 Some(ident) => {
826 self.style.current_indent.truncate(self.style.current_indent.len() - ident);
827 self.output.reserve(self.style.current_indent.len() + 1);
828 self.output.push('\n');
829 self.output.push_str(self.style.current_indent.as_str());
830 }
831 None => {}
832 }
833 self.output.push('}');
834 Ok(())
835 }
836}
837
838#[cfg(test)]
839mod tests {
840 use super::*;
841 #[derive(Serialize)]
842 struct Test {
843 int: u32,
844 seq: Vec<&'static str>,
845 }
846
847 #[test]
848 fn test_struct() {
849
850 let test = Test {
851 int: 1,
852 seq: vec!["a", "b"],
853 };
854 let expected = r#"{"int": 1, "seq": ["a", "b"]}"#;
855 assert_eq!(to_string(&test).unwrap(), expected);
856 }
857 #[test]
858 fn test_struct_styled() {
859 let test = Test {
860 int: 1,
861 seq: vec!["a", "b"],
862 };
863 let expected = r#"{
864 "int": 1,
865 "seq": [
866 "a",
867 "b",
868 ],
869}"#;
870 let style = FormatConfiguration::with_indent(4, TrailingComma::ALL);
871 assert_eq!(to_string_formatted(&test, style).unwrap(), expected);
872 }
873
874
875 #[test]
876 fn test_enum() {
877 #[derive(Serialize)]
878 enum E {
879 Unit,
880 Newtype(u32),
881 Tuple(u32, u32),
882 Struct { a: u32 },
883 }
884
885 let u = E::Unit;
886 let expected = r#""Unit""#;
887 assert_eq!(to_string(&u).unwrap(), expected);
888
889 let n = E::Newtype(1);
890 let expected = r#"{"Newtype": 1}"#;
891 assert_eq!(to_string(&n).unwrap(), expected);
892
893 let t = E::Tuple(1, 2);
894 let expected = r#"{"Tuple": [1, 2]}"#;
895 assert_eq!(to_string(&t).unwrap(), expected);
896
897 let s = E::Struct { a: 1 };
898 let expected = r#"{"Struct": {"a": 1}}"#;
899 assert_eq!(to_string(&s).unwrap(), expected);
900 }
901}