quick_xml/se/
content.rs

1//! Contains serializer for content of an XML element
2
3use crate::de::TEXT_KEY;
4use crate::errors::serialize::DeError;
5use crate::se::element::{ElementSerializer, Struct, Tuple};
6use crate::se::simple_type::{QuoteTarget, SimpleTypeSerializer};
7use crate::se::{Indent, QuoteLevel, XmlName};
8use serde::ser::{
9    Impossible, Serialize, SerializeSeq, SerializeTuple, SerializeTupleStruct, Serializer,
10};
11use serde::serde_if_integer128;
12use std::fmt::Write;
13
14macro_rules! write_primitive {
15    ($method:ident ( $ty:ty )) => {
16        #[inline]
17        fn $method(self, value: $ty) -> Result<Self::Ok, Self::Error> {
18            self.into_simple_type_serializer().$method(value)?;
19            Ok(())
20        }
21    };
22}
23
24////////////////////////////////////////////////////////////////////////////////////////////////////
25
26/// A serializer used to serialize content of an element. It does not write
27/// surrounding tags. Unlike the [`ElementSerializer`], this serializer serializes
28/// enums using variant names as tag names, i. e. as `<variant>...</variant>`
29///
30/// This serializer does the following:
31/// - numbers converted to a decimal representation and serialized as naked strings;
32/// - booleans serialized ether as `"true"` or `"false"`;
33/// - strings and characters are serialized as naked strings;
34/// - `None` does not write anything;
35/// - `Some` and newtypes are serialized as an inner type using the same serializer;
36/// - units (`()`) and unit structs does not write anything;
37/// - sequences, tuples and tuple structs are serialized without delimiters.
38///   `[1, 2, 3]` would be serialized as `123` (if not using indent);
39/// - structs and maps are not supported ([`DeError::Unsupported`] is returned);
40/// - enums:
41///   - unit variants are serialized as self-closed `<variant/>`;
42///   - newtype variants are serialized as inner value wrapped in `<variant>...</variant>`;
43///   - tuple variants are serialized as sequences where each element is wrapped
44///     in `<variant>...</variant>`;
45///   - struct variants are serialized as a sequence of fields wrapped in
46///     `<variant>...</variant>`. Each field is serialized recursively using
47///     either [`ElementSerializer`], `ContentSerializer` (`$value` fields), or
48///     [`SimpleTypeSerializer`] (`$text` fields). In particular, the empty struct
49///     is serialized as `<variant/>`;
50///
51/// Usage of empty tags depends on the [`Self::expand_empty_elements`] setting.
52///
53/// The difference between this serializer and [`SimpleTypeSerializer`] is in how
54/// sequences and maps are serialized. Unlike `SimpleTypeSerializer` it supports
55/// any types in sequences and serializes them as list of elements, but that has
56/// drawbacks. Sequence of primitives would be serialized without delimiters and
57/// it will be impossible to distinguish between them. Even worse, when serializing
58/// with indent, sequence of strings become one big string with additional content
59/// and it would be impossible to distinguish between content of the original
60/// strings and inserted indent characters.
61pub struct ContentSerializer<'w, 'i, W: Write> {
62    pub writer: &'w mut W,
63    /// Defines which XML characters need to be escaped in text content
64    pub level: QuoteLevel,
65    /// Current indentation level. Note, that `Indent::None` means that there is
66    /// no indentation at all, but `write_indent == false` means only, that indent
67    /// writing is disabled in this instantiation of `ContentSerializer`, but
68    /// child serializers should have access to the actual state of indentation.
69    pub(super) indent: Indent<'i>,
70    /// If `true`, then current indent will be written before writing the content,
71    /// but only if content is not empty.
72    pub write_indent: bool,
73    // If `true`, then empty elements will be serialized as `<element></element>`
74    // instead of `<element/>`.
75    pub expand_empty_elements: bool,
76    //TODO: add settings to disallow consequent serialization of primitives
77}
78
79impl<'w, 'i, W: Write> ContentSerializer<'w, 'i, W> {
80    /// Turns this serializer into serializer of a text content
81    #[inline]
82    pub fn into_simple_type_serializer(self) -> SimpleTypeSerializer<'i, &'w mut W> {
83        //TODO: Customization point: choose between CDATA and Text representation
84        SimpleTypeSerializer {
85            writer: self.writer,
86            target: QuoteTarget::Text,
87            level: self.level,
88            indent: if self.write_indent {
89                self.indent
90            } else {
91                Indent::None
92            },
93        }
94    }
95
96    /// Creates new serializer that shares state with this serializer and
97    /// writes to the same underlying writer
98    #[inline]
99    pub fn new_seq_element_serializer(&mut self) -> ContentSerializer<W> {
100        ContentSerializer {
101            writer: self.writer,
102            level: self.level,
103            indent: self.indent.borrow(),
104            write_indent: self.write_indent,
105            expand_empty_elements: self.expand_empty_elements,
106        }
107    }
108
109    /// Writes `name` as self-closed tag
110    #[inline]
111    pub(super) fn write_empty(mut self, name: XmlName) -> Result<(), DeError> {
112        self.write_indent()?;
113        if self.expand_empty_elements {
114            self.writer.write_char('<')?;
115            self.writer.write_str(name.0)?;
116            self.writer.write_str("></")?;
117            self.writer.write_str(name.0)?;
118            self.writer.write_char('>')?;
119        } else {
120            self.writer.write_str("<")?;
121            self.writer.write_str(name.0)?;
122            self.writer.write_str("/>")?;
123        }
124        Ok(())
125    }
126
127    /// Writes simple type content between `name` tags
128    pub(super) fn write_wrapped<S>(mut self, name: XmlName, serialize: S) -> Result<(), DeError>
129    where
130        S: for<'a> FnOnce(SimpleTypeSerializer<'i, &'a mut W>) -> Result<&'a mut W, DeError>,
131    {
132        self.write_indent()?;
133        self.writer.write_char('<')?;
134        self.writer.write_str(name.0)?;
135        self.writer.write_char('>')?;
136
137        let writer = serialize(self.into_simple_type_serializer())?;
138
139        writer.write_str("</")?;
140        writer.write_str(name.0)?;
141        writer.write_char('>')?;
142        Ok(())
143    }
144
145    pub(super) fn write_indent(&mut self) -> Result<(), DeError> {
146        if self.write_indent {
147            self.indent.write_indent(&mut self.writer)?;
148            self.write_indent = false;
149        }
150        Ok(())
151    }
152}
153
154impl<'w, 'i, W: Write> Serializer for ContentSerializer<'w, 'i, W> {
155    type Ok = ();
156    type Error = DeError;
157
158    type SerializeSeq = Self;
159    type SerializeTuple = Self;
160    type SerializeTupleStruct = Self;
161    type SerializeTupleVariant = Tuple<'w, 'i, W>;
162    type SerializeMap = Impossible<Self::Ok, Self::Error>;
163    type SerializeStruct = Impossible<Self::Ok, Self::Error>;
164    type SerializeStructVariant = Struct<'w, 'i, W>;
165
166    write_primitive!(serialize_bool(bool));
167
168    write_primitive!(serialize_i8(i8));
169    write_primitive!(serialize_i16(i16));
170    write_primitive!(serialize_i32(i32));
171    write_primitive!(serialize_i64(i64));
172
173    write_primitive!(serialize_u8(u8));
174    write_primitive!(serialize_u16(u16));
175    write_primitive!(serialize_u32(u32));
176    write_primitive!(serialize_u64(u64));
177
178    serde_if_integer128! {
179        write_primitive!(serialize_i128(i128));
180        write_primitive!(serialize_u128(u128));
181    }
182
183    write_primitive!(serialize_f32(f32));
184    write_primitive!(serialize_f64(f64));
185
186    write_primitive!(serialize_char(char));
187    write_primitive!(serialize_bytes(&[u8]));
188
189    #[inline]
190    fn serialize_str(self, value: &str) -> Result<Self::Ok, Self::Error> {
191        if !value.is_empty() {
192            self.into_simple_type_serializer().serialize_str(value)?;
193        }
194        Ok(())
195    }
196
197    /// Does not write anything
198    #[inline]
199    fn serialize_none(self) -> Result<Self::Ok, Self::Error> {
200        Ok(())
201    }
202
203    fn serialize_some<T: ?Sized + Serialize>(self, value: &T) -> Result<Self::Ok, Self::Error> {
204        value.serialize(self)
205    }
206
207    /// Does not write anything
208    #[inline]
209    fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
210        Ok(())
211    }
212
213    /// Does not write anything
214    #[inline]
215    fn serialize_unit_struct(self, _name: &'static str) -> Result<Self::Ok, Self::Error> {
216        Ok(())
217    }
218
219    /// If `variant` is a special `$text` variant, then do nothing, otherwise
220    /// checks `variant` for XML name validity and writes `<variant/>`.
221    fn serialize_unit_variant(
222        self,
223        _name: &'static str,
224        _variant_index: u32,
225        variant: &'static str,
226    ) -> Result<Self::Ok, Self::Error> {
227        if variant == TEXT_KEY {
228            Ok(())
229        } else {
230            let name = XmlName::try_from(variant)?;
231            self.write_empty(name)
232        }
233    }
234
235    fn serialize_newtype_struct<T: ?Sized + Serialize>(
236        self,
237        _name: &'static str,
238        value: &T,
239    ) -> Result<Self::Ok, Self::Error> {
240        value.serialize(self)
241    }
242
243    /// If `variant` is a special `$text` variant, then writes `value` as a `xs:simpleType`,
244    /// otherwise checks `variant` for XML name validity and writes `value` as a new
245    /// `<variant>` element.
246    fn serialize_newtype_variant<T: ?Sized + Serialize>(
247        self,
248        _name: &'static str,
249        _variant_index: u32,
250        variant: &'static str,
251        value: &T,
252    ) -> Result<Self::Ok, Self::Error> {
253        if variant == TEXT_KEY {
254            value.serialize(self.into_simple_type_serializer())?;
255            Ok(())
256        } else {
257            value.serialize(ElementSerializer {
258                key: XmlName::try_from(variant)?,
259                ser: self,
260            })
261        }
262    }
263
264    #[inline]
265    fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> {
266        Ok(self)
267    }
268
269    #[inline]
270    fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple, Self::Error> {
271        self.serialize_seq(Some(len))
272    }
273
274    #[inline]
275    fn serialize_tuple_struct(
276        self,
277        _name: &'static str,
278        len: usize,
279    ) -> Result<Self::SerializeTupleStruct, Self::Error> {
280        self.serialize_tuple(len)
281    }
282
283    /// Serializes variant as a tuple with name `variant`, producing
284    ///
285    /// ```xml
286    /// <variant><!-- 1st element of a tuple --></variant>
287    /// <variant><!-- 2nd element of a tuple --></variant>
288    /// <!-- ... -->
289    /// <variant><!-- Nth element of a tuple --></variant>
290    /// ```
291    #[inline]
292    fn serialize_tuple_variant(
293        self,
294        name: &'static str,
295        _variant_index: u32,
296        variant: &'static str,
297        len: usize,
298    ) -> Result<Self::SerializeTupleVariant, Self::Error> {
299        if variant == TEXT_KEY {
300            self.into_simple_type_serializer()
301                .serialize_tuple_struct(name, len)
302                .map(Tuple::Text)
303        } else {
304            let ser = ElementSerializer {
305                key: XmlName::try_from(variant)?,
306                ser: self,
307            };
308            ser.serialize_tuple_struct(name, len).map(Tuple::Element)
309        }
310    }
311
312    fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
313        Err(DeError::Unsupported(
314            format!("serialization of map types is not supported in `$value` field").into(),
315        ))
316    }
317
318    #[inline]
319    fn serialize_struct(
320        self,
321        name: &'static str,
322        _len: usize,
323    ) -> Result<Self::SerializeStruct, Self::Error> {
324        Err(DeError::Unsupported(
325            format!("serialization of struct `{name}` is not supported in `$value` field").into(),
326        ))
327    }
328
329    /// Serializes variant as an element with name `variant`, producing
330    ///
331    /// ```xml
332    /// <variant>
333    ///   <!-- struct fields... -->
334    /// </variant>
335    /// ```
336    ///
337    /// If struct has no fields which is represented by nested elements or a text,
338    /// it may be serialized as self-closed element `<variant/>`.
339    #[inline]
340    fn serialize_struct_variant(
341        self,
342        name: &'static str,
343        _variant_index: u32,
344        variant: &'static str,
345        len: usize,
346    ) -> Result<Self::SerializeStructVariant, Self::Error> {
347        if variant == TEXT_KEY {
348            Err(DeError::Unsupported(
349                format!("cannot serialize `$text` struct variant of `{}` enum", name).into(),
350            ))
351        } else {
352            let ser = ElementSerializer {
353                key: XmlName::try_from(variant)?,
354                ser: self,
355            };
356            ser.serialize_struct(name, len)
357        }
358    }
359}
360
361impl<'w, 'i, W: Write> SerializeSeq for ContentSerializer<'w, 'i, W> {
362    type Ok = ();
363    type Error = DeError;
364
365    fn serialize_element<T>(&mut self, value: &T) -> Result<(), Self::Error>
366    where
367        T: ?Sized + Serialize,
368    {
369        value.serialize(self.new_seq_element_serializer())?;
370        // Write indent for next element
371        self.write_indent = true;
372        Ok(())
373    }
374
375    #[inline]
376    fn end(self) -> Result<Self::Ok, Self::Error> {
377        Ok(())
378    }
379}
380
381impl<'w, 'i, W: Write> SerializeTuple for ContentSerializer<'w, 'i, W> {
382    type Ok = ();
383    type Error = DeError;
384
385    #[inline]
386    fn serialize_element<T>(&mut self, value: &T) -> Result<(), Self::Error>
387    where
388        T: ?Sized + Serialize,
389    {
390        SerializeSeq::serialize_element(self, value)
391    }
392
393    #[inline]
394    fn end(self) -> Result<Self::Ok, Self::Error> {
395        SerializeSeq::end(self)
396    }
397}
398
399impl<'w, 'i, W: Write> SerializeTupleStruct for ContentSerializer<'w, 'i, W> {
400    type Ok = ();
401    type Error = DeError;
402
403    #[inline]
404    fn serialize_field<T>(&mut self, value: &T) -> Result<(), Self::Error>
405    where
406        T: ?Sized + Serialize,
407    {
408        SerializeSeq::serialize_element(self, value)
409    }
410
411    #[inline]
412    fn end(self) -> Result<Self::Ok, Self::Error> {
413        SerializeSeq::end(self)
414    }
415}
416
417////////////////////////////////////////////////////////////////////////////////////////////////////
418
419/// Make tests public to reuse types in `elements::tests` module
420#[cfg(test)]
421pub(super) mod tests {
422    use super::*;
423    use crate::utils::Bytes;
424    use serde::Serialize;
425    use std::collections::BTreeMap;
426
427    #[derive(Debug, Serialize, PartialEq)]
428    pub struct Unit;
429
430    #[derive(Debug, Serialize, PartialEq)]
431    #[serde(rename = "<\"&'>")]
432    pub struct UnitEscaped;
433
434    #[derive(Debug, Serialize, PartialEq)]
435    pub struct Newtype(pub usize);
436
437    #[derive(Debug, Serialize, PartialEq)]
438    pub struct Tuple(pub &'static str, pub usize);
439
440    #[derive(Debug, Serialize, PartialEq)]
441    pub struct Struct {
442        pub key: &'static str,
443        pub val: (usize, usize),
444    }
445
446    /// Struct with a special `$text` field
447    #[derive(Debug, Serialize, PartialEq)]
448    pub struct Text<T> {
449        pub before: &'static str,
450        #[serde(rename = "$text")]
451        pub content: T,
452        pub after: &'static str,
453    }
454
455    /// Struct with a special `$value` field
456    #[derive(Debug, Serialize, PartialEq)]
457    pub struct Value<T> {
458        pub before: &'static str,
459        #[serde(rename = "$value")]
460        pub content: T,
461        pub after: &'static str,
462    }
463
464    /// Attributes identified by starting with `@` character
465    #[derive(Debug, Serialize, PartialEq)]
466    pub struct Attributes {
467        #[serde(rename = "@key")]
468        pub key: &'static str,
469        #[serde(rename = "@val")]
470        pub val: (usize, usize),
471    }
472    #[derive(Debug, Serialize, PartialEq)]
473    pub struct AttributesBefore {
474        #[serde(rename = "@key")]
475        pub key: &'static str,
476        pub val: usize,
477    }
478    #[derive(Debug, Serialize, PartialEq)]
479    pub struct AttributesAfter {
480        pub key: &'static str,
481        #[serde(rename = "@val")]
482        pub val: usize,
483    }
484
485    #[derive(Debug, Serialize, PartialEq)]
486    pub enum Enum {
487        Unit,
488        /// Variant name becomes a tag name, but the name of variant is invalid
489        /// XML name. Serialization of this element should be forbidden
490        #[serde(rename = "<\"&'>")]
491        UnitEscaped,
492        Newtype(usize),
493        Tuple(&'static str, usize),
494        Struct {
495            key: &'static str,
496            /// Should be serialized as elements
497            val: (usize, usize),
498        },
499        Attributes {
500            #[serde(rename = "@key")]
501            key: &'static str,
502            #[serde(rename = "@val")]
503            val: (usize, usize),
504        },
505        AttributesBefore {
506            #[serde(rename = "@key")]
507            key: &'static str,
508            val: usize,
509        },
510        AttributesAfter {
511            key: &'static str,
512            #[serde(rename = "@val")]
513            val: usize,
514        },
515    }
516
517    #[derive(Debug, Serialize, PartialEq)]
518    pub enum SpecialEnum<T> {
519        /// Struct variant with a special `$text` field
520        Text {
521            before: &'static str,
522            #[serde(rename = "$text")]
523            content: T,
524            after: &'static str,
525        },
526        /// Struct variant with a special `$value` field
527        Value {
528            before: &'static str,
529            #[serde(rename = "$value")]
530            content: T,
531            after: &'static str,
532        },
533    }
534
535    mod without_indent {
536        use super::Struct;
537        use super::*;
538        use pretty_assertions::assert_eq;
539
540        /// Checks that given `$data` successfully serialized as `$expected`
541        macro_rules! serialize_as {
542            ($name:ident: $data:expr => $expected:expr) => {
543                #[test]
544                fn $name() {
545                    let mut buffer = String::new();
546                    let ser = ContentSerializer {
547                        writer: &mut buffer,
548                        level: QuoteLevel::Full,
549                        indent: Indent::None,
550                        write_indent: false,
551                        expand_empty_elements: false,
552                    };
553
554                    $data.serialize(ser).unwrap();
555                    assert_eq!(buffer, $expected);
556                }
557            };
558        }
559
560        /// Checks that attempt to serialize given `$data` results to a
561        /// serialization error `$kind` with `$reason`
562        macro_rules! err {
563            ($name:ident: $data:expr => $kind:ident($reason:literal)) => {
564                #[test]
565                fn $name() {
566                    let mut buffer = String::new();
567                    let ser = ContentSerializer {
568                        writer: &mut buffer,
569                        level: QuoteLevel::Full,
570                        indent: Indent::None,
571                        write_indent: false,
572                        expand_empty_elements: false,
573                    };
574
575                    match $data.serialize(ser).unwrap_err() {
576                        DeError::$kind(e) => assert_eq!(e, $reason),
577                        e => panic!(
578                            "Expected `{}({})`, found `{:?}`",
579                            stringify!($kind),
580                            $reason,
581                            e
582                        ),
583                    }
584                    // We could write something before fail
585                    // assert_eq!(buffer, "");
586                }
587            };
588        }
589
590        // Primitives is serialized in the same way as for SimpleTypeSerializer
591        serialize_as!(false_: false => "false");
592        serialize_as!(true_:  true  => "true");
593
594        serialize_as!(i8_:    -42i8                => "-42");
595        serialize_as!(i16_:   -4200i16             => "-4200");
596        serialize_as!(i32_:   -42000000i32         => "-42000000");
597        serialize_as!(i64_:   -42000000000000i64   => "-42000000000000");
598        serialize_as!(isize_: -42000000000000isize => "-42000000000000");
599
600        serialize_as!(u8_:    42u8                => "42");
601        serialize_as!(u16_:   4200u16             => "4200");
602        serialize_as!(u32_:   42000000u32         => "42000000");
603        serialize_as!(u64_:   42000000000000u64   => "42000000000000");
604        serialize_as!(usize_: 42000000000000usize => "42000000000000");
605
606        serde_if_integer128! {
607            serialize_as!(i128_: -420000000000000000000000000000i128 => "-420000000000000000000000000000");
608            serialize_as!(u128_:  420000000000000000000000000000u128 => "420000000000000000000000000000");
609        }
610
611        serialize_as!(f32_: 4.2f32 => "4.2");
612        serialize_as!(f64_: 4.2f64 => "4.2");
613
614        serialize_as!(char_non_escaped: 'h' => "h");
615        serialize_as!(char_lt:   '<' => "&lt;");
616        serialize_as!(char_gt:   '>' => "&gt;");
617        serialize_as!(char_amp:  '&' => "&amp;");
618        serialize_as!(char_apos: '\'' => "&apos;");
619        serialize_as!(char_quot: '"' => "&quot;");
620        //TODO: add a setting to escape leading/trailing spaces, in order to
621        // pretty-print does not change the content
622        serialize_as!(char_space: ' ' => " ");
623
624        serialize_as!(str_non_escaped: "non-escaped string" => "non-escaped string");
625        serialize_as!(str_escaped: "<\"escaped & string'>" => "&lt;&quot;escaped &amp; string&apos;&gt;");
626
627        err!(bytes: Bytes(b"<\"escaped & bytes'>") => Unsupported("`serialize_bytes` not supported yet"));
628
629        serialize_as!(option_none: Option::<Enum>::None => "");
630        serialize_as!(option_some: Some("non-escaped string") => "non-escaped string");
631        serialize_as!(option_some_empty_str: Some("") => "");
632
633        serialize_as!(unit: () => "");
634        serialize_as!(unit_struct: Unit => "");
635        serialize_as!(unit_struct_escaped: UnitEscaped => "");
636
637        // Unlike SimpleTypeSerializer, enumeration values serialized as tags
638        serialize_as!(enum_unit: Enum::Unit => "<Unit/>");
639        err!(enum_unit_escaped: Enum::UnitEscaped
640            => Unsupported("character `<` is not allowed at the start of an XML name `<\"&'>`"));
641
642        // Newtypes recursively applies ContentSerializer
643        serialize_as!(newtype: Newtype(42) => "42");
644        serialize_as!(enum_newtype: Enum::Newtype(42) => "<Newtype>42</Newtype>");
645
646        // Note that sequences of primitives serialized without delimiters!
647        serialize_as!(seq: vec![1, 2, 3] => "123");
648        serialize_as!(seq_empty: Vec::<usize>::new() => "");
649        serialize_as!(tuple: ("<\"&'>", "with\t\r\n spaces", 3usize)
650            => "&lt;&quot;&amp;&apos;&gt;\
651                with\t\r\n spaces\
652                3");
653        serialize_as!(tuple_struct: Tuple("first", 42)
654            => "first\
655                42");
656        serialize_as!(enum_tuple: Enum::Tuple("first", 42)
657            => "<Tuple>first</Tuple>\
658                <Tuple>42</Tuple>");
659
660        // Structured types cannot be serialized without surrounding tag, which
661        // only `enum` can provide
662        err!(map: BTreeMap::from([("_1", 2), ("_3", 4)])
663            => Unsupported("serialization of map types is not supported in `$value` field"));
664        err!(struct_: Struct { key: "answer", val: (42, 42) }
665            => Unsupported("serialization of struct `Struct` is not supported in `$value` field"));
666        serialize_as!(enum_struct: Enum::Struct { key: "answer", val: (42, 42) }
667            => "<Struct>\
668                    <key>answer</key>\
669                    <val>42</val>\
670                    <val>42</val>\
671                </Struct>");
672
673        /// Special field name `$text` should be serialized as a text content
674        mod text_field {
675            use super::*;
676            use pretty_assertions::assert_eq;
677
678            err!(map: BTreeMap::from([("$text", 2), ("_3", 4)])
679                => Unsupported("serialization of map types is not supported in `$value` field"));
680            err!(struct_:
681                Text {
682                    before: "answer",
683                    content: (42, 42),
684                    after: "answer",
685                }
686                => Unsupported("serialization of struct `Text` is not supported in `$value` field"));
687            serialize_as!(enum_struct:
688                SpecialEnum::Text {
689                    before: "answer",
690                    content: (42, 42),
691                    after: "answer",
692                }
693                => "<Text>\
694                        <before>answer</before>\
695                        42 42\
696                        <after>answer</after>\
697                    </Text>");
698        }
699
700        /// `$text` field inside a struct variant of an enum
701        mod enum_with_text_field {
702            use super::*;
703            use pretty_assertions::assert_eq;
704
705            macro_rules! text {
706                ($name:ident: $data:expr => $expected:literal) => {
707                    serialize_as!($name:
708                        SpecialEnum::Text {
709                            before: "answer",
710                            content: $data,
711                            after: "answer",
712                        }
713                        => concat!(
714                            "<Text><before>answer</before>",
715                            $expected,
716                            "<after>answer</after></Text>",
717                        ));
718                };
719            }
720
721            text!(false_: false => "false");
722            text!(true_:  true  => "true");
723
724            text!(i8_:    -42i8                => "-42");
725            text!(i16_:   -4200i16             => "-4200");
726            text!(i32_:   -42000000i32         => "-42000000");
727            text!(i64_:   -42000000000000i64   => "-42000000000000");
728            text!(isize_: -42000000000000isize => "-42000000000000");
729
730            text!(u8_:    42u8                => "42");
731            text!(u16_:   4200u16             => "4200");
732            text!(u32_:   42000000u32         => "42000000");
733            text!(u64_:   42000000000000u64   => "42000000000000");
734            text!(usize_: 42000000000000usize => "42000000000000");
735
736            serde_if_integer128! {
737                text!(i128_: -420000000000000000000000000000i128 => "-420000000000000000000000000000");
738                text!(u128_:  420000000000000000000000000000u128 => "420000000000000000000000000000");
739            }
740
741            text!(f32_: 4.2f32 => "4.2");
742            text!(f64_: 4.2f64 => "4.2");
743
744            text!(char_non_escaped: 'h' => "h");
745            text!(char_lt:   '<' => "&lt;");
746            text!(char_gt:   '>' => "&gt;");
747            text!(char_amp:  '&' => "&amp;");
748            text!(char_apos: '\'' => "&apos;");
749            text!(char_quot: '"' => "&quot;");
750            //TODO: add a setting to escape leading/trailing spaces, in order to
751            // pretty-print does not change the content
752            text!(char_space: ' ' => " ");
753
754            text!(str_non_escaped: "non-escaped string" => "non-escaped string");
755            text!(str_escaped: "<\"escaped & string'>" => "&lt;&quot;escaped &amp; string&apos;&gt;");
756
757            err!(bytes:
758                SpecialEnum::Text {
759                    before: "answer",
760                    content: Bytes(b"<\"escaped & bytes'>"),
761                    after: "answer",
762                }
763                => Unsupported("`serialize_bytes` not supported yet"));
764
765            text!(option_none: Option::<&str>::None => "");
766            text!(option_some: Some("non-escaped string") => "non-escaped string");
767            text!(option_some_empty_str: Some("") => "");
768
769            text!(unit: () => "");
770            text!(unit_struct: Unit => "");
771            text!(unit_struct_escaped: UnitEscaped => "");
772
773            text!(enum_unit: Enum::Unit => "Unit");
774            text!(enum_unit_escaped: Enum::UnitEscaped => "&lt;&quot;&amp;&apos;&gt;");
775
776            text!(newtype: Newtype(42) => "42");
777            // We have no space where name of a variant can be stored
778            err!(enum_newtype:
779                SpecialEnum::Text {
780                    before: "answer",
781                    content: Enum::Newtype(42),
782                    after: "answer",
783                }
784                => Unsupported("cannot serialize enum newtype variant `Enum::Newtype` as text content value"));
785
786            // Sequences are serialized separated by spaces, all spaces inside are escaped
787            text!(seq: vec![1, 2, 3] => "1 2 3");
788            text!(seq_empty: Vec::<usize>::new() => "");
789            text!(tuple: ("<\"&'>", "with\t\n\r spaces", 3usize)
790                => "&lt;&quot;&amp;&apos;&gt; \
791                    with&#9;&#10;&#13;&#32;spaces \
792                    3");
793            text!(tuple_struct: Tuple("first", 42) => "first 42");
794            // We have no space where name of a variant can be stored
795            err!(enum_tuple:
796                SpecialEnum::Text {
797                    before: "answer",
798                    content: Enum::Tuple("first", 42),
799                    after: "answer",
800                }
801                => Unsupported("cannot serialize enum tuple variant `Enum::Tuple` as text content value"));
802
803            // Complex types cannot be serialized in `$text` field
804            err!(map:
805                SpecialEnum::Text {
806                    before: "answer",
807                    content: BTreeMap::from([("_1", 2), ("_3", 4)]),
808                    after: "answer",
809                }
810                => Unsupported("cannot serialize map as text content value"));
811            err!(struct_:
812                SpecialEnum::Text {
813                    before: "answer",
814                    content: Struct { key: "answer", val: (42, 42) },
815                    after: "answer",
816                }
817                => Unsupported("cannot serialize struct `Struct` as text content value"));
818            err!(enum_struct:
819                SpecialEnum::Text {
820                    before: "answer",
821                    content: Enum::Struct { key: "answer", val: (42, 42) },
822                    after: "answer",
823                }
824                => Unsupported("cannot serialize enum struct variant `Enum::Struct` as text content value"));
825        }
826
827        /// `$value` field inside a struct variant of an enum
828        mod enum_with_value_field {
829            use super::*;
830            use pretty_assertions::assert_eq;
831
832            macro_rules! value {
833                ($name:ident: $data:expr => $expected:literal) => {
834                    serialize_as!($name:
835                        SpecialEnum::Value {
836                            before: "answer",
837                            content: $data,
838                            after: "answer",
839                        }
840                        => concat!(
841                            "<Value><before>answer</before>",
842                            $expected,
843                            "<after>answer</after></Value>",
844                        ));
845                };
846            }
847
848            value!(false_: false => "false");
849            value!(true_:  true  => "true");
850
851            value!(i8_:    -42i8                => "-42");
852            value!(i16_:   -4200i16             => "-4200");
853            value!(i32_:   -42000000i32         => "-42000000");
854            value!(i64_:   -42000000000000i64   => "-42000000000000");
855            value!(isize_: -42000000000000isize => "-42000000000000");
856
857            value!(u8_:    42u8                => "42");
858            value!(u16_:   4200u16             => "4200");
859            value!(u32_:   42000000u32         => "42000000");
860            value!(u64_:   42000000000000u64   => "42000000000000");
861            value!(usize_: 42000000000000usize => "42000000000000");
862
863            serde_if_integer128! {
864                value!(i128_: -420000000000000000000000000000i128 => "-420000000000000000000000000000");
865                value!(u128_:  420000000000000000000000000000u128 => "420000000000000000000000000000");
866            }
867
868            value!(f32_: 4.2f32 => "4.2");
869            value!(f64_: 4.2f64 => "4.2");
870
871            value!(char_non_escaped: 'h' => "h");
872            value!(char_lt:   '<' => "&lt;");
873            value!(char_gt:   '>' => "&gt;");
874            value!(char_amp:  '&' => "&amp;");
875            value!(char_apos: '\'' => "&apos;");
876            value!(char_quot: '"' => "&quot;");
877            //TODO: add a setting to escape leading/trailing spaces, in order to
878            // pretty-print does not change the content
879            value!(char_space: ' ' => " ");
880
881            value!(str_non_escaped: "non-escaped string" => "non-escaped string");
882            value!(str_escaped: "<\"escaped & string'>" => "&lt;&quot;escaped &amp; string&apos;&gt;");
883
884            err!(bytes:
885                SpecialEnum::Value {
886                    before: "answer",
887                    content: Bytes(b"<\"escaped & bytes'>"),
888                    after: "answer",
889                }
890                => Unsupported("`serialize_bytes` not supported yet"));
891
892            value!(option_none: Option::<&str>::None => "");
893            value!(option_some: Some("non-escaped string") => "non-escaped string");
894            value!(option_some_empty_str: Some("") => "");
895
896            value!(unit: () => "");
897            value!(unit_struct: Unit => "");
898            value!(unit_struct_escaped: UnitEscaped => "");
899
900            value!(enum_unit: Enum::Unit => "<Unit/>");
901            err!(enum_unit_escaped:
902                SpecialEnum::Value {
903                    before: "answer",
904                    content: Enum::UnitEscaped,
905                    after: "answer",
906                }
907                => Unsupported("character `<` is not allowed at the start of an XML name `<\"&'>`"));
908
909            value!(newtype: Newtype(42) => "42");
910            value!(enum_newtype: Enum::Newtype(42) => "<Newtype>42</Newtype>");
911
912            // Note that sequences of primitives serialized without delimiters!
913            value!(seq: vec![1, 2, 3] => "123");
914            value!(seq_empty: Vec::<usize>::new() => "");
915            value!(tuple: ("<\"&'>", "with\t\n\r spaces", 3usize)
916                => "&lt;&quot;&amp;&apos;&gt;\
917                    with\t\n\r spaces\
918                    3");
919            value!(tuple_struct: Tuple("first", 42) => "first42");
920            value!(enum_tuple: Enum::Tuple("first", 42)
921                => "<Tuple>first</Tuple>\
922                    <Tuple>42</Tuple>");
923
924            // We cannot wrap map or struct in any container and should not
925            // flatten it, so it is impossible to serialize maps and structs
926            err!(map:
927                SpecialEnum::Value {
928                    before: "answer",
929                    content: BTreeMap::from([("_1", 2), ("_3", 4)]),
930                    after: "answer",
931                }
932                => Unsupported("serialization of map types is not supported in `$value` field"));
933            err!(struct_:
934                SpecialEnum::Value {
935                    before: "answer",
936                    content: Struct { key: "answer", val: (42, 42) },
937                    after: "answer",
938                }
939                => Unsupported("serialization of struct `Struct` is not supported in `$value` field"));
940            value!(enum_struct:
941                Enum::Struct { key: "answer", val: (42, 42) }
942                => "<Struct>\
943                        <key>answer</key>\
944                        <val>42</val>\
945                        <val>42</val>\
946                    </Struct>");
947        }
948
949        mod attributes {
950            use super::*;
951            use pretty_assertions::assert_eq;
952
953            err!(map_attr: BTreeMap::from([("@key1", 1), ("@key2", 2)])
954                => Unsupported("serialization of map types is not supported in `$value` field"));
955            err!(map_mixed: BTreeMap::from([("@key1", 1), ("key2", 2)])
956                => Unsupported("serialization of map types is not supported in `$value` field"));
957
958            err!(struct_: Attributes { key: "answer", val: (42, 42) }
959                => Unsupported("serialization of struct `Attributes` is not supported in `$value` field"));
960            err!(struct_before: AttributesBefore { key: "answer", val: 42 }
961                => Unsupported("serialization of struct `AttributesBefore` is not supported in `$value` field"));
962            err!(struct_after: AttributesAfter { key: "answer", val: 42 }
963                => Unsupported("serialization of struct `AttributesAfter` is not supported in `$value` field"));
964
965            serialize_as!(enum_: Enum::Attributes { key: "answer", val: (42, 42) }
966                => r#"<Attributes key="answer" val="42 42"/>"#);
967            serialize_as!(enum_before: Enum::AttributesBefore { key: "answer", val: 42 }
968                => r#"<AttributesBefore key="answer"><val>42</val></AttributesBefore>"#);
969            serialize_as!(enum_after: Enum::AttributesAfter { key: "answer", val: 42 }
970                => r#"<AttributesAfter val="42"><key>answer</key></AttributesAfter>"#);
971        }
972    }
973
974    mod with_indent {
975        use super::Struct;
976        use super::*;
977        use crate::writer::Indentation;
978        use pretty_assertions::assert_eq;
979
980        /// Checks that given `$data` successfully serialized as `$expected`
981        macro_rules! serialize_as {
982            ($name:ident: $data:expr => $expected:expr) => {
983                #[test]
984                fn $name() {
985                    let mut buffer = String::new();
986                    let ser = ContentSerializer {
987                        writer: &mut buffer,
988                        level: QuoteLevel::Full,
989                        indent: Indent::Owned(Indentation::new(b' ', 2)),
990                        write_indent: false,
991                        expand_empty_elements: false,
992                    };
993
994                    $data.serialize(ser).unwrap();
995                    assert_eq!(buffer, $expected);
996                }
997            };
998        }
999
1000        /// Checks that attempt to serialize given `$data` results to a
1001        /// serialization error `$kind` with `$reason`
1002        macro_rules! err {
1003            ($name:ident: $data:expr => $kind:ident($reason:literal)) => {
1004                #[test]
1005                fn $name() {
1006                    let mut buffer = String::new();
1007                    let ser = ContentSerializer {
1008                        writer: &mut buffer,
1009                        level: QuoteLevel::Full,
1010                        indent: Indent::Owned(Indentation::new(b' ', 2)),
1011                        write_indent: false,
1012                        expand_empty_elements: false,
1013                    };
1014
1015                    match $data.serialize(ser).unwrap_err() {
1016                        DeError::$kind(e) => assert_eq!(e, $reason),
1017                        e => panic!(
1018                            "Expected `{}({})`, found `{:?}`",
1019                            stringify!($kind),
1020                            $reason,
1021                            e
1022                        ),
1023                    }
1024                    // We can write something before fail
1025                    // assert_eq!(buffer, "");
1026                }
1027            };
1028        }
1029
1030        serialize_as!(false_: false => "false");
1031        serialize_as!(true_:  true  => "true");
1032
1033        serialize_as!(i8_:    -42i8                => "-42");
1034        serialize_as!(i16_:   -4200i16             => "-4200");
1035        serialize_as!(i32_:   -42000000i32         => "-42000000");
1036        serialize_as!(i64_:   -42000000000000i64   => "-42000000000000");
1037        serialize_as!(isize_: -42000000000000isize => "-42000000000000");
1038
1039        serialize_as!(u8_:    42u8                => "42");
1040        serialize_as!(u16_:   4200u16             => "4200");
1041        serialize_as!(u32_:   42000000u32         => "42000000");
1042        serialize_as!(u64_:   42000000000000u64   => "42000000000000");
1043        serialize_as!(usize_: 42000000000000usize => "42000000000000");
1044
1045        serde_if_integer128! {
1046            serialize_as!(i128_: -420000000000000000000000000000i128 => "-420000000000000000000000000000");
1047            serialize_as!(u128_:  420000000000000000000000000000u128 => "420000000000000000000000000000");
1048        }
1049
1050        serialize_as!(f32_: 4.2f32 => "4.2");
1051        serialize_as!(f64_: 4.2f64 => "4.2");
1052
1053        serialize_as!(char_non_escaped: 'h' => "h");
1054        serialize_as!(char_lt:   '<' => "&lt;");
1055        serialize_as!(char_gt:   '>' => "&gt;");
1056        serialize_as!(char_amp:  '&' => "&amp;");
1057        serialize_as!(char_apos: '\'' => "&apos;");
1058        serialize_as!(char_quot: '"' => "&quot;");
1059        //TODO: add a setting to escape leading/trailing spaces, in order to
1060        // pretty-print does not change the content
1061        serialize_as!(char_space: ' ' => " ");
1062
1063        serialize_as!(str_non_escaped: "non-escaped string" => "non-escaped string");
1064        serialize_as!(str_escaped: "<\"escaped & string'>" => "&lt;&quot;escaped &amp; string&apos;&gt;");
1065
1066        err!(bytes: Bytes(b"<\"escaped & bytes'>") => Unsupported("`serialize_bytes` not supported yet"));
1067
1068        serialize_as!(option_none: Option::<Enum>::None => "");
1069        serialize_as!(option_some: Some(Enum::Unit) => "<Unit/>");
1070
1071        serialize_as!(unit: () => "");
1072        serialize_as!(unit_struct: Unit => "");
1073        serialize_as!(unit_struct_escaped: UnitEscaped => "");
1074
1075        // Unlike SimpleTypeSerializer, enumeration values serialized as tags
1076        serialize_as!(enum_unit: Enum::Unit => "<Unit/>");
1077        err!(enum_unit_escaped: Enum::UnitEscaped
1078            => Unsupported("character `<` is not allowed at the start of an XML name `<\"&'>`"));
1079
1080        // Newtypes recursively applies ContentSerializer
1081        serialize_as!(newtype: Newtype(42) => "42");
1082        serialize_as!(enum_newtype: Enum::Newtype(42) => "<Newtype>42</Newtype>");
1083
1084        // Note that sequences of primitives serialized without delimiters other that indent!
1085        serialize_as!(seq: vec![1, 2, 3]
1086            => "1\n\
1087                2\n\
1088                3");
1089        serialize_as!(seq_empty: Vec::<usize>::new() => "");
1090        serialize_as!(tuple: ("<\"&'>", "with\t\r\n spaces", 3usize)
1091            => "&lt;&quot;&amp;&apos;&gt;\n\
1092                with\t\r\n spaces\n\
1093                3");
1094        serialize_as!(tuple_struct: Tuple("first", 42)
1095            => "first\n\
1096                42");
1097        serialize_as!(enum_tuple: Enum::Tuple("first", 42)
1098            => "<Tuple>first</Tuple>\n\
1099                <Tuple>42</Tuple>");
1100
1101        // Structured types cannot be serialized without surrounding tag, which
1102        // only `enum` can provide
1103        err!(map: BTreeMap::from([("_1", 2), ("_3", 4)])
1104            => Unsupported("serialization of map types is not supported in `$value` field"));
1105        err!(struct_: Struct { key: "answer", val: (42, 42) }
1106            => Unsupported("serialization of struct `Struct` is not supported in `$value` field"));
1107        serialize_as!(enum_struct: Enum::Struct { key: "answer", val: (42, 42) }
1108            => "<Struct>\n  \
1109                    <key>answer</key>\n  \
1110                    <val>42</val>\n  \
1111                    <val>42</val>\n\
1112                </Struct>");
1113
1114        /// Special field name `$text` should be serialized as text content
1115        mod text_field {
1116            use super::*;
1117            use pretty_assertions::assert_eq;
1118
1119            err!(map: BTreeMap::from([("$text", 2), ("_3", 4)])
1120                => Unsupported("serialization of map types is not supported in `$value` field"));
1121            err!(struct_:
1122                Text {
1123                    before: "answer",
1124                    content: (42, 42),
1125                    after: "answer",
1126                }
1127                => Unsupported("serialization of struct `Text` is not supported in `$value` field"));
1128            serialize_as!(enum_struct:
1129                SpecialEnum::Text {
1130                    before: "answer",
1131                    content: (42, 42),
1132                    after: "answer",
1133                }
1134                => "<Text>\n  \
1135                        <before>answer</before>\n  \
1136                        42 42\n  \
1137                        <after>answer</after>\n\
1138                    </Text>");
1139        }
1140
1141        /// `$text` field inside a struct variant of an enum
1142        mod enum_with_text_field {
1143            use super::*;
1144            use pretty_assertions::assert_eq;
1145
1146            macro_rules! text {
1147                ($name:ident: $data:expr) => {
1148                    serialize_as!($name:
1149                        SpecialEnum::Text {
1150                            before: "answer",
1151                            content: $data,
1152                            after: "answer",
1153                        }
1154                        => "<Text>\n  \
1155                                <before>answer</before>\n  \
1156                                <after>answer</after>\n\
1157                            </Text>");
1158                };
1159                ($name:ident: $data:expr => $expected:literal) => {
1160                    serialize_as!($name:
1161                        SpecialEnum::Text {
1162                            before: "answer",
1163                            content: $data,
1164                            after: "answer",
1165                        }
1166                        => concat!(
1167                            "<Text>\n  <before>answer</before>\n  ",
1168                            $expected,
1169                            "\n  <after>answer</after>\n</Text>",
1170                        ));
1171                };
1172            }
1173
1174            text!(false_: false => "false");
1175            text!(true_:  true  => "true");
1176
1177            text!(i8_:    -42i8                => "-42");
1178            text!(i16_:   -4200i16             => "-4200");
1179            text!(i32_:   -42000000i32         => "-42000000");
1180            text!(i64_:   -42000000000000i64   => "-42000000000000");
1181            text!(isize_: -42000000000000isize => "-42000000000000");
1182
1183            text!(u8_:    42u8                => "42");
1184            text!(u16_:   4200u16             => "4200");
1185            text!(u32_:   42000000u32         => "42000000");
1186            text!(u64_:   42000000000000u64   => "42000000000000");
1187            text!(usize_: 42000000000000usize => "42000000000000");
1188
1189            serde_if_integer128! {
1190                text!(i128_: -420000000000000000000000000000i128 => "-420000000000000000000000000000");
1191                text!(u128_:  420000000000000000000000000000u128 => "420000000000000000000000000000");
1192            }
1193
1194            text!(f32_: 4.2f32 => "4.2");
1195            text!(f64_: 4.2f64 => "4.2");
1196
1197            text!(char_non_escaped: 'h' => "h");
1198            text!(char_lt:   '<' => "&lt;");
1199            text!(char_gt:   '>' => "&gt;");
1200            text!(char_amp:  '&' => "&amp;");
1201            text!(char_apos: '\'' => "&apos;");
1202            text!(char_quot: '"' => "&quot;");
1203            //TODO: add a setting to escape leading/trailing spaces, in order to
1204            // pretty-print does not change the content
1205            text!(char_space: ' ' => " ");
1206
1207            text!(str_non_escaped: "non-escaped string" => "non-escaped string");
1208            text!(str_escaped: "<\"escaped & string'>" => "&lt;&quot;escaped &amp; string&apos;&gt;");
1209
1210            err!(bytes:
1211                SpecialEnum::Text {
1212                    before: "answer",
1213                    content: Bytes(b"<\"escaped & bytes'>"),
1214                    after: "answer",
1215                }
1216                => Unsupported("`serialize_bytes` not supported yet"));
1217
1218            text!(option_none: Option::<&str>::None);
1219            text!(option_some: Some("non-escaped string") => "non-escaped string");
1220            text!(option_some_empty_str: Some(""));
1221
1222            text!(unit: ());
1223            text!(unit_struct: Unit);
1224            text!(unit_struct_escaped: UnitEscaped);
1225
1226            text!(enum_unit: Enum::Unit => "Unit");
1227            text!(enum_unit_escaped: Enum::UnitEscaped => "&lt;&quot;&amp;&apos;&gt;");
1228
1229            text!(newtype: Newtype(42) => "42");
1230            // We have no space where name of a variant can be stored
1231            err!(enum_newtype:
1232                SpecialEnum::Text {
1233                    before: "answer",
1234                    content: Enum::Newtype(42),
1235                    after: "answer",
1236                }
1237                => Unsupported("cannot serialize enum newtype variant `Enum::Newtype` as text content value"));
1238
1239            // Sequences are serialized separated by spaces, all spaces inside are escaped
1240            text!(seq: vec![1, 2, 3] => "1 2 3");
1241            text!(seq_empty: Vec::<usize>::new());
1242            text!(tuple: ("<\"&'>", "with\t\n\r spaces", 3usize)
1243                => "&lt;&quot;&amp;&apos;&gt; \
1244                    with&#9;&#10;&#13;&#32;spaces \
1245                    3");
1246            text!(tuple_struct: Tuple("first", 42) => "first 42");
1247            // We have no space where name of a variant can be stored
1248            err!(enum_tuple:
1249                SpecialEnum::Text {
1250                    before: "answer",
1251                    content: Enum::Tuple("first", 42),
1252                    after: "answer",
1253                }
1254                => Unsupported("cannot serialize enum tuple variant `Enum::Tuple` as text content value"));
1255
1256            // Complex types cannot be serialized in `$text` field
1257            err!(map:
1258                SpecialEnum::Text {
1259                    before: "answer",
1260                    content: BTreeMap::from([("_1", 2), ("_3", 4)]),
1261                    after: "answer",
1262                }
1263                => Unsupported("cannot serialize map as text content value"));
1264            err!(struct_:
1265                SpecialEnum::Text {
1266                    before: "answer",
1267                    content: Struct { key: "answer", val: (42, 42) },
1268                    after: "answer",
1269                }
1270                => Unsupported("cannot serialize struct `Struct` as text content value"));
1271            err!(enum_struct:
1272                SpecialEnum::Text {
1273                    before: "answer",
1274                    content: Enum::Struct { key: "answer", val: (42, 42) },
1275                    after: "answer",
1276                }
1277                => Unsupported("cannot serialize enum struct variant `Enum::Struct` as text content value"));
1278        }
1279
1280        /// `$value` field inside a struct variant of an enum
1281        mod enum_with_value_field {
1282            use super::*;
1283            use pretty_assertions::assert_eq;
1284
1285            macro_rules! value {
1286                ($name:ident: $data:expr) => {
1287                    serialize_as!($name:
1288                        SpecialEnum::Value {
1289                            before: "answer",
1290                            content: $data,
1291                            after: "answer",
1292                        }
1293                        => "<Value>\n  \
1294                                <before>answer</before>\n  \
1295                                <after>answer</after>\n\
1296                            </Value>");
1297                };
1298                ($name:ident: $data:expr => $expected:literal) => {
1299                    serialize_as!($name:
1300                        SpecialEnum::Value {
1301                            before: "answer",
1302                            content: $data,
1303                            after: "answer",
1304                        }
1305                        => concat!(
1306                            "<Value>\n  <before>answer</before>\n  ",
1307                            $expected,
1308                            "\n  <after>answer</after>\n</Value>",
1309                        ));
1310                };
1311            }
1312
1313            value!(false_: false => "false");
1314            value!(true_:  true  => "true");
1315
1316            value!(i8_:    -42i8                => "-42");
1317            value!(i16_:   -4200i16             => "-4200");
1318            value!(i32_:   -42000000i32         => "-42000000");
1319            value!(i64_:   -42000000000000i64   => "-42000000000000");
1320            value!(isize_: -42000000000000isize => "-42000000000000");
1321
1322            value!(u8_:    42u8                => "42");
1323            value!(u16_:   4200u16             => "4200");
1324            value!(u32_:   42000000u32         => "42000000");
1325            value!(u64_:   42000000000000u64   => "42000000000000");
1326            value!(usize_: 42000000000000usize => "42000000000000");
1327
1328            serde_if_integer128! {
1329                value!(i128_: -420000000000000000000000000000i128 => "-420000000000000000000000000000");
1330                value!(u128_:  420000000000000000000000000000u128 => "420000000000000000000000000000");
1331            }
1332
1333            value!(f32_: 4.2f32 => "4.2");
1334            value!(f64_: 4.2f64 => "4.2");
1335
1336            value!(char_non_escaped: 'h' => "h");
1337            value!(char_lt:   '<' => "&lt;");
1338            value!(char_gt:   '>' => "&gt;");
1339            value!(char_amp:  '&' => "&amp;");
1340            value!(char_apos: '\'' => "&apos;");
1341            value!(char_quot: '"' => "&quot;");
1342            //TODO: add a setting to escape leading/trailing spaces, in order to
1343            // pretty-print does not change the content
1344            value!(char_space: ' ' => " ");
1345
1346            value!(str_non_escaped: "non-escaped string" => "non-escaped string");
1347            value!(str_escaped: "<\"escaped & string'>" => "&lt;&quot;escaped &amp; string&apos;&gt;");
1348
1349            err!(bytes:
1350                SpecialEnum::Value {
1351                    before: "answer",
1352                    content: Bytes(b"<\"escaped & bytes'>"),
1353                    after: "answer",
1354                }
1355                => Unsupported("`serialize_bytes` not supported yet"));
1356
1357            value!(option_none: Option::<&str>::None);
1358            value!(option_some: Some("non-escaped string") => "non-escaped string");
1359            value!(option_some_empty_str: Some(""));
1360
1361            value!(unit: ());
1362            value!(unit_struct: Unit);
1363            value!(unit_struct_escaped: UnitEscaped);
1364
1365            value!(enum_unit: Enum::Unit => "<Unit/>");
1366            err!(enum_unit_escaped:
1367                SpecialEnum::Value {
1368                    before: "answer",
1369                    content: Enum::UnitEscaped,
1370                    after: "answer",
1371                }
1372                => Unsupported("character `<` is not allowed at the start of an XML name `<\"&'>`"));
1373
1374            value!(newtype: Newtype(42) => "42");
1375            value!(enum_newtype: Enum::Newtype(42) => "<Newtype>42</Newtype>");
1376
1377            // Note that sequences of primitives serialized without delimiters!
1378            value!(seq: vec![1, 2, 3] => "1\n  2\n  3");
1379            value!(seq_empty: Vec::<usize>::new());
1380            value!(tuple: ("<\"&'>", "with\t\n\r spaces", 3usize)
1381                => "&lt;&quot;&amp;&apos;&gt;\n  \
1382                    with\t\n\r spaces\n  \
1383                    3");
1384            value!(tuple_struct: Tuple("first", 42) => "first\n  42");
1385            value!(enum_tuple: Enum::Tuple("first", 42)
1386                => "<Tuple>first</Tuple>\n  \
1387                    <Tuple>42</Tuple>");
1388
1389            // We cannot wrap map or struct in any container and should not
1390            // flatten it, so it is impossible to serialize maps and structs
1391            err!(map:
1392                SpecialEnum::Value {
1393                    before: "answer",
1394                    content: BTreeMap::from([("_1", 2), ("_3", 4)]),
1395                    after: "answer",
1396                }
1397                => Unsupported("serialization of map types is not supported in `$value` field"));
1398            err!(struct_:
1399                SpecialEnum::Value {
1400                    before: "answer",
1401                    content: Struct { key: "answer", val: (42, 42) },
1402                    after: "answer",
1403                }
1404                => Unsupported("serialization of struct `Struct` is not supported in `$value` field"));
1405            value!(enum_struct:
1406                Enum::Struct { key: "answer", val: (42, 42) }
1407                => "<Struct>\n    \
1408                        <key>answer</key>\n    \
1409                        <val>42</val>\n    \
1410                        <val>42</val>\n  \
1411                    </Struct>");
1412        }
1413
1414        mod attributes {
1415            use super::*;
1416            use pretty_assertions::assert_eq;
1417
1418            err!(map_attr: BTreeMap::from([("@key1", 1), ("@key2", 2)])
1419                => Unsupported("serialization of map types is not supported in `$value` field"));
1420            err!(map_mixed: BTreeMap::from([("@key1", 1), ("key2", 2)])
1421                => Unsupported("serialization of map types is not supported in `$value` field"));
1422
1423            err!(struct_: Attributes { key: "answer", val: (42, 42) }
1424                => Unsupported("serialization of struct `Attributes` is not supported in `$value` field"));
1425            err!(struct_before: AttributesBefore { key: "answer", val: 42 }
1426                => Unsupported("serialization of struct `AttributesBefore` is not supported in `$value` field"));
1427            err!(struct_after: AttributesAfter { key: "answer", val: 42 }
1428                => Unsupported("serialization of struct `AttributesAfter` is not supported in `$value` field"));
1429
1430            serialize_as!(enum_: Enum::Attributes { key: "answer", val: (42, 42) }
1431                => r#"<Attributes key="answer" val="42 42"/>"#);
1432            serialize_as!(enum_before: Enum::AttributesBefore { key: "answer", val: 42 }
1433                => "<AttributesBefore key=\"answer\">\n  \
1434                        <val>42</val>\n\
1435                    </AttributesBefore>");
1436            serialize_as!(enum_after: Enum::AttributesAfter { key: "answer", val: 42 }
1437                => "<AttributesAfter val=\"42\">\n  \
1438                        <key>answer</key>\n\
1439                    </AttributesAfter>");
1440        }
1441    }
1442}