mason_rs/serde/
ser.rs

1//! Serialize a Rust data structure into MASON data.
2
3use core::fmt;
4use std::fmt::{Display, Write};
5
6use pastey::paste;
7use serde::{
8    Serialize,
9    ser::{self, Error as _, Impossible},
10};
11
12use crate::serialize;
13
14use super::error::{Error, Result};
15
16/// A structure for serializing Rust values into MASON.
17pub struct Serializer<W: Write> {
18    writer: W,
19    depth: usize,
20}
21
22impl<W: Write> Serializer<W> {
23    /// Creates a new MASON serializer.
24    pub fn new(writer: W) -> Self {
25        Self { writer, depth: 0 }
26    }
27}
28
29/// Serialize the given data structure as MASON into the I/O stream.
30///
31/// Serialization guarantees it only feeds valid UTF-8 sequences to the writer.
32///
33/// # Errors
34///
35/// Serialization can fail if `T`'s implementation of `Serialize` decides to
36/// fail, or if `T` contains a map with non-string keys.
37pub fn to_writer<T: Serialize, W: Write>(value: &T, writer: &mut W) -> Result<()> {
38    let mut serializer = Serializer::new(writer);
39    value.serialize(&mut serializer)?;
40    Ok(())
41}
42
43/// Serialize the given data structure as a String of MASON.
44///
45/// # Errors
46///
47/// Serialization can fail if `T`'s implementation of `Serialize` decides to
48/// fail, or if `T` contains a map with non-string keys.
49pub fn to_string<T: Serialize>(value: &T) -> Result<String> {
50    let mut string = String::new();
51    to_writer(value, &mut string)?;
52    Ok(string)
53}
54
55impl<W: Write> Serializer<W> {
56    fn as_compound(&mut self) -> Compound<'_, W> {
57        Compound {
58            serializer: self,
59            first_item: true,
60        }
61    }
62
63    fn write_whitespace(&mut self, depth: usize) -> fmt::Result {
64        if depth == 0 {
65            return Ok(());
66        }
67        write!(self.writer, "{}", "    ".repeat(depth))
68    }
69}
70
71macro_rules! write_displayed {
72    ($type:ty) => {
73        paste! {
74            fn [<serialize_ $type>](self, v: $type) -> Result<()> {
75                Ok(write!(self.writer, "{v}")?)
76            }
77        }
78    };
79}
80
81impl<'s, W: Write> ser::Serializer for &'s mut Serializer<W> {
82    type Ok = ();
83    type Error = Error;
84
85    type SerializeSeq = Compound<'s, W>;
86    type SerializeTuple = Compound<'s, W>;
87    type SerializeTupleStruct = Compound<'s, W>;
88    type SerializeTupleVariant = Compound<'s, W>;
89    type SerializeMap = Compound<'s, W>;
90    type SerializeStruct = Compound<'s, W>;
91    type SerializeStructVariant = Compound<'s, W>;
92
93    write_displayed!(bool);
94
95    // MASON does not distinguish between number types.
96    write_displayed!(i8);
97    write_displayed!(i16);
98    write_displayed!(i32);
99    // It is possible for an i64 to not be representable as f64. It is not invalid
100    // MASON to have a non-f64 number, but most parsers will raise an error when
101    // deserializing such a number. It might be better to raise an error when
102    // serializing instead, but I will leave it like this for now
103    write_displayed!(i64);
104    write_displayed!(u8);
105    write_displayed!(u16);
106    write_displayed!(u32);
107    // This has the same issue as serializing i64.
108    write_displayed!(u64);
109    write_displayed!(f32);
110    write_displayed!(f64);
111
112    fn serialize_char(self, v: char) -> Result<()> {
113        // just serialize the char as a string
114        Ok(serialize::serialize_string(
115            &mut self.writer,
116            v.encode_utf8(&mut [0; 4]),
117        )?)
118    }
119
120    fn serialize_str(self, v: &str) -> Result<()> {
121        Ok(serialize::serialize_string(&mut self.writer, v)?)
122    }
123
124    fn serialize_bytes(self, v: &[u8]) -> Result<()> {
125        Ok(serialize::serialize_bytes(&mut self.writer, v)?)
126    }
127
128    // An absent optional is represented as the MASON `null`.
129    fn serialize_none(self) -> Result<()> {
130        Ok(write!(self.writer, "null")?)
131    }
132
133    // A present optional is represented as just the contained value.
134    fn serialize_some<T>(self, value: &T) -> Result<()>
135    where
136        T: ?Sized + Serialize,
137    {
138        value.serialize(self)
139    }
140
141    // In Serde, unit means an anonymous value containing no data. Map this to
142    // MASON as `null`.
143    fn serialize_unit(self) -> Result<()> {
144        self.serialize_none()
145    }
146
147    // Unit struct means a named value containing no data. Again, since there is
148    // no data, map this to MASON as `null`.
149    fn serialize_unit_struct(self, _name: &'static str) -> Result<()> {
150        self.serialize_none()
151    }
152
153    fn serialize_unit_variant(
154        self,
155        _name: &'static str,
156        _variant_index: u32,
157        variant: &'static str,
158    ) -> Result<()> {
159        Ok(serialize::serialize_key(&mut self.writer, variant)?)
160    }
161
162    fn serialize_newtype_struct<T>(self, _name: &'static str, value: &T) -> Result<()>
163    where
164        T: ?Sized + Serialize,
165    {
166        value.serialize(self)
167    }
168
169    fn serialize_newtype_variant<T>(
170        self,
171        _name: &'static str,
172        _variant_index: u32,
173        variant: &'static str,
174        value: &T,
175    ) -> Result<()>
176    where
177        T: ?Sized + Serialize,
178    {
179        if self.depth != 0 {
180            writeln!(self.writer, "{{\n")?;
181        }
182        serialize::serialize_key(&mut self.writer, variant)?;
183        write!(self.writer, ": ")?;
184        value.serialize(&mut *self)?;
185        if self.depth != 0 {
186            writeln!(self.writer, "\n}}")?;
187        }
188        Ok(())
189    }
190
191    fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq> {
192        write!(self.writer, "[")?;
193        Ok(self.as_compound())
194    }
195
196    // Tuples look just like sequences in MASON.
197    fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple> {
198        self.serialize_seq(Some(len))
199    }
200
201    // Tuple structs look just like sequences in MASON.
202    fn serialize_tuple_struct(
203        self,
204        _name: &'static str,
205        len: usize,
206    ) -> Result<Self::SerializeTupleStruct> {
207        self.serialize_seq(Some(len))
208    }
209
210    // Tuple variants are represented in MASON as `{ NAME: [DATA...] }`.
211    fn serialize_tuple_variant(
212        self,
213        _name: &'static str,
214        _variant_index: u32,
215        variant: &'static str,
216        _len: usize,
217    ) -> Result<Self::SerializeTupleVariant> {
218        if self.depth != 0 {
219            writeln!(self.writer, "{{")?;
220        }
221        serialize::serialize_key(&mut self.writer, variant)?;
222        write!(self.writer, ": [")?;
223        Ok(self.as_compound())
224    }
225
226    // Maps are represented in MASON as `{ K: V, K: V, ... }`.
227    fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap> {
228        if self.depth != 0 {
229            writeln!(self.writer, "{{")?;
230        }
231        Ok(self.as_compound())
232    }
233
234    // Structs look just like maps in MASON.
235    fn serialize_struct(self, _name: &'static str, len: usize) -> Result<Self::SerializeStruct> {
236        self.serialize_map(Some(len))
237    }
238
239    // Struct variants are represented in MASON as `NAME: { K: V, ... }`.
240    fn serialize_struct_variant(
241        self,
242        _name: &'static str,
243        _variant_index: u32,
244        variant: &'static str,
245        _len: usize,
246    ) -> Result<Self::SerializeStructVariant> {
247        if self.depth != 0 {
248            write!(self.writer, "{{")?;
249        };
250        serialize::serialize_key(&mut self.writer, variant)?;
251        writeln!(self.writer, ": {{")?;
252        self.depth += 1;
253        Ok(self.as_compound())
254    }
255}
256
257// Not public API. Should be pub(crate).
258#[doc(hidden)]
259pub struct Compound<'s, W: Write> {
260    serializer: &'s mut Serializer<W>,
261    first_item: bool,
262}
263
264impl<W: Write> Compound<'_, W> {
265    fn write_unless_first_item(&mut self, string: &'static str) -> fmt::Result {
266        if !self.first_item {
267            write!(self.serializer.writer, "{}", string)
268        } else {
269            self.first_item = false;
270            Ok(())
271        }
272    }
273}
274
275impl<W: Write> ser::SerializeSeq for Compound<'_, W> {
276    type Ok = ();
277    type Error = Error;
278
279    fn serialize_element<T>(&mut self, value: &T) -> Result<()>
280    where
281        T: ?Sized + Serialize,
282    {
283        self.write_unless_first_item(", ")?;
284        value.serialize(&mut *self.serializer)
285    }
286
287    fn end(self) -> Result<()> {
288        write!(self.serializer.writer, "]")?;
289        Ok(())
290    }
291}
292
293impl<W: Write> ser::SerializeTuple for Compound<'_, W> {
294    type Ok = ();
295    type Error = Error;
296
297    fn serialize_element<T>(&mut self, value: &T) -> Result<()>
298    where
299        T: ?Sized + Serialize,
300    {
301        <Self as ser::SerializeSeq>::serialize_element(self, value)
302    }
303
304    fn end(self) -> Result<()> {
305        <Self as ser::SerializeSeq>::end(self)
306    }
307}
308
309impl<W: Write> ser::SerializeTupleStruct for Compound<'_, W> {
310    type Ok = ();
311    type Error = Error;
312
313    fn serialize_field<T>(&mut self, value: &T) -> Result<()>
314    where
315        T: ?Sized + Serialize,
316    {
317        <Self as ser::SerializeSeq>::serialize_element(self, value)
318    }
319
320    fn end(self) -> Result<()> {
321        <Self as ser::SerializeSeq>::end(self)
322    }
323}
324
325impl<W: Write> ser::SerializeTupleVariant for Compound<'_, W> {
326    type Ok = ();
327    type Error = Error;
328
329    fn serialize_field<T>(&mut self, value: &T) -> Result<()>
330    where
331        T: ?Sized + Serialize,
332    {
333        <Self as ser::SerializeSeq>::serialize_element(self, value)
334    }
335
336    fn end(self) -> Result<()> {
337        if self.serializer.depth > 0 {
338            // Here we must close the object in addition to the array
339            write!(self.serializer.writer, "]\n}}")?;
340        } else {
341            write!(self.serializer.writer, "]")?;
342        }
343        Ok(())
344    }
345}
346
347impl<W: Write> ser::SerializeMap for Compound<'_, W> {
348    type Ok = ();
349    type Error = Error;
350
351    // MASON only allows string keys so the implementation below will produce invalid
352    // MASON if the key serializes as something other than a string.
353    fn serialize_key<T>(&mut self, key: &T) -> Result<()>
354    where
355        T: ?Sized + Serialize,
356    {
357        self.write_unless_first_item("\n")?;
358        self.serializer.write_whitespace(self.serializer.depth)?;
359        key.serialize(KeySerializer {
360            ser: self.serializer,
361        })
362    }
363
364    fn serialize_value<T>(&mut self, value: &T) -> Result<()>
365    where
366        T: ?Sized + Serialize,
367    {
368        write!(self.serializer.writer, ": ")?;
369        self.serializer.depth += 1;
370        value.serialize(&mut *self.serializer)?;
371        self.serializer.depth -= 1;
372        Ok(())
373    }
374
375    fn end(self) -> Result<()> {
376        if self.serializer.depth > 0 {
377            write!(self.serializer.writer, "\n}}")?;
378        }
379        Ok(())
380    }
381}
382
383impl<W: Write> ser::SerializeStruct for Compound<'_, W> {
384    type Ok = ();
385    type Error = Error;
386
387    fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<()>
388    where
389        T: ?Sized + Serialize,
390    {
391        <Self as ser::SerializeMap>::serialize_key(self, key)?;
392        <Self as ser::SerializeMap>::serialize_value(self, value)
393    }
394
395    fn end(self) -> Result<()> {
396        <Self as ser::SerializeMap>::end(self)
397    }
398}
399
400impl<W: Write> ser::SerializeStructVariant for Compound<'_, W> {
401    type Ok = ();
402    type Error = Error;
403
404    fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<()>
405    where
406        T: ?Sized + Serialize,
407    {
408        <Self as ser::SerializeMap>::serialize_key(self, key)?;
409        <Self as ser::SerializeMap>::serialize_value(self, value)
410    }
411
412    fn end(self) -> Result<()> {
413        if self.serializer.depth > 1 {
414            // here we must close both the inner and outer object
415            write!(self.serializer.writer, "\n}}\n}}")?;
416        } else {
417            write!(self.serializer.writer, "\n}}")?;
418        }
419        self.serializer.depth -= 1;
420        Ok(())
421    }
422}
423
424// A serializer which can only serialize valid keys
425struct KeySerializer<'s, W: Write> {
426    ser: &'s mut Serializer<W>,
427}
428
429impl<W: Write> KeySerializer<'_, W> {
430    // this function does not enforce that value is not a string, but it is only
431    // used for numbers, which are never valid identifiers.
432    fn serialize_non_str_displayable(self, value: impl Display) -> fmt::Result {
433        write!(self.ser.writer, "\"{value}\"")
434    }
435}
436
437impl<W: Write> ser::Serializer for KeySerializer<'_, W> {
438    type Ok = ();
439    type Error = Error;
440
441    #[inline]
442    fn serialize_str(self, value: &str) -> Result<()> {
443        Ok(serialize::serialize_key(&mut self.ser.writer, value)?)
444    }
445
446    #[inline]
447    fn serialize_unit_variant(
448        self,
449        _name: &'static str,
450        _variant_index: u32,
451        variant: &'static str,
452    ) -> Result<()> {
453        Ok(serialize::serialize_key(&mut self.ser.writer, variant)?)
454    }
455
456    #[inline]
457    fn serialize_newtype_struct<T>(self, _name: &'static str, value: &T) -> Result<()>
458    where
459        T: ?Sized + Serialize,
460    {
461        value.serialize(self)
462    }
463
464    type SerializeSeq = Impossible<(), Error>;
465    type SerializeTuple = Impossible<(), Error>;
466    type SerializeTupleStruct = Impossible<(), Error>;
467    type SerializeTupleVariant = Impossible<(), Error>;
468    type SerializeMap = Impossible<(), Error>;
469    type SerializeStruct = Impossible<(), Error>;
470    type SerializeStructVariant = Impossible<(), Error>;
471
472    // a bool is always a valid key
473    fn serialize_bool(self, value: bool) -> Result<()> {
474        self.ser.serialize_bool(value)
475    }
476
477    fn serialize_i8(self, value: i8) -> Result<()> {
478        Ok(self.serialize_non_str_displayable(value)?)
479    }
480
481    fn serialize_i16(self, value: i16) -> Result<()> {
482        Ok(self.serialize_non_str_displayable(value)?)
483    }
484
485    fn serialize_i32(self, value: i32) -> Result<()> {
486        Ok(self.serialize_non_str_displayable(value)?)
487    }
488
489    fn serialize_i64(self, value: i64) -> Result<()> {
490        Ok(self.serialize_non_str_displayable(value)?)
491    }
492
493    fn serialize_i128(self, value: i128) -> Result<()> {
494        Ok(self.serialize_non_str_displayable(value)?)
495    }
496
497    fn serialize_u8(self, value: u8) -> Result<()> {
498        Ok(self.serialize_non_str_displayable(value)?)
499    }
500
501    fn serialize_u16(self, value: u16) -> Result<()> {
502        Ok(self.serialize_non_str_displayable(value)?)
503    }
504
505    fn serialize_u32(self, value: u32) -> Result<()> {
506        Ok(self.serialize_non_str_displayable(value)?)
507    }
508
509    fn serialize_u64(self, value: u64) -> Result<()> {
510        Ok(self.serialize_non_str_displayable(value)?)
511    }
512
513    fn serialize_u128(self, value: u128) -> Result<()> {
514        Ok(self.serialize_non_str_displayable(value)?)
515    }
516
517    fn serialize_f32(self, value: f32) -> Result<()> {
518        Ok(self.serialize_non_str_displayable(value)?)
519    }
520
521    fn serialize_f64(self, value: f64) -> Result<()> {
522        Ok(self.serialize_non_str_displayable(value)?)
523    }
524
525    fn serialize_char(self, value: char) -> Result<()> {
526        self.serialize_str(value.encode_utf8(&mut [0u8; 4]))
527    }
528
529    fn serialize_bytes(self, _value: &[u8]) -> Result<()> {
530        Err(Error::custom("invalid map key: bytes"))
531    }
532
533    fn serialize_unit(self) -> Result<()> {
534        self.serialize_none()
535    }
536
537    fn serialize_unit_struct(self, _name: &'static str) -> Result<()> {
538        self.serialize_none()
539    }
540
541    fn serialize_newtype_variant<T>(
542        self,
543        _name: &'static str,
544        _variant_index: u32,
545        _variant: &'static str,
546        _value: &T,
547    ) -> Result<()>
548    where
549        T: ?Sized + Serialize,
550    {
551        Err(Error::custom("invalid     { key: seq"))
552    }
553
554    // null is a valid key
555    fn serialize_none(self) -> Result<()> {
556        self.ser.serialize_none()
557    }
558
559    fn serialize_some<T>(self, value: &T) -> Result<()>
560    where
561        T: ?Sized + Serialize,
562    {
563        value.serialize(self)
564    }
565
566    fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq> {
567        Err(Error::custom("invalid map key: seq"))
568    }
569
570    fn serialize_tuple(self, _len: usize) -> Result<Self::SerializeTuple> {
571        Err(Error::custom("invalid map key: tuple"))
572    }
573
574    fn serialize_tuple_struct(
575        self,
576        _name: &'static str,
577        _len: usize,
578    ) -> Result<Self::SerializeTupleStruct> {
579        Err(Error::custom("invalid map key: tuple struct"))
580    }
581
582    fn serialize_tuple_variant(
583        self,
584        _name: &'static str,
585        _variant_index: u32,
586        _variant: &'static str,
587        _len: usize,
588    ) -> Result<Self::SerializeTupleVariant> {
589        Err(Error::custom("invalid map key: tuple variant"))
590    }
591
592    fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap> {
593        Err(Error::custom("invalid map key: map"))
594    }
595
596    fn serialize_struct(self, _name: &'static str, _len: usize) -> Result<Self::SerializeStruct> {
597        Err(Error::custom("invalid map key: struct"))
598    }
599
600    fn serialize_struct_variant(
601        self,
602        _name: &'static str,
603        _variant_index: u32,
604        _variant: &'static str,
605        _len: usize,
606    ) -> Result<Self::SerializeStructVariant> {
607        Err(Error::custom("invalid map key: struct_variant"))
608    }
609
610    fn collect_str<T>(self, value: &T) -> Result<()>
611    where
612        T: ?Sized + Display,
613    {
614        self.ser.collect_str(value)
615    }
616}
617
618#[cfg(test)]
619mod tests {
620    use std::collections::HashMap;
621
622    use super::*;
623
624    #[test]
625    fn test_struct() {
626        #[derive(Serialize)]
627        struct Test {
628            int: u32,
629            seq: Vec<&'static str>,
630        }
631
632        let test = Test {
633            int: 1,
634            seq: vec!["a", "b"],
635        };
636        let expected = "\
637int: 1
638seq: [\"a\", \"b\"]";
639        assert_eq!(to_string(&test).unwrap(), expected);
640    }
641
642    #[test]
643    fn test_enum() {
644        #[derive(Serialize)]
645        enum E {
646            Unit,
647            Newtype(u32),
648            Tuple(u32, u32),
649            Struct { a: u32 },
650        }
651
652        let u = E::Unit;
653        let expected = r#"Unit"#;
654        assert_eq!(to_string(&u).unwrap(), expected);
655
656        let n = E::Newtype(1);
657        let expected = r#"Newtype: 1"#;
658        assert_eq!(to_string(&n).unwrap(), expected);
659
660        let t = E::Tuple(1, 2);
661        let expected = r#"Tuple: [1, 2]"#;
662        assert_eq!(to_string(&t).unwrap(), expected);
663
664        let s = E::Struct { a: 1 };
665        let expected = "\
666Struct: {
667    a: 1
668}";
669        assert_eq!(to_string(&s).unwrap(), expected);
670    }
671
672    #[test]
673    fn test_complicated() {
674        #[derive(Serialize)]
675        struct Complicated {
676            map: HashMap<String, Vec<f32>>,
677            bytes: &'static [u8],
678            option: Option<String>,
679            nothing: (),
680        }
681
682        let complicated = Complicated {
683            map: HashMap::from([
684                ("simple-key".into(), vec![1.0, 999.0, 1.2345]),
685                (
686                    "a \" \\ \\\" difficult key 🏳️‍⚧️".into(),
687                    vec![-1e9, 1.23e3, 3.21e-10],
688                ),
689            ]),
690            bytes: b"Bytes!",
691            option: None,
692            nothing: (),
693        };
694
695        let simple_key = "simple-key: [1, 999, 1.2345]";
696        let difficult_key =
697            r#""a \" \\ \\\" difficult key 🏳️‍⚧️": [-1000000000, 1230, 0.000000000321]"#;
698
699        // the order of hash map items is random
700        let first_key = complicated.map.keys().next().unwrap();
701        let map_str = if first_key == "simple-key" {
702            format!("{{\n    {}\n    {}\n}}", simple_key, difficult_key)
703        } else {
704            format!("{{\n    {}\n    {}\n}}", difficult_key, simple_key)
705        };
706
707        let expected = "\
708map: <map>
709bytes: [66, 121, 116, 101, 115, 33]
710option: null
711nothing: null"
712            .replace("<map>", &map_str);
713        let got = to_string(&complicated).unwrap();
714        if expected != got {
715            panic!(
716                "assertion `left == right` failed\n left:\n{}\n\nright:\n{}",
717                expected, got
718            )
719        }
720    }
721}