Skip to main content

ason/
ser.rs

1// Copyright (c) 2026 Hemashushu <hippospark@gmail.com>, All rights reserved.
2//
3// This Source Code Form is subject to the terms of
4// the Mozilla Public License version 2.0 and additional exceptions.
5// For more details, see the LICENSE, LICENSE.additional, and CONTRIBUTING files.
6
7use std::io::Write;
8
9use serde::{Serialize, ser};
10
11use crate::error::AsonError;
12
13pub const DEFAULT_INDENT_CHARS: &str = "    ";
14pub const DEFAULT_NEWLINE_CHARS: &str = "\n";
15
16pub fn ser_to_string<T>(value: &T) -> Result<String, AsonError>
17where
18    T: Serialize,
19{
20    let mut buf: Vec<u8> = vec![];
21    ser_to_writer(value, &mut buf)?;
22    let s = String::from_utf8(buf).unwrap();
23    Ok(s)
24}
25
26pub fn ser_to_writer<T, W: Write>(value: &T, writer: &mut W) -> Result<(), AsonError>
27where
28    T: Serialize,
29{
30    let mut serializer = Serializer::new(writer);
31    value.serialize(&mut serializer)
32}
33
34pub struct Serializer<'a, W>
35where
36    W: Write,
37{
38    upstream: &'a mut W,
39    indent_level: usize,
40    is_first_element: bool,
41    // newline_separator: bool,
42}
43
44impl<'a, W> Serializer<'a, W>
45where
46    W: Write,
47{
48    pub fn new(upstream: &'a mut W) -> Self {
49        Self {
50            upstream,
51            indent_level: 0,
52            is_first_element: false,
53            // newline_separator: false,
54        }
55    }
56
57    fn print_newline(&mut self) -> Result<(), AsonError> {
58        self.print_str(DEFAULT_NEWLINE_CHARS)?;
59        for _ in 0..self.indent_level {
60            self.print_str(DEFAULT_INDENT_CHARS)?;
61        }
62        Ok(())
63    }
64
65    fn print_space(&mut self) -> Result<(), AsonError> {
66        self.print_str(" ")?;
67        Ok(())
68    }
69
70    fn print_opening_brace(&mut self) -> Result<(), AsonError> {
71        self.print_str("{")?;
72        self.increase_indent();
73        self.print_newline()?;
74        Ok(())
75    }
76
77    fn print_closing_brace(&mut self) -> Result<(), AsonError> {
78        self.decrease_indent();
79        self.print_newline()?;
80        self.print_str("}")?;
81        Ok(())
82    }
83
84    fn print_opening_bracket(&mut self) -> Result<(), AsonError> {
85        self.print_str("[")?;
86        self.increase_indent();
87        self.print_newline()?;
88        Ok(())
89    }
90
91    fn print_closing_bracket(&mut self) -> Result<(), AsonError> {
92        self.decrease_indent();
93        self.print_newline()?;
94        self.print_str("]")?;
95        Ok(())
96    }
97
98    fn print_opening_parenthesis(&mut self) -> Result<(), AsonError> {
99        self.print_str("(")?;
100        Ok(())
101    }
102
103    fn print_closing_parenthesis(&mut self) -> Result<(), AsonError> {
104        self.print_str(")")?;
105        Ok(())
106    }
107
108    fn print_str(&mut self, s: &str) -> Result<(), AsonError> {
109        self.upstream
110            .write_all(s.as_bytes())
111            .map_err(|e| AsonError::Message(e.to_string()))
112    }
113
114    fn increase_indent(&mut self) {
115        self.indent_level += 1;
116    }
117
118    fn decrease_indent(&mut self) {
119        if self.indent_level > 0 {
120            self.indent_level -= 1;
121        }
122    }
123}
124
125impl<'a, W> ser::Serializer for &mut Serializer<'a, W>
126where
127    W: Write,
128{
129    type Ok = ();
130    type Error = AsonError;
131
132    type SerializeSeq = Self;
133    type SerializeTuple = Self;
134    type SerializeTupleStruct = Self;
135    type SerializeTupleVariant = Self;
136    type SerializeMap = Self;
137    type SerializeStruct = Self;
138    type SerializeStructVariant = Self;
139
140    fn serialize_bool(self, v: bool) -> Result<(), AsonError> {
141        self.print_str(if v { "true" } else { "false" })
142    }
143
144    fn serialize_i8(self, v: i8) -> Result<(), AsonError> {
145        self.print_str(&format!("{}_i8", v))
146    }
147
148    fn serialize_i16(self, v: i16) -> Result<(), AsonError> {
149        self.print_str(&format!("{}_i16", v))
150    }
151
152    fn serialize_i32(self, v: i32) -> Result<(), AsonError> {
153        // `i32` is the default type for integer numbers,
154        // so the suffix `_i32` can be omitted.
155        self.print_str(&format!("{}", v))
156    }
157
158    fn serialize_i64(self, v: i64) -> Result<(), AsonError> {
159        self.print_str(&format!("{}_i64", v))
160    }
161
162    fn serialize_u8(self, v: u8) -> Result<(), AsonError> {
163        self.print_str(&format!("{}_u8", v))
164    }
165
166    fn serialize_u16(self, v: u16) -> Result<(), AsonError> {
167        self.print_str(&format!("{}_u16", v))
168    }
169
170    fn serialize_u32(self, v: u32) -> Result<(), AsonError> {
171        self.print_str(&format!("{}_u32", v))
172    }
173
174    fn serialize_u64(self, v: u64) -> Result<(), AsonError> {
175        self.print_str(&format!("{}_u64", v))
176    }
177
178    fn serialize_f32(self, v: f32) -> Result<(), AsonError> {
179        let str = if v.is_nan() {
180            "NaN_f32".to_owned()
181        } else if v == f32::INFINITY {
182            "Inf_f32".to_owned()
183        } else if v == f32::NEG_INFINITY {
184            "-Inf_f32".to_owned()
185        } else {
186            format!("{}_f32", v)
187        };
188
189        self.print_str(&str)
190    }
191
192    fn serialize_f64(self, v: f64) -> Result<(), AsonError> {
193        // `f64` is the default type for floating-point numbers,
194        // so the suffix `_f64` can be omitted.
195
196        let str = if v.is_nan() {
197            "NaN".to_owned()
198        } else if v == f64::INFINITY {
199            "Inf".to_owned()
200        } else if v == f64::NEG_INFINITY {
201            "-Inf".to_owned()
202        } else {
203            // a decimal point needs to be appended to indicate that it is a floating-point literal
204            // if there is no decimal point.
205            // For example, `3` is an integer literal, while `3.0` is a floating-point literal.
206            let mut s = v.to_string();
207            if !s.contains('.') {
208                s.push_str(".0");
209            }
210            s
211        };
212        self.print_str(&str)
213    }
214
215    fn serialize_char(self, v: char) -> Result<(), AsonError> {
216        // escape single char
217        let str = match v {
218            '\\' => "\\\\".to_owned(),
219            '\'' => "\\'".to_owned(),
220            '\t' => {
221                // horizontal tabulation
222                "\\t".to_owned()
223            }
224            '\r' => {
225                // carriage return, jump to the beginning of the line (CR)
226                "\\r".to_owned()
227            }
228            '\n' => {
229                // new line/line feed (LF)
230                "\\n".to_owned()
231            }
232            '\0' => {
233                // null char
234                "\\0".to_owned()
235            }
236            _ => v.to_string(),
237        };
238
239        self.print_str(&format!("'{}'", str))
240    }
241
242    fn serialize_str(self, v: &str) -> Result<(), AsonError> {
243        let str = v
244            .chars()
245            .map(|c| match c {
246                '\\' => "\\\\".to_owned(),
247                '"' => "\\\"".to_owned(),
248                '\t' => "\\t".to_owned(),
249
250                // null char is allowed in the source code,
251                // it is used to represent the null-terminated string.
252                '\0' => "\\0".to_owned(),
253
254                _ => c.to_string(),
255            })
256            .collect::<Vec<String>>()
257            .join("");
258
259        self.print_str(&format!("\"{}\"", str))
260    }
261
262    /// Format the byte array as a hexadecimal string with the following format:
263    ///
264    /// ```text
265    /// - Each byte is represented as a two-digit hexadecimal number (00 to ff).
266    /// - Bytes are separated by a space.
267    /// - Every 4 bytes, an additional space is added for readability.
268    /// - Every 8 bytes, a newline is added, and the subsequent lines are indented.
269    /// - The entire byte array is enclosed in `h"..."`.
270    ///
271    ///   h"00 11 22 33  44 55 66 77
272    ///     88 99 aa bb  cc dd ee ff"
273    /// ^^^^__ indent
274    /// ```
275    ///
276    /// This format is designed to be human-readable and easy to parse.
277    fn serialize_bytes(self, v: &[u8]) -> Result<(), AsonError> {
278        let leading_space_chars = DEFAULT_INDENT_CHARS.repeat(self.indent_level);
279        let line_separator = format!("\n{}", leading_space_chars);
280        let str = v
281            .chunks(8)
282            .map(|chunk| {
283                // each line
284                chunk
285                    .iter()
286                    .enumerate()
287                    .map(|(idx, byte)| {
288                        // Rust std format!()
289                        // https://doc.rust-lang.org/std/fmt/
290                        if idx == 4 {
291                            format!("  {:02x}", byte)
292                        } else if idx == 0 {
293                            format!("{:02x}", byte)
294                        } else {
295                            format!(" {:02x}", byte)
296                        }
297                    })
298                    .collect::<Vec<String>>()
299                    .join("")
300            })
301            .collect::<Vec<String>>()
302            .join(&line_separator);
303
304        self.print_str(&format!("h\"{}\"", str))
305    }
306
307    fn serialize_none(self) -> Result<(), AsonError> {
308        self.print_str("Option::None")
309    }
310
311    fn serialize_some<T>(self, value: &T) -> Result<(), AsonError>
312    where
313        T: ?Sized + Serialize,
314    {
315        self.print_str("Option::Some")?;
316        self.print_opening_parenthesis()?;
317        value.serialize(&mut *self)?;
318        self.print_closing_parenthesis()?;
319        Ok(())
320    }
321
322    fn serialize_unit(self) -> Result<(), AsonError> {
323        // The type of `()` in Rust.
324        Err(AsonError::Message("Does not support Unit.".to_owned()))
325    }
326
327    fn serialize_unit_struct(self, _name: &'static str) -> Result<(), AsonError> {
328        // A unit struct is a struct that has no fields, for example `struct Unit;`.
329        Err(AsonError::Message(
330            "Does not support \"Unit\" style Struct.".to_owned(),
331        ))
332    }
333
334    fn serialize_unit_variant(
335        self,
336        name: &'static str,
337        _variant_index: u32,
338        variant: &'static str,
339    ) -> Result<(), AsonError> {
340        self.print_str(&format!("{}::{}", name, variant))
341    }
342
343    fn serialize_newtype_struct<T>(self, _name: &'static str, _value: &T) -> Result<(), AsonError>
344    where
345        T: ?Sized + Serialize,
346    {
347        // A newtype struct is a tuple struct with a single field, for example `struct NewType(u8);`.
348        Err(AsonError::Message(
349            "Does not support \"New-Type\" style Struct.".to_owned(),
350        ))
351    }
352
353    fn serialize_newtype_variant<T>(
354        self,
355        name: &'static str,
356        _variant_index: u32,
357        variant: &'static str,
358        value: &T,
359    ) -> Result<(), AsonError>
360    where
361        T: ?Sized + Serialize,
362    {
363        // ```rust
364        // enum Name {
365        //     Variant(type)
366        // }
367        // ```
368
369        self.print_str(&format!("{}::{}", name, variant))?;
370        self.print_opening_parenthesis()?;
371        value.serialize(&mut *self)?;
372        self.print_closing_parenthesis()?;
373        Ok(())
374    }
375
376    fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq, AsonError> {
377        // `[...]`
378        self.print_opening_bracket()?;
379        self.is_first_element = true;
380        // self.newline_separator = true;
381        Ok(self)
382    }
383
384    fn serialize_tuple(self, _len: usize) -> Result<Self::SerializeTuple, AsonError> {
385        // Note that the Rust fixed length arrays
386        // will be treated as tuples, e.g.
387        // [i32; 4]
388        //
389        // per: https://serde.rs/data-model.html
390
391        // `(...)`
392        self.print_opening_parenthesis()?;
393        self.is_first_element = true;
394        // self.newline_separator = false;
395        Ok(self)
396    }
397
398    fn serialize_tuple_struct(
399        self,
400        _name: &'static str,
401        _len: usize,
402    ) -> Result<Self::SerializeTupleStruct, AsonError> {
403        // A tuple struct is a struct that looks like a tuple, for example `struct TupleStruct(u8, String);`.
404        Err(AsonError::Message(
405            "Does not support \"Tuple\" style Struct.".to_owned(),
406        ))
407    }
408
409    fn serialize_tuple_variant(
410        self,
411        name: &'static str,
412        _variant_index: u32,
413        variant: &'static str,
414        _len: usize,
415    ) -> Result<Self::SerializeTupleVariant, AsonError> {
416        // ```rust
417        // enum Name {
418        //     Variant(type, type, ...)
419        // }
420        // ```
421
422        self.print_str(&format!("{}::{}", name, variant))?;
423        self.print_opening_parenthesis()?;
424        self.is_first_element = true;
425        // self.newline_separator = false;
426        Ok(self)
427    }
428
429    fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap, AsonError> {
430        // `[key: value, ...]`
431        self.print_opening_bracket()?;
432        self.is_first_element = true;
433        // self.newline_separator = true;
434        Ok(self)
435    }
436
437    fn serialize_struct(
438        self,
439        _name: &'static str,
440        _len: usize,
441    ) -> Result<Self::SerializeStruct, AsonError> {
442        // `{key: value, ...}`
443        self.print_opening_brace()?;
444        self.is_first_element = true;
445        // self.newline_separator = true;
446        Ok(self)
447    }
448
449    fn serialize_struct_variant(
450        self,
451        name: &'static str,
452        _variant_index: u32,
453        variant: &'static str,
454        _len: usize,
455    ) -> Result<Self::SerializeStructVariant, AsonError> {
456        // ```rust
457        // enum Name {
458        //     Variant{key: value, ...}
459        // }
460        // ```
461
462        self.print_str(&format!("{}::{}", name, variant))?;
463        self.print_opening_brace()?;
464        self.is_first_element = true;
465        // self.newline_separator = true;
466        Ok(self)
467    }
468}
469
470impl<W> ser::SerializeSeq for &mut Serializer<'_, W>
471where
472    W: Write,
473{
474    type Ok = ();
475    type Error = AsonError;
476
477    fn serialize_element<T>(&mut self, value: &T) -> Result<(), AsonError>
478    where
479        T: ?Sized + Serialize,
480    {
481        if self.is_first_element {
482            self.is_first_element = false;
483        } else {
484            self.print_newline()?;
485        }
486
487        value.serialize(&mut **self)
488    }
489
490    fn end(self) -> Result<(), AsonError> {
491        self.print_closing_bracket()
492    }
493}
494
495impl<W> ser::SerializeTuple for &mut Serializer<'_, W>
496where
497    W: Write,
498{
499    type Ok = ();
500    type Error = AsonError;
501
502    fn serialize_element<T>(&mut self, value: &T) -> Result<(), AsonError>
503    where
504        T: ?Sized + Serialize,
505    {
506        if self.is_first_element {
507            self.is_first_element = false;
508        } else {
509            self.print_space()?;
510        }
511
512        value.serialize(&mut **self)
513    }
514
515    fn end(self) -> Result<(), AsonError> {
516        self.print_closing_parenthesis()
517    }
518}
519
520impl<W> ser::SerializeTupleStruct for &mut Serializer<'_, W>
521where
522    W: Write,
523{
524    type Ok = ();
525    type Error = AsonError;
526
527    fn serialize_field<T>(&mut self, _value: &T) -> Result<(), AsonError>
528    where
529        T: ?Sized + Serialize,
530    {
531        unreachable!()
532    }
533
534    fn end(self) -> Result<(), AsonError> {
535        unreachable!()
536    }
537}
538
539impl<W> ser::SerializeTupleVariant for &mut Serializer<'_, W>
540where
541    W: Write,
542{
543    type Ok = ();
544    type Error = AsonError;
545
546    fn serialize_field<T>(&mut self, value: &T) -> Result<(), AsonError>
547    where
548        T: ?Sized + Serialize,
549    {
550        if self.is_first_element {
551            self.is_first_element = false;
552        } else {
553            self.print_space()?;
554        }
555
556        value.serialize(&mut **self)
557    }
558
559    fn end(self) -> Result<(), AsonError> {
560        self.print_closing_parenthesis()
561    }
562}
563
564impl<W> ser::SerializeMap for &mut Serializer<'_, W>
565where
566    W: Write,
567{
568    type Ok = ();
569    type Error = AsonError;
570
571    fn serialize_key<T>(&mut self, key: &T) -> Result<(), AsonError>
572    where
573        T: ?Sized + Serialize,
574    {
575        if self.is_first_element {
576            self.is_first_element = false;
577        } else {
578            self.print_newline()?;
579        }
580
581        key.serialize(&mut **self)
582    }
583
584    fn serialize_value<T>(&mut self, value: &T) -> Result<(), AsonError>
585    where
586        T: ?Sized + Serialize,
587    {
588        self.print_str(": ")?;
589        value.serialize(&mut **self)
590    }
591
592    fn end(self) -> Result<(), AsonError> {
593        self.print_closing_bracket()
594    }
595}
596
597impl<W> ser::SerializeStruct for &mut Serializer<'_, W>
598where
599    W: Write,
600{
601    type Ok = ();
602    type Error = AsonError;
603
604    fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<(), AsonError>
605    where
606        T: ?Sized + Serialize,
607    {
608        if self.is_first_element {
609            self.is_first_element = false;
610        } else {
611            self.print_newline()?;
612        }
613
614        self.print_str(key)?;
615        self.print_str(": ")?;
616        value.serialize(&mut **self)
617    }
618
619    fn end(self) -> Result<(), AsonError> {
620        self.print_closing_brace()
621    }
622}
623
624impl<W> ser::SerializeStructVariant for &mut Serializer<'_, W>
625where
626    W: Write,
627{
628    type Ok = ();
629    type Error = AsonError;
630
631    fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<(), AsonError>
632    where
633        T: ?Sized + Serialize,
634    {
635        if self.is_first_element {
636            self.is_first_element = false;
637        } else {
638            self.print_newline()?;
639        }
640
641        self.print_str(key)?;
642        self.print_str(": ")?;
643        value.serialize(&mut **self)
644    }
645
646    fn end(self) -> Result<(), AsonError> {
647        self.print_closing_brace()
648    }
649}
650
651#[cfg(test)]
652mod tests {
653    use std::collections::HashMap;
654
655    use pretty_assertions::assert_eq;
656    use serde::Serialize;
657    use serde_bytes::ByteBuf;
658
659    use crate::ser::ser_to_string;
660
661    #[test]
662    fn test_primitive_values() {
663        // bool
664        {
665            let v0: bool = false;
666            assert_eq!(ser_to_string(&v0).unwrap(), r#"false"#);
667
668            let v1: bool = true;
669            assert_eq!(ser_to_string(&v1).unwrap(), r#"true"#);
670        }
671
672        // signed integers
673        {
674            let v0: i8 = 11;
675            assert_eq!(ser_to_string(&v0).unwrap(), r#"11_i8"#);
676
677            let v1: i16 = 13;
678            assert_eq!(ser_to_string(&v1).unwrap(), r#"13_i16"#);
679
680            let v2: i32 = 17;
681            assert_eq!(ser_to_string(&v2).unwrap(), r#"17"#);
682
683            let v3: i64 = 19;
684            assert_eq!(ser_to_string(&v3).unwrap(), r#"19_i64"#);
685        }
686
687        // unsigned integers
688        {
689            let v0: u8 = 11;
690            assert_eq!(ser_to_string(&v0).unwrap(), r#"11_u8"#);
691
692            let v1: u16 = 13;
693            assert_eq!(ser_to_string(&v1).unwrap(), r#"13_u16"#);
694
695            let v2: u32 = 17;
696            assert_eq!(ser_to_string(&v2).unwrap(), r#"17_u32"#);
697
698            let v3: u64 = 19;
699            assert_eq!(ser_to_string(&v3).unwrap(), r#"19_u64"#);
700        }
701
702        // floating-point f32
703        {
704            let v0: f32 = 123_f32;
705            assert_eq!(ser_to_string(&v0).unwrap(), r#"123_f32"#);
706
707            let v1: f32 = -4.56_f32;
708            assert_eq!(ser_to_string(&v1).unwrap(), r#"-4.56_f32"#);
709
710            let v2: f32 = std::f32::consts::PI;
711            assert_eq!(ser_to_string(&v2).unwrap(), r#"3.1415927_f32"#);
712
713            let v3: f32 = 0f32;
714            assert_eq!(ser_to_string(&v3).unwrap(), r#"0_f32"#);
715
716            let v4: f32 = -0f32;
717            assert_eq!(ser_to_string(&v4).unwrap(), r#"-0_f32"#);
718
719            assert_eq!(ser_to_string(&f32::NAN).unwrap(), r#"NaN_f32"#);
720            assert_eq!(ser_to_string(&f32::INFINITY).unwrap(), r#"Inf_f32"#);
721            assert_eq!(ser_to_string(&f32::NEG_INFINITY).unwrap(), r#"-Inf_f32"#);
722        }
723
724        // floating-point f64
725        {
726            let v0: f64 = 123_f64;
727            assert_eq!(ser_to_string(&v0).unwrap(), r#"123.0"#);
728
729            let v1: f64 = -4.56_f64;
730            assert_eq!(ser_to_string(&v1).unwrap(), r#"-4.56"#);
731
732            let v2: f64 = std::f64::consts::E;
733            assert_eq!(ser_to_string(&v2).unwrap(), r#"2.718281828459045"#);
734
735            let v3: f64 = 0f64;
736            assert_eq!(ser_to_string(&v3).unwrap(), r#"0.0"#);
737
738            let v4: f64 = -0f64;
739            assert_eq!(ser_to_string(&v4).unwrap(), r#"-0.0"#);
740
741            assert_eq!(ser_to_string(&f64::NAN).unwrap(), r#"NaN"#);
742            assert_eq!(ser_to_string(&f64::INFINITY).unwrap(), r#"Inf"#);
743            assert_eq!(ser_to_string(&f64::NEG_INFINITY).unwrap(), r#"-Inf"#);
744        }
745
746        // char
747        {
748            assert_eq!(ser_to_string(&'a').unwrap(), r#"'a'"#);
749            assert_eq!(ser_to_string(&'文').unwrap(), r#"'文'"#);
750            assert_eq!(ser_to_string(&'🍒').unwrap(), r#"'🍒'"#);
751
752            // escaped characters
753            assert_eq!(ser_to_string(&'\\').unwrap(), r#"'\\'"#);
754            assert_eq!(ser_to_string(&'\'').unwrap(), r#"'\''"#);
755
756            // double quote does not necessary to be escaped
757            assert_eq!(ser_to_string(&'"').unwrap(), r#"'"'"#);
758            assert_eq!(ser_to_string(&'\"').unwrap(), r#"'"'"#);
759
760            assert_eq!(ser_to_string(&'\t').unwrap(), r#"'\t'"#);
761            assert_eq!(ser_to_string(&'\r').unwrap(), r#"'\r'"#);
762            assert_eq!(ser_to_string(&'\n').unwrap(), r#"'\n'"#);
763            assert_eq!(ser_to_string(&'\0').unwrap(), r#"'\0'"#);
764
765            assert_eq!(ser_to_string(&'萱').unwrap(), r#"'萱'"#);
766        }
767
768        // string
769        {
770            assert_eq!(ser_to_string(&"abc文字🍒").unwrap(), r#""abc文字🍒""#);
771            assert_eq!(
772                ser_to_string(&"abc\"\'\\\t\0xyz").unwrap(),
773                r#""abc\"'\\\t\0xyz""#
774            );
775            assert_eq!(
776                ser_to_string(&"hello\r\nworld").unwrap(),
777                "\"hello\r\nworld\""
778            );
779        }
780    }
781
782    #[test]
783    fn test_hexadecimal_byte_data() {
784        let v0 = vec![11u8, 13, 17, 19];
785        let v0b = ByteBuf::from(v0);
786        assert_eq!(ser_to_string(&v0b).unwrap(), r#"h"0b 0d 11 13""#);
787
788        let v1 = b"abc";
789        let v1b = ByteBuf::from(v1);
790        assert_eq!(ser_to_string(&v1b).unwrap(), r#"h"61 62 63""#);
791    }
792
793    #[test]
794    fn test_option() {
795        let v0: Option<i32> = None;
796        assert_eq!(ser_to_string(&v0).unwrap(), r#"Option::None"#);
797
798        let v1: Option<i32> = Some(123);
799        assert_eq!(ser_to_string(&v1).unwrap(), r#"Option::Some(123)"#);
800    }
801
802    #[test]
803    fn test_list() {
804        assert_eq!(
805            ser_to_string(&vec![11, 13, 17, 19]).unwrap(),
806            r#"[
807    11
808    13
809    17
810    19
811]"#
812        );
813
814        assert_eq!(
815            ser_to_string(&"abc".as_bytes()).unwrap(),
816            r#"[
817    97_u8
818    98_u8
819    99_u8
820]"#
821        );
822
823        assert_eq!(
824            ser_to_string(&vec!["foo", "bar", "2024"]).unwrap(),
825            r#"[
826    "foo"
827    "bar"
828    "2024"
829]"#
830        );
831
832        // nested seq
833
834        assert_eq!(
835            ser_to_string(&vec![vec![11, 13], vec![17, 19], vec![23, 29]]).unwrap(),
836            r#"[
837    [
838        11
839        13
840    ]
841    [
842        17
843        19
844    ]
845    [
846        23
847        29
848    ]
849]"#
850        );
851    }
852
853    #[test]
854    fn test_tuple() {
855        assert_eq!(
856            ser_to_string(&(11, 13, 17, 19)).unwrap(),
857            r#"(11 13 17 19)"#
858        );
859
860        // a fixed-length array is treated as tuple
861        assert_eq!(ser_to_string(b"abc").unwrap(), r#"(97_u8 98_u8 99_u8)"#);
862
863        assert_eq!(
864            ser_to_string(&("foo", "bar", "2024")).unwrap(),
865            r#"("foo" "bar" "2024")"#
866        );
867
868        // nested tuple
869        assert_eq!(
870            ser_to_string(&((11, 13), (17, 19), (23, 29))).unwrap(),
871            r#"((11 13) (17 19) (23 29))"#
872        );
873    }
874
875    #[test]
876    fn test_object() {
877        #[derive(Serialize)]
878        struct Object {
879            id: i32,
880            name: String,
881            checked: bool,
882        }
883
884        let v0 = Object {
885            id: 123,
886            name: "foo".to_owned(),
887            checked: true,
888        };
889
890        let expected0 = r#"{
891    id: 123
892    name: "foo"
893    checked: true
894}"#;
895        assert_eq!(ser_to_string(&v0).unwrap(), expected0);
896
897        // nested object
898        #[derive(Serialize)]
899        struct Address {
900            code: i32,
901            city: String,
902        }
903
904        #[derive(Serialize)]
905        struct NestedObject {
906            id: i32,
907            name: String,
908            address: Box<Address>,
909        }
910
911        let v1 = NestedObject {
912            id: 456,
913            name: "bar".to_owned(),
914            address: Box::new(Address {
915                code: 518000,
916                city: "sz".to_owned(),
917            }),
918        };
919
920        let expected1 = r#"{
921    id: 456
922    name: "bar"
923    address: {
924        code: 518000
925        city: "sz"
926    }
927}"#;
928
929        assert_eq!(ser_to_string(&v1).unwrap(), expected1);
930    }
931
932    #[test]
933    fn test_named_list() {
934        let mut m0 = HashMap::<String, String>::new();
935        m0.insert("red".to_owned(), "0xff0000".to_owned());
936        m0.insert("green".to_owned(), "0x00ff00".to_owned());
937        m0.insert("blue".to_owned(), "0x0000ff".to_owned());
938
939        // the order of the key-value pairs in the output string is not guaranteed,
940        // because the `HashMap` does not guarantee the order of the key-value pairs.
941        // so we just check if the output string contains the expected key-value pairs.
942        let s0 = ser_to_string(&m0).unwrap();
943        assert!(s0.starts_with('['));
944        assert!(s0.ends_with(']'));
945        assert!(s0.contains(r#""red": "0xff0000""#));
946        assert!(s0.contains(r#""green": "0x00ff00""#));
947        assert!(s0.contains(r#""blue": "0x0000ff""#));
948
949        let mut m1 = HashMap::<i32, Option<String>>::new();
950        m1.insert(223, Some("hello".to_owned()));
951        m1.insert(227, None);
952        m1.insert(229, Some("world".to_owned()));
953
954        // the order of the key-value pairs in the output string is not guaranteed,
955        // because the `HashMap` does not guarantee the order of the key-value pairs.
956        // so we just check if the output string contains the expected key-value pairs.
957        let s1 = ser_to_string(&m1).unwrap();
958        assert!(s1.starts_with('['));
959        assert!(s1.ends_with(']'));
960        assert!(s1.contains(r#"223: Option::Some("hello")"#));
961        assert!(s1.contains(r#"227: Option::None"#));
962        assert!(s1.contains(r#"229: Option::Some("world")"#));
963    }
964
965    #[test]
966    fn test_enum() {
967        #[derive(Serialize)]
968        enum Color {
969            Red,
970            Green,
971            Blue,
972        }
973
974        let v0 = Color::Red;
975        assert_eq!(ser_to_string(&v0).unwrap(), r#"Color::Red"#);
976
977        let v1 = Color::Green;
978        assert_eq!(ser_to_string(&v1).unwrap(), r#"Color::Green"#);
979
980        let v2 = Color::Blue;
981        assert_eq!(ser_to_string(&v2).unwrap(), r#"Color::Blue"#);
982    }
983
984    #[test]
985    fn test_variant_with_primitive_value() {
986        #[derive(Serialize)]
987        enum Color {
988            Red,
989
990            #[allow(dead_code)]
991            Green,
992            Blue,
993            Grey(u8),
994        }
995
996        {
997            let v0 = Color::Red;
998            assert_eq!(ser_to_string(&v0).unwrap(), r#"Color::Red"#);
999
1000            let v1 = Color::Grey(11);
1001            assert_eq!(ser_to_string(&v1).unwrap(), r#"Color::Grey(11_u8)"#);
1002        }
1003
1004        // nested
1005        #[derive(Serialize)]
1006        enum Apperance {
1007            Transparent,
1008            Color(Color),
1009        }
1010
1011        {
1012            let v0 = Apperance::Transparent;
1013            assert_eq!(ser_to_string(&v0).unwrap(), r#"Apperance::Transparent"#);
1014
1015            let v1 = Apperance::Color(Color::Blue);
1016            assert_eq!(
1017                ser_to_string(&v1).unwrap(),
1018                r#"Apperance::Color(Color::Blue)"#
1019            );
1020
1021            let v2 = Apperance::Color(Color::Grey(13));
1022            assert_eq!(
1023                ser_to_string(&v2).unwrap(),
1024                r#"Apperance::Color(Color::Grey(13_u8))"#
1025            );
1026        }
1027    }
1028
1029    #[test]
1030    fn test_variant_with_list_value() {
1031        #[derive(Serialize)]
1032        enum Item {
1033            Empty,
1034            List(Vec<i32>),
1035        }
1036
1037        assert_eq!(
1038            ser_to_string(&vec![Item::Empty, Item::List(vec![11, 13])]).unwrap(),
1039            r#"[
1040    Item::Empty
1041    Item::List([
1042        11
1043        13
1044    ])
1045]"#
1046        );
1047    }
1048
1049    #[test]
1050    fn test_variant_with_object_value() {
1051        #[derive(Serialize)]
1052        struct Object {
1053            id: i32,
1054            name: String,
1055        }
1056
1057        #[derive(Serialize)]
1058        enum Item {
1059            Empty,
1060            Object(Object),
1061        }
1062
1063        assert_eq!(
1064            ser_to_string(&vec![
1065                Item::Empty,
1066                Item::Object(Object {
1067                    id: 11,
1068                    name: "foo".to_owned()
1069                })
1070            ])
1071            .unwrap(),
1072            r#"[
1073    Item::Empty
1074    Item::Object({
1075        id: 11
1076        name: "foo"
1077    })
1078]"#
1079        );
1080    }
1081
1082    #[test]
1083    fn test_tuple_like_variant() {
1084        #[allow(clippy::upper_case_acronyms)]
1085        #[derive(Serialize)]
1086        enum Color {
1087            Grey(u8),
1088            RGB(u8, u8, u8),
1089        }
1090
1091        assert_eq!(
1092            ser_to_string(&Color::Grey(127)).unwrap(),
1093            r#"Color::Grey(127_u8)"#
1094        );
1095
1096        assert_eq!(
1097            ser_to_string(&Color::RGB(255, 127, 63)).unwrap(),
1098            r#"Color::RGB(255_u8 127_u8 63_u8)"#
1099        );
1100    }
1101
1102    #[test]
1103    fn test_object_like_variant() {
1104        #[derive(Serialize)]
1105        enum Shape {
1106            Circle(i32),
1107            Rect { width: i32, height: i32 },
1108        }
1109
1110        assert_eq!(
1111            ser_to_string(&Shape::Circle(11)).unwrap(),
1112            r#"Shape::Circle(11)"#
1113        );
1114
1115        assert_eq!(
1116            ser_to_string(&Shape::Rect {
1117                width: 200,
1118                height: 100
1119            })
1120            .unwrap(),
1121            r#"Shape::Rect{
1122    width: 200
1123    height: 100
1124}"#
1125        );
1126    }
1127
1128    #[test]
1129    fn test_list_with_tuple_element() {
1130        assert_eq!(
1131            ser_to_string(&vec![(1, "foo"), (2, "bar")]).unwrap(),
1132            r#"[
1133    (1 "foo")
1134    (2 "bar")
1135]"#
1136        );
1137
1138        assert_eq!(
1139            ser_to_string(&(vec![11, 13], vec!["foo", "bar"])).unwrap(),
1140            r#"([
1141    11
1142    13
1143] [
1144    "foo"
1145    "bar"
1146])"#
1147        );
1148    }
1149
1150    #[test]
1151    fn test_list_with_object_elements() {
1152        #[derive(Serialize)]
1153        struct Object {
1154            id: i32,
1155            name: String,
1156        }
1157
1158        assert_eq!(
1159            ser_to_string(&vec![
1160                Object {
1161                    id: 11,
1162                    name: "foo".to_owned()
1163                },
1164                Object {
1165                    id: 13,
1166                    name: "bar".to_owned()
1167                }
1168            ])
1169            .unwrap(),
1170            r#"[
1171    {
1172        id: 11
1173        name: "foo"
1174    }
1175    {
1176        id: 13
1177        name: "bar"
1178    }
1179]"#
1180        );
1181    }
1182
1183    #[test]
1184    fn test_object_with_list_field() {
1185        #[derive(Serialize)]
1186        struct ObjectList {
1187            id: i32,
1188            items: Vec<i32>,
1189        }
1190
1191        assert_eq!(
1192            ser_to_string(&ObjectList {
1193                id: 456,
1194                items: vec![11, 13, 17, 19]
1195            })
1196            .unwrap(),
1197            r#"{
1198    id: 456
1199    items: [
1200        11
1201        13
1202        17
1203        19
1204    ]
1205}"#
1206        );
1207    }
1208
1209    #[test]
1210    fn test_tuple_with_object_elements() {
1211        #[derive(Serialize)]
1212        struct Object {
1213            id: i32,
1214            name: String,
1215        }
1216
1217        assert_eq!(
1218            ser_to_string(&(
1219                123,
1220                Object {
1221                    id: 11,
1222                    name: "foo".to_owned()
1223                }
1224            ))
1225            .unwrap(),
1226            r#"(123 {
1227    id: 11
1228    name: "foo"
1229})"#
1230        );
1231    }
1232
1233    #[test]
1234    fn test_object_with_tuple_field() {
1235        #[derive(Serialize)]
1236        struct ObjectDetail {
1237            id: i32,
1238            address: (i32, String),
1239        }
1240
1241        assert_eq!(
1242            ser_to_string(&ObjectDetail {
1243                id: 456,
1244                address: (11, "sz".to_owned())
1245            })
1246            .unwrap(),
1247            r#"{
1248    id: 456
1249    address: (11 "sz")
1250}"#
1251        );
1252    }
1253}