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
76 };
77 value.serialize(&mut serializer)?;
78 Ok(serializer.output)
79}
80
81impl ser::Serializer for &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 ser::SerializeSeq for &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 if let Some(ident) = self.style.indent {
382 self.output.push('\n');
383 self.style.current_indent.reserve(ident);
384 for _ in 0 .. ident {
385 self.style.current_indent.push(' ');
386 }
387 self.output.push_str(self.style.current_indent.as_str());
388 }
389 value.serialize(&mut **self)
390 }
391
392 fn end(self) -> Result<()> {
394 match self.style.trailing_comma {
395 TrailingComma::ALL | TrailingComma::OBJECTS => {
396 self.output.push(',')
397 }
398 _ => {}
399 }
400 if let Some(ident) = self.style.indent {
401 self.style.current_indent.truncate(self.style.current_indent.len() - ident);
402 self.output.reserve(self.style.current_indent.len() + 1);
403 self.output.push('\n');
404 self.output.push_str(self.style.current_indent.as_str());
405 }
406 self.output.push(']');
407 Ok(())
408 }
409}
410
411impl ser::SerializeTuple for &mut Serializer {
413 type Ok = ();
414 type Error = SerdeJSON5Error;
415
416 fn serialize_element<T>(&mut self, value: &T) -> Result<()>
417 where
418 T: ?Sized + Serialize,
419 {
420 if !self.output.ends_with('[') {
421 match self.style.indent {
422 Some(_) => {
423 self.output.reserve(self.style.current_indent.len() + 2);
424 self.output += ",\n";
425 self.output.push_str(self.style.current_indent.as_str());
426 }
427 None => {
428 self.output.push_str(self.style.item_separator.as_str())
429 }
430 }
431 } else if let Some(ident) = self.style.indent {
432 self.output.push('\n');
433 self.style.current_indent.reserve(ident);
434 for _ in 0 .. ident {
435 self.style.current_indent.push(' ');
436 }
437 self.output.push_str(self.style.current_indent.as_str());
438 }
439 value.serialize(&mut **self)
440 }
441
442 fn end(self) -> Result<()> {
443 match self.style.trailing_comma {
444 TrailingComma::ALL | TrailingComma::OBJECTS => {
445 self.output.push(',')
446 }
447 _ => {}
448 }
449 if let Some(ident) = self.style.indent {
450 self.style.current_indent.truncate(self.style.current_indent.len() - ident);
451 self.output.reserve(self.style.current_indent.len() + 1);
452 self.output.push('\n');
453 self.output.push_str(self.style.current_indent.as_str());
454 }
455 self.output.push(']');
456 Ok(())
457 }
458}
459
460impl ser::SerializeTupleStruct for &mut Serializer {
462 type Ok = ();
463 type Error = SerdeJSON5Error;
464
465 fn serialize_field<T>(&mut self, value: &T) -> Result<()>
466 where
467 T: ?Sized + Serialize,
468 {
469 if !self.output.ends_with('[') {
470 match self.style.indent {
471 Some(_) => {
472 self.output.reserve(self.style.current_indent.len() + 2);
473 self.output += ",\n";
474 self.output.push_str(self.style.current_indent.as_str());
475 }
476 None => {
477 self.output.push_str(self.style.item_separator.as_str())
478 }
479 }
480 } else if let Some(ident) = self.style.indent {
481 self.output.push('\n');
482 self.style.current_indent.reserve(ident);
483 for _ in 0 .. ident {
484 self.style.current_indent.push(' ');
485 }
486 self.output.push_str(self.style.current_indent.as_str());
487 }
488 value.serialize(&mut **self)
489 }
490
491 fn end(self) -> Result<()> {
492 match self.style.trailing_comma {
493 TrailingComma::ALL | TrailingComma::OBJECTS => {
494 self.output.push(',')
495 }
496 _ => {}
497 }
498 if let Some(ident) = self.style.indent {
499 self.style.current_indent.truncate(self.style.current_indent.len() - ident);
500 self.output.reserve(self.style.current_indent.len() + 1);
501 self.output.push('\n');
502 self.output.push_str(self.style.current_indent.as_str());
503 }
504 self.output.push(']');
505 Ok(())
506 }
507}
508
509impl ser::SerializeTupleVariant for &mut Serializer {
519 type Ok = ();
520 type Error = SerdeJSON5Error;
521
522 fn serialize_field<T>(&mut self, value: &T) -> Result<()>
523 where
524 T: ?Sized + Serialize,
525 {
526 if !self.output.ends_with('[') {
527 match self.style.indent {
528 Some(_) => {
529 self.output.reserve(self.style.current_indent.len() + 2);
530 self.output += ",\n";
531 self.output.push_str(self.style.current_indent.as_str());
532 }
533 None => {
534 self.output.push_str(self.style.item_separator.as_str())
535 }
536 }
537 } else if let Some(ident) = self.style.indent {
538 self.output.push('\n');
539 self.style.current_indent.reserve(ident);
540 for _ in 0 .. ident {
541 self.style.current_indent.push(' ');
542 }
543 self.output.push_str(self.style.current_indent.as_str());
544 }
545 value.serialize(&mut **self)
546 }
547
548 fn end(self) -> Result<()> {
549 match self.style.trailing_comma {
550 TrailingComma::ALL | TrailingComma::OBJECTS => {
551 self.output.push(',')
552 }
553 _ => {}
554 }
555 if let Some(ident) = self.style.indent {
556 self.style.current_indent.truncate(self.style.current_indent.len() - ident);
557 self.output.reserve(self.style.current_indent.len() + 1);
558 self.output.push('\n');
559 self.output.push_str(self.style.current_indent.as_str());
560 }
561 self.output.push(']');
562 match self.style.trailing_comma {
563 TrailingComma::ALL | TrailingComma::OBJECTS => {
564 self.output.push(',')
565 }
566 _ => {}
567 }
568 if let Some(ident) = self.style.indent {
569 self.style.current_indent.truncate(self.style.current_indent.len() - ident);
570 self.output.reserve(self.style.current_indent.len() + 1);
571 self.output.push('\n');
572 self.output.push_str(self.style.current_indent.as_str());
573 }
574 self.output.push('}');
575 Ok(())
576 }
577}
578
579impl ser::SerializeMap for &mut Serializer {
588 type Ok = ();
589 type Error = SerdeJSON5Error;
590
591 fn serialize_key<T>(&mut self, key: &T) -> Result<()>
600 where
601 T: ?Sized + Serialize,
602 {
603 if !self.output.ends_with('{') {
604 match self.style.indent {
605 Some(_) => {
606 self.output.reserve(self.style.current_indent.len() + 2);
607 self.output += ",\n";
608 self.output.push_str(self.style.current_indent.as_str());
609 }
610 None => {
611 self.output.push_str(self.style.item_separator.as_str())
612 }
613 }
614 } else if let Some(ident) = self.style.indent {
615 self.output.push('\n');
616 self.style.current_indent.reserve(ident);
617 for _ in 0 .. ident {
618 self.style.current_indent.push(' ');
619 }
620 self.output.push_str(self.style.current_indent.as_str());
621 }
622 key.serialize(&mut **self)
623 }
624
625 fn serialize_value<T>(&mut self, value: &T) -> Result<()>
629 where
630 T: ?Sized + Serialize,
631 {
632 self.output.push_str(self.style.key_separator.as_str());
633 value.serialize(&mut **self)
634 }
635
636 fn end(self) -> Result<()> {
637 match self.style.trailing_comma {
638 TrailingComma::ALL | TrailingComma::OBJECTS => {
639 self.output.push(',')
640 }
641 _ => {}
642 }
643 if let Some(ident) = self.style.indent {
644 self.style.current_indent.truncate(self.style.current_indent.len() - ident);
645 self.output.reserve(self.style.current_indent.len() + 1);
646 self.output.push('\n');
647 self.output.push_str(self.style.current_indent.as_str());
648 }
649 self.output.push('}');
650 Ok(())
651 }
652}
653
654impl ser::SerializeStruct for &mut Serializer {
657 type Ok = ();
658 type Error = SerdeJSON5Error;
659
660 fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<()>
661 where
662 T: ?Sized + Serialize,
663 {
664 if !self.output.ends_with('{') {
665 match self.style.indent {
666 Some(_) => {
667 self.output.reserve(self.style.current_indent.len() + 2);
668 self.output += ",\n";
669 self.output.push_str(self.style.current_indent.as_str());
670 }
671 None => {
672 self.output.push_str(self.style.item_separator.as_str())
673 }
674 }
675 } else if let Some(ident) = self.style.indent {
676 self.output.push('\n');
677 self.style.current_indent.reserve(ident);
678 for _ in 0 .. ident {
679 self.style.current_indent.push(' ');
680 }
681 self.output.push_str(self.style.current_indent.as_str());
682 }
683 key.serialize(&mut **self)?;
684 self.output.push_str(self.style.key_separator.as_str());
685 value.serialize(&mut **self)
686 }
687
688 fn end(self) -> Result<()> {
689 match self.style.trailing_comma {
690 TrailingComma::ALL | TrailingComma::OBJECTS => {
691 self.output.push(',')
692 }
693 _ => {}
694 }
695 if let Some(ident) = self.style.indent {
696 self.style.current_indent.truncate(self.style.current_indent.len() - ident);
697 self.output.reserve(self.style.current_indent.len() + 1);
698 self.output.push('\n');
699 self.output.push_str(self.style.current_indent.as_str());
700 }
701
702 self.output.push('}');
703 Ok(())
704 }
705}
706
707
708
709impl ser::SerializeStructVariant for &mut Serializer {
712 type Ok = ();
713 type Error = SerdeJSON5Error;
714
715 fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<()>
716 where
717 T: ?Sized + Serialize,
718 {
719 if !self.output.ends_with('{') {
720 match self.style.indent {
721 Some(_) => {
722 self.output.reserve(self.style.current_indent.len() + 2);
723 self.output += ",\n";
724 self.output.push_str(self.style.current_indent.as_str());
725 }
726 None => {
727 self.output.push_str(self.style.item_separator.as_str())
728 }
729 }
730 } else if let Some(ident) = self.style.indent {
731 self.output.push('\n');
732 self.style.current_indent.reserve(ident);
733 for _ in 0 .. ident {
734 self.style.current_indent.push(' ');
735 }
736 self.output.push_str(self.style.current_indent.as_str());
737 }
738 key.serialize(&mut **self)?;
739 self.output.push_str(self.style.key_separator.as_str());
740 value.serialize(&mut **self)
741 }
742
743 fn end(self) -> Result<()> {
744 match self.style.trailing_comma {
745 TrailingComma::ALL | TrailingComma::OBJECTS => {
746 self.output.push(',')
747 }
748 _ => {}
749 }
750 if let Some(ident) = self.style.indent {
751 self.style.current_indent.truncate(self.style.current_indent.len() - ident);
752 self.output.reserve(self.style.current_indent.len() + 1);
753 self.output.push('\n');
754 self.output.push_str(self.style.current_indent.as_str());
755 }
756 self.output.push('}');
757
758
759 match self.style.trailing_comma {
760 TrailingComma::ALL | TrailingComma::OBJECTS => {
761 self.output.push(',')
762 }
763 _ => {}
764 }
765 if let Some(ident) = self.style.indent {
766 self.style.current_indent.truncate(self.style.current_indent.len() - ident);
767 self.output.reserve(self.style.current_indent.len() + 1);
768 self.output.push('\n');
769 self.output.push_str(self.style.current_indent.as_str());
770 }
771 self.output.push('}');
772 Ok(())
773 }
774}
775
776#[cfg(test)]
777mod tests {
778 use super::*;
779 #[derive(Serialize)]
780 struct Test {
781 int: u32,
782 seq: Vec<&'static str>,
783 }
784
785 #[test]
786 fn test_struct() {
787
788 let test = Test {
789 int: 1,
790 seq: vec!["a", "b"],
791 };
792 let expected = r#"{"int": 1, "seq": ["a", "b"]}"#;
793 assert_eq!(to_string(&test).unwrap(), expected);
794 }
795 #[test]
796 fn test_struct_styled() {
797 let test = Test {
798 int: 1,
799 seq: vec!["a", "b"],
800 };
801 let expected = r#"{
802 "int": 1,
803 "seq": [
804 "a",
805 "b",
806 ],
807}"#;
808 let style = FormatConfiguration::with_indent(4, TrailingComma::ALL);
809 assert_eq!(to_string_formatted(&test, style).unwrap(), expected);
810 }
811
812
813 #[test]
814 fn test_enum() {
815 #[derive(Serialize)]
816 enum E {
817 Unit,
818 Newtype(u32),
819 Tuple(u32, u32),
820 Struct { a: u32 },
821 }
822
823 let u = E::Unit;
824 let expected = r#""Unit""#;
825 assert_eq!(to_string(&u).unwrap(), expected);
826
827 let n = E::Newtype(1);
828 let expected = r#"{"Newtype": 1}"#;
829 assert_eq!(to_string(&n).unwrap(), expected);
830
831 let t = E::Tuple(1, 2);
832 let expected = r#"{"Tuple": [1, 2]}"#;
833 assert_eq!(to_string(&t).unwrap(), expected);
834
835 let s = E::Struct { a: 1 };
836 let expected = r#"{"Struct": {"a": 1}}"#;
837 assert_eq!(to_string(&s).unwrap(), expected);
838 }
839}