Skip to main content

quick_xml/se/
element.rs

1//! Contains serializer for an XML element
2
3use crate::de::{TEXT_KEY, VALUE_KEY};
4use crate::se::content::ContentSerializer;
5use crate::se::key::QNameSerializer;
6use crate::se::simple_type::{QuoteTarget, SimpleSeq, SimpleTypeSerializer};
7use crate::se::text::TextSerializer;
8use crate::se::{EmptyElementHandling, SeError, WriteResult, XmlName};
9use serde::ser::{
10    Impossible, Serialize, SerializeMap, SerializeSeq, SerializeStruct, SerializeStructVariant,
11    SerializeTuple, SerializeTupleStruct, SerializeTupleVariant, Serializer,
12};
13use std::fmt::Write;
14
15/// Writes simple type content between [`ElementSerializer::key`] tags.
16macro_rules! write_primitive {
17    ($method:ident ( $ty:ty )) => {
18        fn $method(self, value: $ty) -> Result<Self::Ok, Self::Error> {
19            self.ser.write_wrapped(self.key, |ser| ser.$method(value))
20        }
21    };
22}
23
24////////////////////////////////////////////////////////////////////////////////////////////////////
25
26/// A serializer used to serialize element with specified name. Unlike the [`ContentSerializer`],
27/// this serializer never uses variant names of enum variants, and because of that
28/// it is unable to serialize any enum values, except unit variants.
29///
30/// Returns the classification of the last written type.
31///
32/// This serializer is used for an ordinary fields in structs, which are not special
33/// fields named `$text` ([`TEXT_KEY`]) or `$value` ([`VALUE_KEY`]). `$text` field
34/// should be serialized using [`SimpleTypeSerializer`] and `$value` field should be
35/// serialized using [`ContentSerializer`].
36///
37/// This serializer does the following:
38/// - numbers converted to a decimal representation and serialized as `<key>value</key>`;
39/// - booleans serialized ether as `<key>true</key>` or `<key>false</key>`;
40/// - strings and characters are serialized as `<key>value</key>`. In particular,
41///   an empty string is serialized as `<key/>`;
42/// - `None` is serialized as `<key/>`;
43/// - `Some` and newtypes are serialized as an inner type using the same serializer;
44/// - units (`()`) and unit structs are serialized as `<key/>`;
45/// - sequences, tuples and tuple structs are serialized as repeated `<key>` tag.
46///   In particular, empty sequence is serialized to nothing;
47/// - structs are serialized as a sequence of fields wrapped in a `<key>` tag. Each
48///   field is serialized recursively using either `ElementSerializer`, [`ContentSerializer`]
49///   (`$value` fields), or [`SimpleTypeSerializer`] (`$text` fields).
50///   In particular, the empty struct is serialized as `<key/>`;
51/// - maps are serialized as a sequence of entries wrapped in a `<key>` tag. If key is
52///   serialized to a special name, the same rules as for struct fields are applied.
53///   In particular, the empty map is serialized as `<key/>`;
54/// - enums:
55///   - unit variants are serialized as `<key>variant</key>`;
56///   - other variants are not supported ([`SeError::Unsupported`] is returned);
57///
58/// Usage of empty tags depends on the [`ContentSerializer::empty_element_handling`] setting.
59pub struct ElementSerializer<'w, 'k, W: Write> {
60    /// The inner serializer that contains the settings and mostly do the actual work
61    pub ser: ContentSerializer<'w, 'k, W>,
62    /// Tag name used to wrap serialized types except enum variants which uses the variant name
63    pub(super) key: XmlName<'k>,
64}
65
66impl<'w, 'k, W: Write> Serializer for ElementSerializer<'w, 'k, W> {
67    type Ok = WriteResult;
68    type Error = SeError;
69
70    type SerializeSeq = Self;
71    type SerializeTuple = Self;
72    type SerializeTupleStruct = Self;
73    type SerializeTupleVariant = Impossible<Self::Ok, Self::Error>;
74    type SerializeMap = Map<'w, 'k, W>;
75    type SerializeStruct = Struct<'w, 'k, W>;
76    type SerializeStructVariant = Struct<'w, 'k, W>;
77
78    write_primitive!(serialize_bool(bool));
79
80    write_primitive!(serialize_i8(i8));
81    write_primitive!(serialize_i16(i16));
82    write_primitive!(serialize_i32(i32));
83    write_primitive!(serialize_i64(i64));
84
85    write_primitive!(serialize_u8(u8));
86    write_primitive!(serialize_u16(u16));
87    write_primitive!(serialize_u32(u32));
88    write_primitive!(serialize_u64(u64));
89
90    write_primitive!(serialize_i128(i128));
91    write_primitive!(serialize_u128(u128));
92
93    write_primitive!(serialize_f32(f32));
94    write_primitive!(serialize_f64(f64));
95
96    write_primitive!(serialize_char(char));
97    write_primitive!(serialize_bytes(&[u8]));
98
99    fn serialize_str(self, value: &str) -> Result<Self::Ok, Self::Error> {
100        if value.is_empty() {
101            self.ser.write_empty(self.key)
102        } else {
103            self.ser
104                .write_wrapped(self.key, |ser| ser.serialize_str(value))
105        }
106    }
107
108    /// By serde contract we should serialize key of [`None`] values. If someone
109    /// wants to skip the field entirely, he should use
110    /// `#[serde(skip_serializing_if = "Option::is_none")]`.
111    ///
112    /// In XML when we serialize field, we write field name as:
113    /// - element name, or
114    /// - attribute name
115    ///
116    /// and field value as
117    /// - content of the element, or
118    /// - attribute value
119    ///
120    /// So serialization of `None` works the same as [serialization of `()`](#method.serialize_unit)
121    fn serialize_none(self) -> Result<Self::Ok, Self::Error> {
122        self.serialize_unit()
123    }
124
125    fn serialize_some<T: ?Sized + Serialize>(self, value: &T) -> Result<Self::Ok, Self::Error> {
126        value.serialize(self)
127    }
128
129    fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
130        self.ser.write_empty(self.key)
131    }
132
133    fn serialize_unit_struct(self, _name: &'static str) -> Result<Self::Ok, Self::Error> {
134        self.ser.write_empty(self.key)
135    }
136
137    /// Writes a tag with name [`Self::key`] and content of unit variant inside.
138    /// If variant is a special `$text` value, then empty tag `<key/>` is written.
139    /// Otherwise a `<key>variant</key>` is written.
140    fn serialize_unit_variant(
141        self,
142        name: &'static str,
143        variant_index: u32,
144        variant: &'static str,
145    ) -> Result<Self::Ok, Self::Error> {
146        if variant == TEXT_KEY {
147            self.ser.write_empty(self.key)
148        } else {
149            self.ser.write_wrapped(self.key, |ser| {
150                ser.serialize_unit_variant(name, variant_index, variant)
151            })
152        }
153    }
154
155    fn serialize_newtype_struct<T: ?Sized + Serialize>(
156        self,
157        _name: &'static str,
158        value: &T,
159    ) -> Result<Self::Ok, Self::Error> {
160        value.serialize(self)
161    }
162
163    /// Always returns [`SeError::Unsupported`]. Newtype variants can be serialized
164    /// only in `$value` fields, which is serialized using [`ContentSerializer`].
165    #[inline]
166    fn serialize_newtype_variant<T: ?Sized + Serialize>(
167        self,
168        name: &'static str,
169        _variant_index: u32,
170        variant: &'static str,
171        _value: &T,
172    ) -> Result<Self::Ok, Self::Error> {
173        Err(SeError::Unsupported(
174            format!(
175                "cannot serialize enum newtype variant `{}::{}`",
176                name, variant
177            )
178            .into(),
179        ))
180    }
181
182    #[inline]
183    fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> {
184        Ok(self)
185    }
186
187    #[inline]
188    fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple, Self::Error> {
189        self.serialize_seq(Some(len))
190    }
191
192    #[inline]
193    fn serialize_tuple_struct(
194        self,
195        _name: &'static str,
196        len: usize,
197    ) -> Result<Self::SerializeTupleStruct, Self::Error> {
198        self.serialize_tuple(len)
199    }
200
201    /// Always returns [`SeError::Unsupported`]. Tuple variants can be serialized
202    /// only in `$value` fields, which is serialized using [`ContentSerializer`].
203    #[inline]
204    fn serialize_tuple_variant(
205        self,
206        name: &'static str,
207        _variant_index: u32,
208        variant: &'static str,
209        _len: usize,
210    ) -> Result<Self::SerializeTupleVariant, Self::Error> {
211        Err(SeError::Unsupported(
212            format!(
213                "cannot serialize enum tuple variant `{}::{}`",
214                name, variant
215            )
216            .into(),
217        ))
218    }
219
220    fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
221        Ok(Map {
222            ser: self.serialize_struct("", 0)?,
223            key: None,
224        })
225    }
226
227    #[inline]
228    fn serialize_struct(
229        mut self,
230        _name: &'static str,
231        _len: usize,
232    ) -> Result<Self::SerializeStruct, Self::Error> {
233        self.ser.write_indent()?;
234        self.ser.indent.increase();
235
236        self.ser.writer.write_char('<')?;
237        self.ser.writer.write_str(self.key.0)?;
238        Ok(Struct {
239            ser: self,
240            children: String::new(),
241            write_indent: true,
242        })
243    }
244
245    /// Always returns [`SeError::Unsupported`]. Struct variants can be serialized
246    /// only in `$value` fields, which is serialized using [`ContentSerializer`].
247    #[inline]
248    fn serialize_struct_variant(
249        self,
250        name: &'static str,
251        _variant_index: u32,
252        variant: &'static str,
253        _len: usize,
254    ) -> Result<Self::SerializeStructVariant, Self::Error> {
255        Err(SeError::Unsupported(
256            format!(
257                "cannot serialize enum struct variant `{}::{}`",
258                name, variant
259            )
260            .into(),
261        ))
262    }
263}
264
265impl<'w, 'k, W: Write> SerializeSeq for ElementSerializer<'w, 'k, W> {
266    type Ok = WriteResult;
267    type Error = SeError;
268
269    fn serialize_element<T>(&mut self, value: &T) -> Result<(), Self::Error>
270    where
271        T: ?Sized + Serialize,
272    {
273        value.serialize(ElementSerializer {
274            ser: self.ser.new_seq_element_serializer(true),
275            key: self.key,
276        })?;
277        // Write indent for the next element
278        self.ser.write_indent = true;
279        Ok(())
280    }
281
282    #[inline]
283    fn end(self) -> Result<Self::Ok, Self::Error> {
284        Ok(WriteResult::Element)
285    }
286}
287
288impl<'w, 'k, W: Write> SerializeTuple for ElementSerializer<'w, 'k, W> {
289    type Ok = WriteResult;
290    type Error = SeError;
291
292    #[inline]
293    fn serialize_element<T>(&mut self, value: &T) -> Result<(), Self::Error>
294    where
295        T: ?Sized + Serialize,
296    {
297        SerializeSeq::serialize_element(self, value)
298    }
299
300    #[inline]
301    fn end(self) -> Result<Self::Ok, Self::Error> {
302        SerializeSeq::end(self)
303    }
304}
305
306impl<'w, 'k, W: Write> SerializeTupleStruct for ElementSerializer<'w, 'k, W> {
307    type Ok = WriteResult;
308    type Error = SeError;
309
310    #[inline]
311    fn serialize_field<T>(&mut self, value: &T) -> Result<(), Self::Error>
312    where
313        T: ?Sized + Serialize,
314    {
315        SerializeSeq::serialize_element(self, value)
316    }
317
318    #[inline]
319    fn end(self) -> Result<Self::Ok, Self::Error> {
320        SerializeSeq::end(self)
321    }
322}
323
324////////////////////////////////////////////////////////////////////////////////////////////////////
325
326/// A serializer for tuple variants. Tuples can be serialized in two modes:
327/// - wrapping each tuple field into a tag
328/// - without wrapping, fields are delimited by a space
329pub enum Tuple<'w, 'k, W: Write> {
330    /// Serialize each tuple field as an element
331    Element(ElementSerializer<'w, 'k, W>),
332    /// Serialize tuple as an `xs:list`: space-delimited content of fields
333    Text(SimpleSeq<&'w mut W>),
334}
335
336impl<'w, 'k, W: Write> SerializeTupleVariant for Tuple<'w, 'k, W> {
337    type Ok = WriteResult;
338    type Error = SeError;
339
340    #[inline]
341    fn serialize_field<T>(&mut self, value: &T) -> Result<(), Self::Error>
342    where
343        T: ?Sized + Serialize,
344    {
345        match self {
346            Self::Element(ser) => SerializeTuple::serialize_element(ser, value),
347            Self::Text(ser) => SerializeTuple::serialize_element(ser, value),
348        }
349    }
350
351    #[inline]
352    fn end(self) -> Result<Self::Ok, Self::Error> {
353        match self {
354            Self::Element(ser) => SerializeTuple::end(ser),
355            // Do not write indent after `$text` fields because it may be interpreted as
356            // part of content when deserialize
357            Self::Text(ser) => SerializeTuple::end(ser).map(|_| WriteResult::SensitiveText),
358        }
359    }
360}
361
362////////////////////////////////////////////////////////////////////////////////////////////////////
363
364/// A serializer for struct variants, which serializes the struct contents inside
365/// of wrapping tags (`<${tag}>...</${tag}>`).
366///
367/// Returns the classification of the last written type.
368///
369/// Serialization of each field depends on it representation:
370/// - attributes written directly to the higher serializer
371/// - elements buffered into internal buffer and at the end written into higher
372///   serializer
373pub struct Struct<'w, 'k, W: Write> {
374    ser: ElementSerializer<'w, 'k, W>,
375    /// Buffer to store serialized elements
376    // TODO: Customization point: allow direct writing of elements, but all
377    // attributes should be listed first. Fail, if attribute encountered after
378    // element. Use feature to configure
379    children: String,
380    /// Whether need to write indent after the last written field
381    write_indent: bool,
382}
383
384impl<'w, 'k, W: Write> Struct<'w, 'k, W> {
385    #[inline]
386    fn write_field<T>(&mut self, key: &str, value: &T) -> Result<(), SeError>
387    where
388        T: ?Sized + Serialize,
389    {
390        //TODO: Customization point: allow user to determine if field is attribute or not
391        if let Some(key) = key.strip_prefix('@') {
392            let key = XmlName::try_from(key)?;
393            self.write_attribute(key, value)
394        } else {
395            self.write_element(key, value)
396        }
397    }
398
399    /// Writes `value` as an attribute
400    #[inline]
401    fn write_attribute<T>(&mut self, key: XmlName, value: &T) -> Result<(), SeError>
402    where
403        T: ?Sized + Serialize,
404    {
405        //TODO: Customization point: each attribute on new line
406        self.ser.ser.writer.write_char(' ')?;
407        self.ser.ser.writer.write_str(key.0)?;
408        self.ser.ser.writer.write_char('=')?;
409
410        //TODO: Customization point: preferred quote style
411        self.ser.ser.writer.write_char('"')?;
412        value.serialize(SimpleTypeSerializer {
413            writer: &mut self.ser.ser.writer,
414            target: QuoteTarget::DoubleQAttr,
415            level: self.ser.ser.level,
416        })?;
417        self.ser.ser.writer.write_char('"')?;
418
419        Ok(())
420    }
421
422    /// Writes `value` either as a text content, or as an element.
423    ///
424    /// If `key` has a magic value [`TEXT_KEY`], then `value` serialized as a
425    /// [simple type].
426    ///
427    /// If `key` has a magic value [`VALUE_KEY`], then `value` serialized as a
428    /// [content] without wrapping in tags, otherwise it is wrapped in
429    /// `<${key}>...</${key}>`.
430    ///
431    /// [simple type]: SimpleTypeSerializer
432    /// [content]: ContentSerializer
433    fn write_element<T>(&mut self, key: &str, value: &T) -> Result<(), SeError>
434    where
435        T: ?Sized + Serialize,
436    {
437        let ser = ContentSerializer {
438            writer: &mut self.children,
439            level: self.ser.ser.level,
440            indent: self.ser.ser.indent.borrow(),
441            // If previous field does not require indent, do not write it
442            write_indent: self.write_indent,
443            text_format: self.ser.ser.text_format,
444            allow_primitive: true,
445            empty_element_handling: self.ser.ser.empty_element_handling,
446        };
447
448        if key == TEXT_KEY {
449            value.serialize(TextSerializer(ser.into_simple_type_serializer()?))?;
450            // Text was written so we don't need to indent next field
451            self.write_indent = false;
452        } else if key == VALUE_KEY {
453            // If element was written then we need to indent next field unless it is a text field
454            self.write_indent = value.serialize(ser)?.allow_indent();
455        } else {
456            value.serialize(ElementSerializer {
457                key: XmlName::try_from(key)?,
458                ser,
459            })?;
460            // Element was written so we need to indent next field unless it is a text field
461            self.write_indent = true;
462        }
463        Ok(())
464    }
465}
466
467impl<'w, 'k, W: Write> SerializeStruct for Struct<'w, 'k, W> {
468    type Ok = WriteResult;
469    type Error = SeError;
470
471    fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error>
472    where
473        T: ?Sized + Serialize,
474    {
475        self.write_field(key, value)
476    }
477
478    fn end(mut self) -> Result<Self::Ok, Self::Error> {
479        self.ser.ser.indent.decrease();
480
481        if self.children.is_empty() {
482            match self.ser.ser.empty_element_handling {
483                EmptyElementHandling::SelfClosed => {
484                    self.ser.ser.writer.write_str("/>")?;
485                }
486                EmptyElementHandling::SelfClosedWithSpace => {
487                    self.ser.ser.writer.write_str(" />")?;
488                }
489                EmptyElementHandling::Expanded => {
490                    self.ser.ser.writer.write_str("></")?;
491                    self.ser.ser.writer.write_str(self.ser.key.0)?;
492                    self.ser.ser.writer.write_char('>')?;
493                }
494            }
495        } else {
496            self.ser.ser.writer.write_char('>')?;
497            self.ser.ser.writer.write_str(&self.children)?;
498
499            if self.write_indent {
500                self.ser.ser.indent.write_indent(&mut self.ser.ser.writer)?;
501            }
502
503            self.ser.ser.writer.write_str("</")?;
504            self.ser.ser.writer.write_str(self.ser.key.0)?;
505            self.ser.ser.writer.write_char('>')?;
506        }
507        Ok(WriteResult::Element)
508    }
509}
510
511impl<'w, 'k, W: Write> SerializeStructVariant for Struct<'w, 'k, W> {
512    type Ok = WriteResult;
513    type Error = SeError;
514
515    #[inline]
516    fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error>
517    where
518        T: ?Sized + Serialize,
519    {
520        SerializeStruct::serialize_field(self, key, value)
521    }
522
523    #[inline]
524    fn end(self) -> Result<Self::Ok, Self::Error> {
525        SerializeStruct::end(self)
526    }
527}
528
529////////////////////////////////////////////////////////////////////////////////////////////////////
530
531pub struct Map<'w, 'k, W: Write> {
532    ser: Struct<'w, 'k, W>,
533    /// Key, serialized by `QNameSerializer` if consumer uses `serialize_key` +
534    /// `serialize_value` calls instead of `serialize_entry`
535    key: Option<String>,
536}
537
538impl<'w, 'k, W: Write> Map<'w, 'k, W> {
539    fn make_key<T>(&mut self, key: &T) -> Result<String, SeError>
540    where
541        T: ?Sized + Serialize,
542    {
543        key.serialize(QNameSerializer {
544            writer: String::new(),
545        })
546    }
547}
548
549impl<'w, 'k, W: Write> SerializeMap for Map<'w, 'k, W> {
550    type Ok = WriteResult;
551    type Error = SeError;
552
553    fn serialize_key<T>(&mut self, key: &T) -> Result<(), Self::Error>
554    where
555        T: ?Sized + Serialize,
556    {
557        if self.key.take().is_some() {
558            return Err(SeError::Custom(
559                "calling `serialize_key` twice without `serialize_value`".to_string(),
560            ));
561        }
562        self.key = Some(self.make_key(key)?);
563        Ok(())
564    }
565
566    fn serialize_value<T>(&mut self, value: &T) -> Result<(), Self::Error>
567    where
568        T: ?Sized + Serialize,
569    {
570        if let Some(key) = self.key.take() {
571            return self.ser.write_field(&key, value);
572        }
573        Err(SeError::Custom(
574            "calling `serialize_value` without call of `serialize_key`".to_string(),
575        ))
576    }
577
578    fn serialize_entry<K, V>(&mut self, key: &K, value: &V) -> Result<(), Self::Error>
579    where
580        K: ?Sized + Serialize,
581        V: ?Sized + Serialize,
582    {
583        let key = self.make_key(key)?;
584        self.ser.write_field(&key, value)
585    }
586
587    fn end(mut self) -> Result<Self::Ok, Self::Error> {
588        if let Some(key) = self.key.take() {
589            return Err(SeError::Custom(format!(
590                "calling `end` without call of `serialize_value` for key `{key}`"
591            )));
592        }
593        SerializeStruct::end(self.ser)
594    }
595}
596
597////////////////////////////////////////////////////////////////////////////////////////////////////
598
599#[cfg(test)]
600mod tests {
601    use super::*;
602    use crate::se::content::tests::*;
603    use crate::se::{Indent, QuoteLevel, TextFormat};
604    use crate::utils::Bytes;
605    use serde::Serialize;
606    use std::collections::BTreeMap;
607
608    #[derive(Debug, Serialize, PartialEq)]
609    struct OptionalElements {
610        a: Option<&'static str>,
611
612        #[serde(skip_serializing_if = "Option::is_none")]
613        b: Option<&'static str>,
614    }
615    #[derive(Debug, Serialize, PartialEq)]
616    struct OptionalAttributes {
617        #[serde(rename = "@a")]
618        a: Option<&'static str>,
619
620        #[serde(rename = "@b")]
621        #[serde(skip_serializing_if = "Option::is_none")]
622        b: Option<&'static str>,
623    }
624
625    mod without_indent {
626        use super::*;
627        use crate::se::content::tests::Struct;
628        use pretty_assertions::assert_eq;
629
630        /// Checks that given `$data` successfully serialized as `$expected`
631        macro_rules! serialize_as {
632            ($name:ident: $data:expr => $expected:expr) => {
633                #[test]
634                fn $name() {
635                    let mut buffer = String::new();
636                    let ser = ElementSerializer {
637                        ser: ContentSerializer {
638                            writer: &mut buffer,
639                            level: QuoteLevel::Full,
640                            indent: Indent::None,
641                            write_indent: false,
642                            text_format: TextFormat::Text,
643                            allow_primitive: true,
644                            empty_element_handling: EmptyElementHandling::SelfClosed,
645                        },
646                        key: XmlName("root"),
647                    };
648
649                    let result = $data.serialize(ser).unwrap();
650                    assert_eq!(buffer, $expected);
651                    assert_eq!(result, WriteResult::Element);
652                }
653            };
654        }
655
656        /// Checks that attempt to serialize given `$data` results to a
657        /// serialization error `$kind` with `$reason`
658        macro_rules! err {
659            ($name:ident: $data:expr => $kind:ident($reason:literal)) => {
660                #[test]
661                fn $name() {
662                    let mut buffer = String::new();
663                    let ser = ElementSerializer {
664                        ser: ContentSerializer {
665                            writer: &mut buffer,
666                            level: QuoteLevel::Full,
667                            indent: Indent::None,
668                            write_indent: false,
669                            text_format: TextFormat::Text,
670                            allow_primitive: true,
671                            empty_element_handling: EmptyElementHandling::SelfClosed,
672                        },
673                        key: XmlName("root"),
674                    };
675
676                    match $data.serialize(ser).unwrap_err() {
677                        SeError::$kind(e) => assert_eq!(e, $reason),
678                        e => panic!(
679                            "Expected `Err({}({}))`, but got `{:?}`",
680                            stringify!($kind),
681                            $reason,
682                            e
683                        ),
684                    }
685                    // We can write something before fail
686                    // assert_eq!(buffer, "");
687                }
688            };
689        }
690
691        serialize_as!(false_: false => "<root>false</root>");
692        serialize_as!(true_:  true  => "<root>true</root>");
693
694        serialize_as!(i8_:    -42i8                => "<root>-42</root>");
695        serialize_as!(i16_:   -4200i16             => "<root>-4200</root>");
696        serialize_as!(i32_:   -42000000i32         => "<root>-42000000</root>");
697        serialize_as!(i64_:   -42000000000000i64   => "<root>-42000000000000</root>");
698        serialize_as!(isize_: -42000000isize       => "<root>-42000000</root>");
699
700        serialize_as!(u8_:    42u8                => "<root>42</root>");
701        serialize_as!(u16_:   4200u16             => "<root>4200</root>");
702        serialize_as!(u32_:   42000000u32         => "<root>42000000</root>");
703        serialize_as!(u64_:   42000000000000u64   => "<root>42000000000000</root>");
704        serialize_as!(usize_: 42000000usize       => "<root>42000000</root>");
705
706        serialize_as!(i128_: -420000000000000000000000000000i128 => "<root>-420000000000000000000000000000</root>");
707        serialize_as!(u128_:  420000000000000000000000000000u128 => "<root>420000000000000000000000000000</root>");
708
709        serialize_as!(f32_: 4.2f32 => "<root>4.2</root>");
710        serialize_as!(f64_: 4.2f64 => "<root>4.2</root>");
711
712        serialize_as!(char_non_escaped: 'h' => "<root>h</root>");
713        serialize_as!(char_lt:   '<' => "<root>&lt;</root>");
714        serialize_as!(char_gt:   '>' => "<root>&gt;</root>");
715        serialize_as!(char_amp:  '&' => "<root>&amp;</root>");
716        serialize_as!(char_apos: '\'' => "<root>&apos;</root>");
717        serialize_as!(char_quot: '"' => "<root>&quot;</root>");
718
719        serialize_as!(str_non_escaped: "non-escaped string" => "<root>non-escaped string</root>");
720        serialize_as!(str_escaped: "<\"escaped & string'>" => "<root>&lt;&quot;escaped &amp; string&apos;&gt;</root>");
721
722        err!(bytes: Bytes(b"<\"escaped & bytes'>") => Unsupported("`serialize_bytes` not supported yet"));
723
724        serialize_as!(option_none: Option::<&str>::None => "<root/>");
725        serialize_as!(option_some: Some("non-escaped string") => "<root>non-escaped string</root>");
726        serialize_as!(option_some_empty_str: Some("") => "<root/>");
727
728        serialize_as!(unit: () => "<root/>");
729        serialize_as!(unit_struct: Unit => "<root/>");
730        serialize_as!(unit_struct_escaped: UnitEscaped => "<root/>");
731
732        serialize_as!(enum_unit: Enum::Unit => "<root>Unit</root>");
733        serialize_as!(enum_unit_escaped: Enum::UnitEscaped => "<root>&lt;&quot;&amp;&apos;&gt;</root>");
734
735        serialize_as!(newtype: Newtype(42) => "<root>42</root>");
736        err!(enum_newtype: Enum::Newtype(42)
737            => Unsupported("cannot serialize enum newtype variant `Enum::Newtype`"));
738
739        serialize_as!(seq: vec![1, 2, 3]
740            => "<root>1</root>\
741                <root>2</root>\
742                <root>3</root>");
743        serialize_as!(seq_empty: Vec::<usize>::new() => "");
744        serialize_as!(tuple: ("<\"&'>", "with\t\n\r spaces", 3usize)
745            => "<root>&lt;&quot;&amp;&apos;&gt;</root>\
746                <root>with\t\n\r spaces</root>\
747                <root>3</root>");
748        serialize_as!(tuple_struct: Tuple("first", 42)
749            => "<root>first</root>\
750                <root>42</root>");
751        err!(enum_tuple: Enum::Tuple("first", 42)
752            => Unsupported("cannot serialize enum tuple variant `Enum::Tuple`"));
753
754        serialize_as!(map: BTreeMap::from([("_1", 2), ("_3", 4)])
755            => "<root>\
756                    <_1>2</_1>\
757                    <_3>4</_3>\
758                </root>");
759        serialize_as!(struct_: Struct { key: "answer", val: (42, 42) }
760            => "<root>\
761                    <key>answer</key>\
762                    <val>42</val>\
763                    <val>42</val>\
764                </root>");
765        err!(enum_struct: Enum::Struct { key: "answer", val: (42, 42) }
766            => Unsupported("cannot serialize enum struct variant `Enum::Struct`"));
767
768        /// Special field name `$text` should be serialized as text content.
769        /// Sequences serialized as an `xs:list` content
770        mod text_field {
771            use super::*;
772
773            /// `$text` key in a map
774            mod map {
775                use super::*;
776                use pretty_assertions::assert_eq;
777
778                macro_rules! text {
779                    ($name:ident: $data:expr) => {
780                        serialize_as!($name:
781                            BTreeMap::from([("$text", $data)])
782                            => "<root/>");
783                    };
784                    ($name:ident: $data:expr => $expected:literal) => {
785                        serialize_as!($name:
786                            BTreeMap::from([("$text", $data)])
787                            => concat!("<root>", $expected,"</root>"));
788                    };
789                }
790
791                text!(false_: false => "false");
792                text!(true_:  true  => "true");
793
794                text!(i8_:    -42i8                => "-42");
795                text!(i16_:   -4200i16             => "-4200");
796                text!(i32_:   -42000000i32         => "-42000000");
797                text!(i64_:   -42000000000000i64   => "-42000000000000");
798                text!(isize_: -42000000isize       => "-42000000");
799
800                text!(u8_:    42u8                => "42");
801                text!(u16_:   4200u16             => "4200");
802                text!(u32_:   42000000u32         => "42000000");
803                text!(u64_:   42000000000000u64   => "42000000000000");
804                text!(usize_: 42000000usize       => "42000000");
805
806                text!(i128_: -420000000000000000000000000000i128 => "-420000000000000000000000000000");
807                text!(u128_:  420000000000000000000000000000u128 => "420000000000000000000000000000");
808
809                text!(f32_: 4.2f32 => "4.2");
810                text!(f64_: 4.2f64 => "4.2");
811
812                text!(char_non_escaped: 'h' => "h");
813                text!(char_lt:   '<' => "&lt;");
814                text!(char_gt:   '>' => "&gt;");
815                text!(char_amp:  '&' => "&amp;");
816                text!(char_apos: '\'' => "&apos;");
817                text!(char_quot: '"' => "&quot;");
818                text!(char_space: ' ' => " ");
819
820                text!(str_non_escaped: "non-escaped string" => "non-escaped string");
821                text!(str_escaped: "<\"escaped & string'>" => "&lt;&quot;escaped &amp; string&apos;&gt;");
822
823                err!(bytes:
824                    Text {
825                        before: "answer",
826                        content: Bytes(b"<\"escaped & bytes'>"),
827                        after: "answer",
828                    }
829                    => Unsupported("`serialize_bytes` not supported yet"));
830
831                text!(option_none: Option::<&str>::None);
832                text!(option_some: Some("non-escaped string") => "non-escaped string");
833                text!(option_some_empty_str: Some(""));
834
835                text!(unit: ());
836                text!(unit_struct: Unit);
837                text!(unit_struct_escaped: UnitEscaped);
838
839                text!(enum_unit: Enum::Unit => "Unit");
840                text!(enum_unit_escaped: Enum::UnitEscaped => "&lt;&quot;&amp;&apos;&gt;");
841
842                text!(newtype: Newtype(42) => "42");
843                // We have no space where name of a variant can be stored
844                err!(enum_newtype:
845                    Text {
846                        before: "answer",
847                        content: Enum::Newtype(42),
848                        after: "answer",
849                    }
850                    => Unsupported("cannot serialize enum newtype variant `Enum::Newtype` as text content value"));
851
852                // Sequences are serialized separated by spaces, all spaces inside are escaped
853                text!(seq: vec![1, 2, 3] => "1 2 3");
854                text!(seq_empty: Vec::<usize>::new());
855                text!(tuple: ("<\"&'>", "with\t\n\r spaces", 3usize)
856                    => "&lt;&quot;&amp;&apos;&gt; \
857                        with&#9;&#10;&#13;&#32;spaces \
858                        3");
859                text!(tuple_struct: Tuple("first", 42) => "first 42");
860                // We have no space where name of a variant can be stored
861                err!(enum_tuple:
862                    Text {
863                        before: "answer",
864                        content: Enum::Tuple("first", 42),
865                        after: "answer",
866                    }
867                    => Unsupported("cannot serialize enum tuple variant `Enum::Tuple` as text content value"));
868
869                // Complex types cannot be serialized in `$text` field
870                err!(map:
871                    Text {
872                        before: "answer",
873                        content: BTreeMap::from([("_1", 2), ("_3", 4)]),
874                        after: "answer",
875                    }
876                    => Unsupported("cannot serialize map as text content value"));
877                err!(struct_:
878                    Text {
879                        before: "answer",
880                        content: Struct { key: "answer", val: (42, 42) },
881                        after: "answer",
882                    }
883                    => Unsupported("cannot serialize struct `Struct` as text content value"));
884                err!(enum_struct:
885                    Text {
886                        before: "answer",
887                        content: Enum::Struct { key: "answer", val: (42, 42) },
888                        after: "answer",
889                    }
890                    => Unsupported("cannot serialize enum struct variant `Enum::Struct` as text content value"));
891            }
892
893            /// `$text` field inside a struct
894            mod struct_ {
895                use super::*;
896                use pretty_assertions::assert_eq;
897
898                macro_rules! text {
899                    ($name:ident: $data:expr => $expected:literal) => {
900                        serialize_as!($name:
901                            Text {
902                                before: "answer",
903                                content: $data,
904                                after: "answer",
905                            }
906                            => concat!(
907                                "<root><before>answer</before>",
908                                $expected,
909                                "<after>answer</after></root>",
910                            ));
911                    };
912                }
913
914                text!(false_: false => "false");
915                text!(true_:  true  => "true");
916
917                text!(i8_:    -42i8                => "-42");
918                text!(i16_:   -4200i16             => "-4200");
919                text!(i32_:   -42000000i32         => "-42000000");
920                text!(i64_:   -42000000000000i64   => "-42000000000000");
921                text!(isize_: -42000000isize       => "-42000000");
922
923                text!(u8_:    42u8                => "42");
924                text!(u16_:   4200u16             => "4200");
925                text!(u32_:   42000000u32         => "42000000");
926                text!(u64_:   42000000000000u64   => "42000000000000");
927                text!(usize_: 42000000usize       => "42000000");
928
929                text!(i128_: -420000000000000000000000000000i128 => "-420000000000000000000000000000");
930                text!(u128_:  420000000000000000000000000000u128 => "420000000000000000000000000000");
931
932                text!(f32_: 4.2f32 => "4.2");
933                text!(f64_: 4.2f64 => "4.2");
934
935                text!(char_non_escaped: 'h' => "h");
936                text!(char_lt:   '<' => "&lt;");
937                text!(char_gt:   '>' => "&gt;");
938                text!(char_amp:  '&' => "&amp;");
939                text!(char_apos: '\'' => "&apos;");
940                text!(char_quot: '"' => "&quot;");
941                text!(char_space: ' ' => " ");
942
943                text!(str_non_escaped: "non-escaped string" => "non-escaped string");
944                text!(str_escaped: "<\"escaped & string'>" => "&lt;&quot;escaped &amp; string&apos;&gt;");
945
946                err!(bytes:
947                    Text {
948                        before: "answer",
949                        content: Bytes(b"<\"escaped & bytes'>"),
950                        after: "answer",
951                    }
952                    => Unsupported("`serialize_bytes` not supported yet"));
953
954                text!(option_none: Option::<&str>::None => "");
955                text!(option_some: Some("non-escaped string") => "non-escaped string");
956                text!(option_some_empty_str: Some("") => "");
957
958                text!(unit: () => "");
959                text!(unit_struct: Unit => "");
960                text!(unit_struct_escaped: UnitEscaped => "");
961
962                text!(enum_unit: Enum::Unit => "Unit");
963                text!(enum_unit_escaped: Enum::UnitEscaped => "&lt;&quot;&amp;&apos;&gt;");
964
965                text!(newtype: Newtype(42) => "42");
966                // We have no space where name of a variant can be stored
967                err!(enum_newtype:
968                    Text {
969                        before: "answer",
970                        content: Enum::Newtype(42),
971                        after: "answer",
972                    }
973                    => Unsupported("cannot serialize enum newtype variant `Enum::Newtype` as text content value"));
974
975                // Sequences are serialized separated by spaces, all spaces inside are escaped
976                text!(seq: vec![1, 2, 3] => "1 2 3");
977                text!(seq_empty: Vec::<usize>::new() => "");
978                text!(tuple: ("<\"&'>", "with\t\n\r spaces", 3usize)
979                    => "&lt;&quot;&amp;&apos;&gt; \
980                        with&#9;&#10;&#13;&#32;spaces \
981                        3");
982                text!(tuple_struct: Tuple("first", 42) => "first 42");
983                // We have no space where name of a variant can be stored
984                err!(enum_tuple:
985                    Text {
986                        before: "answer",
987                        content: Enum::Tuple("first", 42),
988                        after: "answer",
989                    }
990                    => Unsupported("cannot serialize enum tuple variant `Enum::Tuple` as text content value"));
991
992                // Complex types cannot be serialized in `$text` field
993                err!(map:
994                    Text {
995                        before: "answer",
996                        content: BTreeMap::from([("_1", 2), ("_3", 4)]),
997                        after: "answer",
998                    }
999                    => Unsupported("cannot serialize map as text content value"));
1000                err!(struct_:
1001                    Text {
1002                        before: "answer",
1003                        content: Struct { key: "answer", val: (42, 42) },
1004                        after: "answer",
1005                    }
1006                    => Unsupported("cannot serialize struct `Struct` as text content value"));
1007                err!(enum_struct:
1008                    Text {
1009                        before: "answer",
1010                        content: Enum::Struct { key: "answer", val: (42, 42) },
1011                        after: "answer",
1012                    }
1013                    => Unsupported("cannot serialize enum struct variant `Enum::Struct` as text content value"));
1014            }
1015        }
1016
1017        /// Special field name `$value` should be serialized using name, provided
1018        /// by the type of value instead of a key. Sequences serialized as a list
1019        /// of tags with that name (each element can have their own name)
1020        mod value_field {
1021            use super::*;
1022
1023            /// `$value` key in a map
1024            mod map {
1025                use super::*;
1026                use pretty_assertions::assert_eq;
1027
1028                macro_rules! value {
1029                    ($name:ident: $data:expr) => {
1030                        serialize_as!($name:
1031                            BTreeMap::from([("$value", $data)])
1032                            => "<root/>");
1033                    };
1034                    ($name:ident: $data:expr => $expected:literal) => {
1035                        serialize_as!($name:
1036                            BTreeMap::from([("$value", $data)])
1037                            => concat!("<root>", $expected,"</root>"));
1038                    };
1039                }
1040
1041                value!(false_: false => "false");
1042                value!(true_:  true  => "true");
1043
1044                value!(i8_:    -42i8                => "-42");
1045                value!(i16_:   -4200i16             => "-4200");
1046                value!(i32_:   -42000000i32         => "-42000000");
1047                value!(i64_:   -42000000000000i64   => "-42000000000000");
1048                value!(isize_: -42000000isize       => "-42000000");
1049
1050                value!(u8_:    42u8                => "42");
1051                value!(u16_:   4200u16             => "4200");
1052                value!(u32_:   42000000u32         => "42000000");
1053                value!(u64_:   42000000000000u64   => "42000000000000");
1054                value!(usize_: 42000000usize       => "42000000");
1055
1056                value!(i128_: -420000000000000000000000000000i128 => "-420000000000000000000000000000");
1057                value!(u128_:  420000000000000000000000000000u128 => "420000000000000000000000000000");
1058
1059                value!(f32_: 4.2f32 => "4.2");
1060                value!(f64_: 4.2f64 => "4.2");
1061
1062                value!(char_non_escaped: 'h' => "h");
1063                value!(char_lt:   '<' => "&lt;");
1064                value!(char_gt:   '>' => "&gt;");
1065                value!(char_amp:  '&' => "&amp;");
1066                value!(char_apos: '\'' => "&apos;");
1067                value!(char_quot: '"' => "&quot;");
1068                value!(char_space: ' ' => " ");
1069
1070                value!(str_non_escaped: "non-escaped string" => "non-escaped string");
1071                value!(str_escaped: "<\"escaped & string'>" => "&lt;&quot;escaped &amp; string&apos;&gt;");
1072
1073                err!(bytes:
1074                    BTreeMap::from([("$value", Bytes(b"<\"escaped & bytes'>"))])
1075                    => Unsupported("`serialize_bytes` not supported yet"));
1076
1077                value!(option_none: Option::<&str>::None);
1078                value!(option_some: Some("non-escaped string") => "non-escaped string");
1079                value!(option_some_empty_str: Some(""));
1080
1081                value!(unit: ());
1082                value!(unit_struct: Unit);
1083                value!(unit_struct_escaped: UnitEscaped);
1084
1085                value!(enum_unit: Enum::Unit => "<Unit/>");
1086                err!(enum_unit_escaped:
1087                    BTreeMap::from([("$value", Enum::UnitEscaped)])
1088                    => Unsupported("character `<` is not allowed at the start of an XML name `<\"&'>`"));
1089
1090                value!(newtype: Newtype(42) => "42");
1091                value!(enum_newtype: Enum::Newtype(42) => "<Newtype>42</Newtype>");
1092
1093                // Note that sequences of primitives serialized without delimiters!
1094                err!(seq:
1095                    BTreeMap::from([("$value", vec![1, 2, 3])])
1096                    => Unsupported("consequent primitives would be serialized without delimiter and cannot be deserialized back"));
1097                value!(seq_empty: Vec::<usize>::new());
1098                err!(tuple:
1099                    BTreeMap::from([("$value", ("<\"&'>", "with\t\n\r spaces", 3usize))])
1100                    => Unsupported("consequent primitives would be serialized without delimiter and cannot be deserialized back"));
1101                err!(tuple_struct:
1102                    BTreeMap::from([("$value", Tuple("first", 42))])
1103                    => Unsupported("consequent primitives would be serialized without delimiter and cannot be deserialized back"));
1104                value!(enum_tuple: Enum::Tuple("first", 42)
1105                    => "<Tuple>first</Tuple>\
1106                        <Tuple>42</Tuple>");
1107
1108                // We cannot wrap map in any container and should not
1109                // flatten it, so it is impossible to serialize maps
1110                err!(map:
1111                    BTreeMap::from([("$value", BTreeMap::from([("_1", 2), ("_3", 4)]))])
1112                    => Unsupported("serialization of map types is not supported in `$value` field"));
1113                value!(struct_:
1114                    Struct { key: "answer", val: (42, 42) }
1115                    => "<Struct>\
1116                            <key>answer</key>\
1117                            <val>42</val>\
1118                            <val>42</val>\
1119                        </Struct>");
1120                value!(enum_struct:
1121                    Enum::Struct { key: "answer", val: (42, 42) }
1122                    => "<Struct>\
1123                            <key>answer</key>\
1124                            <val>42</val>\
1125                            <val>42</val>\
1126                        </Struct>");
1127            }
1128
1129            /// `$value` field inside a struct
1130            mod struct_ {
1131                use super::*;
1132                use pretty_assertions::assert_eq;
1133
1134                macro_rules! value {
1135                    ($name:ident: $data:expr => $expected:literal) => {
1136                        serialize_as!($name:
1137                            Value {
1138                                before: "answer",
1139                                content: $data,
1140                                after: "answer",
1141                            }
1142                            => concat!(
1143                                "<root><before>answer</before>",
1144                                $expected,
1145                                "<after>answer</after></root>",
1146                            ));
1147                    };
1148                }
1149
1150                value!(false_: false => "false");
1151                value!(true_:  true  => "true");
1152
1153                value!(i8_:    -42i8                => "-42");
1154                value!(i16_:   -4200i16             => "-4200");
1155                value!(i32_:   -42000000i32         => "-42000000");
1156                value!(i64_:   -42000000000000i64   => "-42000000000000");
1157                value!(isize_: -42000000isize       => "-42000000");
1158
1159                value!(u8_:    42u8                => "42");
1160                value!(u16_:   4200u16             => "4200");
1161                value!(u32_:   42000000u32         => "42000000");
1162                value!(u64_:   42000000000000u64   => "42000000000000");
1163                value!(usize_: 42000000usize       => "42000000");
1164
1165                value!(i128_: -420000000000000000000000000000i128 => "-420000000000000000000000000000");
1166                value!(u128_:  420000000000000000000000000000u128 => "420000000000000000000000000000");
1167
1168                value!(f32_: 4.2f32 => "4.2");
1169                value!(f64_: 4.2f64 => "4.2");
1170
1171                value!(char_non_escaped: 'h' => "h");
1172                value!(char_lt:   '<' => "&lt;");
1173                value!(char_gt:   '>' => "&gt;");
1174                value!(char_amp:  '&' => "&amp;");
1175                value!(char_apos: '\'' => "&apos;");
1176                value!(char_quot: '"' => "&quot;");
1177                value!(char_space: ' ' => " ");
1178
1179                value!(str_non_escaped: "non-escaped string" => "non-escaped string");
1180                value!(str_escaped: "<\"escaped & string'>" => "&lt;&quot;escaped &amp; string&apos;&gt;");
1181
1182                err!(bytes:
1183                    Value {
1184                        before: "answer",
1185                        content: Bytes(b"<\"escaped & bytes'>"),
1186                        after: "answer",
1187                    }
1188                    => Unsupported("`serialize_bytes` not supported yet"));
1189
1190                value!(option_none: Option::<&str>::None => "");
1191                value!(option_some: Some("non-escaped string") => "non-escaped string");
1192                value!(option_some_empty_str: Some("") => "");
1193
1194                value!(unit: () => "");
1195                value!(unit_struct: Unit => "");
1196                value!(unit_struct_escaped: UnitEscaped => "");
1197
1198                value!(enum_unit: Enum::Unit => "<Unit/>");
1199                err!(enum_unit_escaped:
1200                    Value {
1201                        before: "answer",
1202                        content: Enum::UnitEscaped,
1203                        after: "answer",
1204                    }
1205                    => Unsupported("character `<` is not allowed at the start of an XML name `<\"&'>`"));
1206
1207                value!(newtype: Newtype(42) => "42");
1208                value!(enum_newtype: Enum::Newtype(42) => "<Newtype>42</Newtype>");
1209
1210                // Note that sequences of primitives serialized without delimiters!
1211                err!(seq:
1212                    Value {
1213                        before: "answer",
1214                        content: vec![1, 2, 3],
1215                        after: "answer",
1216                    }
1217                    => Unsupported("consequent primitives would be serialized without delimiter and cannot be deserialized back"));
1218                value!(seq_empty: Vec::<usize>::new() => "");
1219                err!(tuple:
1220                    Value {
1221                        before: "answer",
1222                        content: ("<\"&'>", "with\t\n\r spaces", 3usize),
1223                        after: "answer",
1224                    }
1225                    => Unsupported("consequent primitives would be serialized without delimiter and cannot be deserialized back"));
1226                err!(tuple_struct:
1227                    Value {
1228                        before: "answer",
1229                        content: Tuple("first", 42),
1230                        after: "answer",
1231                    }
1232                    => Unsupported("consequent primitives would be serialized without delimiter and cannot be deserialized back"));
1233                value!(enum_tuple: Enum::Tuple("first", 42)
1234                    => "<Tuple>first</Tuple>\
1235                        <Tuple>42</Tuple>");
1236
1237                // We cannot wrap map in any container and should not
1238                // flatten it, so it is impossible to serialize maps
1239                err!(map:
1240                    Value {
1241                        before: "answer",
1242                        content: BTreeMap::from([("_1", 2), ("_3", 4)]),
1243                        after: "answer",
1244                    }
1245                    => Unsupported("serialization of map types is not supported in `$value` field"));
1246                value!(struct_:
1247                    Struct { key: "answer", val: (42, 42) }
1248                    => "<Struct>\
1249                            <key>answer</key>\
1250                            <val>42</val>\
1251                            <val>42</val>\
1252                        </Struct>");
1253                value!(enum_struct:
1254                    Enum::Struct { key: "answer", val: (42, 42) }
1255                    => "<Struct>\
1256                            <key>answer</key>\
1257                            <val>42</val>\
1258                            <val>42</val>\
1259                        </Struct>");
1260            }
1261        }
1262
1263        mod attributes {
1264            use super::*;
1265            use pretty_assertions::assert_eq;
1266
1267            serialize_as!(map_attr: BTreeMap::from([("@key1", 1), ("@key2", 2)])
1268                => r#"<root key1="1" key2="2"/>"#);
1269            serialize_as!(map_mixed: BTreeMap::from([("@key1", 1), ("key2", 2)])
1270                => r#"<root key1="1"><key2>2</key2></root>"#);
1271
1272            serialize_as!(struct_: Attributes { key: "answer", val: (42, 42) }
1273                => r#"<root key="answer" val="42 42"/>"#);
1274            serialize_as!(struct_before: AttributesBefore { key: "answer", val: 42 }
1275                => r#"<root key="answer"><val>42</val></root>"#);
1276            serialize_as!(struct_after: AttributesAfter { key: "answer", val: 42 }
1277                => r#"<root val="42"><key>answer</key></root>"#);
1278
1279            err!(enum_: Enum::Attributes { key: "answer", val: (42, 42) }
1280                => Unsupported("cannot serialize enum struct variant `Enum::Attributes`"));
1281
1282            /// Test for https://github.com/tafia/quick-xml/issues/252
1283            mod optional {
1284                use super::*;
1285                use pretty_assertions::assert_eq;
1286
1287                serialize_as!(none:
1288                    OptionalAttributes { a: None, b: None }
1289                    => r#"<root a=""/>"#);
1290                serialize_as!(some_empty_str:
1291                    OptionalAttributes {
1292                        a: Some(""),
1293                        b: Some(""),
1294                    }
1295                    => r#"<root a="" b=""/>"#);
1296                serialize_as!(some_non_empty:
1297                    OptionalAttributes {
1298                        a: Some("1"),
1299                        b: Some("2"),
1300                    }
1301                    => r#"<root a="1" b="2"/>"#);
1302            }
1303        }
1304
1305        /// Test for https://github.com/tafia/quick-xml/issues/252
1306        mod optional {
1307            use super::*;
1308            use pretty_assertions::assert_eq;
1309
1310            serialize_as!(none:
1311                OptionalElements { a: None, b: None }
1312                => "<root>\
1313                        <a/>\
1314                    </root>");
1315            serialize_as!(some_empty_str:
1316                OptionalElements {
1317                    a: Some(""),
1318                    b: Some(""),
1319                }
1320                => "<root>\
1321                        <a/>\
1322                        <b/>\
1323                    </root>");
1324            serialize_as!(some_non_empty:
1325                OptionalElements {
1326                    a: Some("1"),
1327                    b: Some("2"),
1328                }
1329                => "<root>\
1330                        <a>1</a>\
1331                        <b>2</b>\
1332                    </root>");
1333        }
1334    }
1335
1336    mod with_indent {
1337        use super::*;
1338        use crate::se::content::tests::Struct;
1339        use crate::writer::Indentation;
1340        use pretty_assertions::assert_eq;
1341
1342        /// Checks that given `$data` successfully serialized as `$expected`.
1343        /// Writes `$data` using [`ElementSerializer`] with indent of two spaces.
1344        macro_rules! serialize_as {
1345            ($name:ident: $data:expr => $expected:expr) => {
1346                #[test]
1347                fn $name() {
1348                    let mut buffer = String::new();
1349                    let ser = ElementSerializer {
1350                        ser: ContentSerializer {
1351                            writer: &mut buffer,
1352                            level: QuoteLevel::Full,
1353                            indent: Indent::Owned(Indentation::new(b' ', 2)),
1354                            write_indent: false,
1355                            text_format: TextFormat::Text,
1356                            allow_primitive: true,
1357                            empty_element_handling: EmptyElementHandling::SelfClosed,
1358                        },
1359                        key: XmlName("root"),
1360                    };
1361
1362                    let result = $data.serialize(ser).unwrap();
1363                    assert_eq!(buffer, $expected);
1364                    assert_eq!(result, WriteResult::Element);
1365                }
1366            };
1367        }
1368
1369        /// Checks that attempt to serialize given `$data` results to a
1370        /// serialization error `$kind` with `$reason`
1371        macro_rules! err {
1372            ($name:ident: $data:expr => $kind:ident($reason:literal)) => {
1373                #[test]
1374                fn $name() {
1375                    let mut buffer = String::new();
1376                    let ser = ElementSerializer {
1377                        ser: ContentSerializer {
1378                            writer: &mut buffer,
1379                            level: QuoteLevel::Full,
1380                            indent: Indent::Owned(Indentation::new(b' ', 2)),
1381                            write_indent: false,
1382                            text_format: TextFormat::Text,
1383                            allow_primitive: true,
1384                            empty_element_handling: EmptyElementHandling::SelfClosed,
1385                        },
1386                        key: XmlName("root"),
1387                    };
1388
1389                    match $data.serialize(ser).unwrap_err() {
1390                        SeError::$kind(e) => assert_eq!(e, $reason),
1391                        e => panic!(
1392                            "Expected `Err({}({}))`, but got `{:?}`",
1393                            stringify!($kind),
1394                            $reason,
1395                            e
1396                        ),
1397                    }
1398                    // We can write something before fail
1399                    // assert_eq!(buffer, "");
1400                }
1401            };
1402        }
1403
1404        serialize_as!(false_: false => "<root>false</root>");
1405        serialize_as!(true_:  true  => "<root>true</root>");
1406
1407        serialize_as!(i8_:    -42i8                => "<root>-42</root>");
1408        serialize_as!(i16_:   -4200i16             => "<root>-4200</root>");
1409        serialize_as!(i32_:   -42000000i32         => "<root>-42000000</root>");
1410        serialize_as!(i64_:   -42000000000000i64   => "<root>-42000000000000</root>");
1411        serialize_as!(isize_: -42000000isize       => "<root>-42000000</root>");
1412
1413        serialize_as!(u8_:    42u8                => "<root>42</root>");
1414        serialize_as!(u16_:   4200u16             => "<root>4200</root>");
1415        serialize_as!(u32_:   42000000u32         => "<root>42000000</root>");
1416        serialize_as!(u64_:   42000000000000u64   => "<root>42000000000000</root>");
1417        serialize_as!(usize_: 42000000usize       => "<root>42000000</root>");
1418
1419        serialize_as!(i128_: -420000000000000000000000000000i128 => "<root>-420000000000000000000000000000</root>");
1420        serialize_as!(u128_:  420000000000000000000000000000u128 => "<root>420000000000000000000000000000</root>");
1421
1422        serialize_as!(f32_: 4.2f32 => "<root>4.2</root>");
1423        serialize_as!(f64_: 4.2f64 => "<root>4.2</root>");
1424
1425        serialize_as!(char_non_escaped: 'h' => "<root>h</root>");
1426        serialize_as!(char_lt:   '<' => "<root>&lt;</root>");
1427        serialize_as!(char_gt:   '>' => "<root>&gt;</root>");
1428        serialize_as!(char_amp:  '&' => "<root>&amp;</root>");
1429        serialize_as!(char_apos: '\'' => "<root>&apos;</root>");
1430        serialize_as!(char_quot: '"' => "<root>&quot;</root>");
1431        serialize_as!(char_space: ' ' => "<root> </root>");
1432
1433        serialize_as!(str_non_escaped: "non-escaped string" => "<root>non-escaped string</root>");
1434        serialize_as!(str_escaped: "<\"escaped & string'>" => "<root>&lt;&quot;escaped &amp; string&apos;&gt;</root>");
1435
1436        err!(bytes: Bytes(b"<\"escaped & bytes'>") => Unsupported("`serialize_bytes` not supported yet"));
1437
1438        serialize_as!(option_none: Option::<&str>::None => "<root/>");
1439        serialize_as!(option_some: Some("non-escaped string") => "<root>non-escaped string</root>");
1440        serialize_as!(option_some_empty: Some("") => "<root/>");
1441
1442        serialize_as!(unit: () => "<root/>");
1443        serialize_as!(unit_struct: Unit => "<root/>");
1444        serialize_as!(unit_struct_escaped: UnitEscaped => "<root/>");
1445
1446        serialize_as!(enum_unit: Enum::Unit => "<root>Unit</root>");
1447        serialize_as!(enum_unit_escaped: Enum::UnitEscaped => "<root>&lt;&quot;&amp;&apos;&gt;</root>");
1448
1449        serialize_as!(newtype: Newtype(42) => "<root>42</root>");
1450        err!(enum_newtype: Enum::Newtype(42)
1451            => Unsupported("cannot serialize enum newtype variant `Enum::Newtype`"));
1452
1453        serialize_as!(seq: vec![1, 2, 3]
1454            => "<root>1</root>\n\
1455                <root>2</root>\n\
1456                <root>3</root>");
1457        serialize_as!(seq_empty: Vec::<usize>::new() => "");
1458        serialize_as!(tuple: ("<\"&'>", "with\t\n\r spaces", 3usize)
1459            => "<root>&lt;&quot;&amp;&apos;&gt;</root>\n\
1460                <root>with\t\n\r spaces</root>\n\
1461                <root>3</root>");
1462        serialize_as!(tuple_struct: Tuple("first", 42)
1463            => "<root>first</root>\n\
1464                <root>42</root>");
1465        err!(enum_tuple: Enum::Tuple("first", 42)
1466            => Unsupported("cannot serialize enum tuple variant `Enum::Tuple`"));
1467
1468        serialize_as!(map: BTreeMap::from([("_1", 2), ("_3", 4)])
1469            => "<root>\n  \
1470                    <_1>2</_1>\n  \
1471                    <_3>4</_3>\n\
1472                </root>");
1473        serialize_as!(struct_: Struct { key: "answer", val: (42, 42) }
1474            => "<root>\n  \
1475                    <key>answer</key>\n  \
1476                    <val>42</val>\n  \
1477                    <val>42</val>\n\
1478                </root>");
1479        err!(enum_struct: Enum::Struct { key: "answer", val: (42, 42) }
1480            => Unsupported("cannot serialize enum struct variant `Enum::Struct`"));
1481
1482        /// Special field name `$text` should be serialized as text content.
1483        /// Sequences serialized as an `xs:list` content
1484        mod text_field {
1485            use super::*;
1486
1487            /// `$text` key in a map
1488            mod map {
1489                use super::*;
1490                use pretty_assertions::assert_eq;
1491
1492                macro_rules! text {
1493                    ($name:ident: $data:expr) => {
1494                        serialize_as!($name:
1495                            // Serialization started from ElementSerializer::serialize_map
1496                            BTreeMap::from([("$text", $data)])
1497                            => "<root/>");
1498                    };
1499                    ($name:ident: $data:expr => $expected:literal) => {
1500                        serialize_as!($name:
1501                            // Serialization started from ElementSerializer::serialize_map
1502                            BTreeMap::from([("$text", $data)])
1503                            => concat!("<root>", $expected,"</root>"));
1504                    };
1505                }
1506
1507                text!(false_: false => "false");
1508                text!(true_:  true  => "true");
1509
1510                text!(i8_:    -42i8                => "-42");
1511                text!(i16_:   -4200i16             => "-4200");
1512                text!(i32_:   -42000000i32         => "-42000000");
1513                text!(i64_:   -42000000000000i64   => "-42000000000000");
1514                text!(isize_: -42000000isize       => "-42000000");
1515
1516                text!(u8_:    42u8                => "42");
1517                text!(u16_:   4200u16             => "4200");
1518                text!(u32_:   42000000u32         => "42000000");
1519                text!(u64_:   42000000000000u64   => "42000000000000");
1520                text!(usize_: 42000000usize       => "42000000");
1521
1522                text!(i128_: -420000000000000000000000000000i128 => "-420000000000000000000000000000");
1523                text!(u128_:  420000000000000000000000000000u128 => "420000000000000000000000000000");
1524
1525                text!(f32_: 4.2f32 => "4.2");
1526                text!(f64_: 4.2f64 => "4.2");
1527
1528                text!(char_non_escaped: 'h' => "h");
1529                text!(char_lt:   '<' => "&lt;");
1530                text!(char_gt:   '>' => "&gt;");
1531                text!(char_amp:  '&' => "&amp;");
1532                text!(char_apos: '\'' => "&apos;");
1533                text!(char_quot: '"' => "&quot;");
1534                text!(char_space: ' ' => " ");
1535
1536                text!(str_non_escaped: "non-escaped string" => "non-escaped string");
1537                text!(str_escaped: "<\"escaped & string'>" => "&lt;&quot;escaped &amp; string&apos;&gt;");
1538
1539                err!(bytes:
1540                    Text {
1541                        before: "answer",
1542                        content: Bytes(b"<\"escaped & bytes'>"),
1543                        after: "answer",
1544                    }
1545                    => Unsupported("`serialize_bytes` not supported yet"));
1546
1547                text!(option_none: Option::<&str>::None);
1548                text!(option_some: Some("non-escaped string") => "non-escaped string");
1549                text!(option_some_empty_str: Some(""));
1550
1551                text!(unit: ());
1552                text!(unit_struct: Unit);
1553                text!(unit_struct_escaped: UnitEscaped);
1554
1555                text!(enum_unit: Enum::Unit => "Unit");
1556                text!(enum_unit_escaped: Enum::UnitEscaped => "&lt;&quot;&amp;&apos;&gt;");
1557
1558                text!(newtype: Newtype(42) => "42");
1559                // We have no space where name of a variant can be stored
1560                err!(enum_newtype:
1561                    Text {
1562                        before: "answer",
1563                        content: Enum::Newtype(42),
1564                        after: "answer",
1565                    }
1566                    => Unsupported("cannot serialize enum newtype variant `Enum::Newtype` as text content value"));
1567
1568                // Sequences are serialized separated by spaces, all spaces inside are escaped
1569                text!(seq: vec![1, 2, 3] => "1 2 3");
1570                text!(seq_empty: Vec::<usize>::new());
1571                text!(tuple: ("<\"&'>", "with\t\n\r spaces", 3usize)
1572                    => "&lt;&quot;&amp;&apos;&gt; \
1573                        with&#9;&#10;&#13;&#32;spaces \
1574                        3");
1575                text!(tuple_struct: Tuple("first", 42) => "first 42");
1576                // We have no space where name of a variant can be stored
1577                err!(enum_tuple:
1578                    Text {
1579                        before: "answer",
1580                        content: Enum::Tuple("first", 42),
1581                        after: "answer",
1582                    }
1583                    => Unsupported("cannot serialize enum tuple variant `Enum::Tuple` as text content value"));
1584
1585                // Complex types cannot be serialized in `$text` field
1586                err!(map:
1587                    Text {
1588                        before: "answer",
1589                        content: BTreeMap::from([("_1", 2), ("_3", 4)]),
1590                        after: "answer",
1591                    }
1592                    => Unsupported("cannot serialize map as text content value"));
1593                err!(struct_:
1594                    Text {
1595                        before: "answer",
1596                        content: Struct { key: "answer", val: (42, 42) },
1597                        after: "answer",
1598                    }
1599                    => Unsupported("cannot serialize struct `Struct` as text content value"));
1600                err!(enum_struct:
1601                    Text {
1602                        before: "answer",
1603                        content: Enum::Struct { key: "answer", val: (42, 42) },
1604                        after: "answer",
1605                    }
1606                    => Unsupported("cannot serialize enum struct variant `Enum::Struct` as text content value"));
1607            }
1608
1609            /// `$text` field inside a struct
1610            mod struct_ {
1611                use super::*;
1612                use pretty_assertions::assert_eq;
1613
1614                macro_rules! text {
1615                    ($name:ident: $data:expr => $expected:literal) => {
1616                        serialize_as!($name:
1617                            // Serialization started from ElementSerializer::serialize_struct
1618                            Text {
1619                                before: "answer",
1620                                content: $data,
1621                                after: "answer",
1622                            }
1623                            => concat!(
1624                                "<root>\n  <before>answer</before>",
1625                                $expected,
1626                                "<after>answer</after>\n</root>",
1627                            ));
1628                    };
1629                }
1630
1631                text!(false_: false => "false");
1632                text!(true_:  true  => "true");
1633
1634                text!(i8_:    -42i8                => "-42");
1635                text!(i16_:   -4200i16             => "-4200");
1636                text!(i32_:   -42000000i32         => "-42000000");
1637                text!(i64_:   -42000000000000i64   => "-42000000000000");
1638                text!(isize_: -42000000isize       => "-42000000");
1639
1640                text!(u8_:    42u8                => "42");
1641                text!(u16_:   4200u16             => "4200");
1642                text!(u32_:   42000000u32         => "42000000");
1643                text!(u64_:   42000000000000u64   => "42000000000000");
1644                text!(usize_: 42000000usize       => "42000000");
1645
1646                text!(i128_: -420000000000000000000000000000i128 => "-420000000000000000000000000000");
1647                text!(u128_:  420000000000000000000000000000u128 => "420000000000000000000000000000");
1648
1649                text!(f32_: 4.2f32 => "4.2");
1650                text!(f64_: 4.2f64 => "4.2");
1651
1652                text!(char_non_escaped: 'h' => "h");
1653                text!(char_lt:   '<' => "&lt;");
1654                text!(char_gt:   '>' => "&gt;");
1655                text!(char_amp:  '&' => "&amp;");
1656                text!(char_apos: '\'' => "&apos;");
1657                text!(char_quot: '"' => "&quot;");
1658                text!(char_space: ' ' => " ");
1659
1660                text!(str_non_escaped: "non-escaped string" => "non-escaped string");
1661                text!(str_escaped: "<\"escaped & string'>" => "&lt;&quot;escaped &amp; string&apos;&gt;");
1662
1663                err!(bytes:
1664                    Text {
1665                        before: "answer",
1666                        content: Bytes(b"<\"escaped & bytes'>"),
1667                        after: "answer",
1668                    }
1669                    => Unsupported("`serialize_bytes` not supported yet"));
1670
1671                text!(option_none: Option::<&str>::None => "");
1672                text!(option_some: Some("non-escaped string") => "non-escaped string");
1673                text!(option_some_empty_str: Some("") => "");
1674
1675                text!(unit: () => "");
1676                text!(unit_struct: Unit => "");
1677                text!(unit_struct_escaped: UnitEscaped => "");
1678
1679                text!(enum_unit: Enum::Unit => "Unit");
1680                text!(enum_unit_escaped: Enum::UnitEscaped => "&lt;&quot;&amp;&apos;&gt;");
1681
1682                text!(newtype: Newtype(42) => "42");
1683                // We have no space where name of a variant can be stored
1684                err!(enum_newtype:
1685                    Text {
1686                        before: "answer",
1687                        content: Enum::Newtype(42),
1688                        after: "answer",
1689                    }
1690                    => Unsupported("cannot serialize enum newtype variant `Enum::Newtype` as text content value"));
1691
1692                // Sequences are serialized separated by spaces, all spaces inside are escaped
1693                text!(seq: vec![1, 2, 3] => "1 2 3");
1694                text!(seq_empty: Vec::<usize>::new() => "");
1695                text!(tuple: ("<\"&'>", "with\t\n\r spaces", 3usize)
1696                    => "&lt;&quot;&amp;&apos;&gt; \
1697                        with&#9;&#10;&#13;&#32;spaces \
1698                        3");
1699                text!(tuple_struct: Tuple("first", 42) => "first 42");
1700                // We have no space where name of a variant can be stored
1701                err!(enum_tuple:
1702                    Text {
1703                        before: "answer",
1704                        content: Enum::Tuple("first", 42),
1705                        after: "answer",
1706                    }
1707                    => Unsupported("cannot serialize enum tuple variant `Enum::Tuple` as text content value"));
1708
1709                // Complex types cannot be serialized in `$text` field
1710                err!(map:
1711                    Text {
1712                        before: "answer",
1713                        content: BTreeMap::from([("_1", 2), ("_3", 4)]),
1714                        after: "answer",
1715                    }
1716                    => Unsupported("cannot serialize map as text content value"));
1717                err!(struct_:
1718                    Text {
1719                        before: "answer",
1720                        content: Struct { key: "answer", val: (42, 42) },
1721                        after: "answer",
1722                    }
1723                    => Unsupported("cannot serialize struct `Struct` as text content value"));
1724                err!(enum_struct:
1725                    Text {
1726                        before: "answer",
1727                        content: Enum::Struct { key: "answer", val: (42, 42) },
1728                        after: "answer",
1729                    }
1730                    => Unsupported("cannot serialize enum struct variant `Enum::Struct` as text content value"));
1731            }
1732        }
1733
1734        /// Special field name `$value` should be serialized using name, provided
1735        /// by the type of value instead of a key. Sequences serialized as a list
1736        /// of tags with that name (each element can have their own name)
1737        mod value_field {
1738            use super::*;
1739
1740            /// `$value` key in a map
1741            mod map {
1742                use super::*;
1743                use pretty_assertions::assert_eq;
1744
1745                macro_rules! value {
1746                    ($name:ident: $data:expr) => {
1747                        serialize_as!($name:
1748                            // Serialization started from ElementSerializer::serialize_map
1749                            BTreeMap::from([("$value", $data)])
1750                            => "<root/>");
1751                    };
1752                    ($name:ident: $data:expr => $expected:literal) => {
1753                        serialize_as!($name:
1754                            // Serialization started from ElementSerializer::serialize_map
1755                            BTreeMap::from([("$value", $data)])
1756                            => concat!("<root>", $expected,"</root>"));
1757                    };
1758                }
1759
1760                value!(false_: false => "false");
1761                value!(true_:  true  => "true");
1762
1763                value!(i8_:    -42i8                => "-42");
1764                value!(i16_:   -4200i16             => "-4200");
1765                value!(i32_:   -42000000i32         => "-42000000");
1766                value!(i64_:   -42000000000000i64   => "-42000000000000");
1767                value!(isize_: -42000000isize       => "-42000000");
1768
1769                value!(u8_:    42u8                => "42");
1770                value!(u16_:   4200u16             => "4200");
1771                value!(u32_:   42000000u32         => "42000000");
1772                value!(u64_:   42000000000000u64   => "42000000000000");
1773                value!(usize_: 42000000usize       => "42000000");
1774
1775                value!(i128_: -420000000000000000000000000000i128 => "-420000000000000000000000000000");
1776                value!(u128_:  420000000000000000000000000000u128 => "420000000000000000000000000000");
1777
1778                value!(f32_: 4.2f32 => "4.2");
1779                value!(f64_: 4.2f64 => "4.2");
1780
1781                value!(char_non_escaped: 'h' => "h");
1782                value!(char_lt:   '<' => "&lt;");
1783                value!(char_gt:   '>' => "&gt;");
1784                value!(char_amp:  '&' => "&amp;");
1785                value!(char_apos: '\'' => "&apos;");
1786                value!(char_quot: '"' => "&quot;");
1787                value!(char_space: ' ' => " ");
1788
1789                value!(str_non_escaped: "non-escaped string" => "non-escaped string");
1790                value!(str_escaped: "<\"escaped & string'>" => "&lt;&quot;escaped &amp; string&apos;&gt;");
1791
1792                err!(bytes:
1793                    BTreeMap::from([("$value", Bytes(b"<\"escaped & bytes'>"))])
1794                    => Unsupported("`serialize_bytes` not supported yet"));
1795
1796                value!(option_none: Option::<&str>::None);
1797                value!(option_some: Some("non-escaped string") => "non-escaped string");
1798                value!(option_some_empty_str: Some(""));
1799
1800                value!(unit: ());
1801                value!(unit_struct: Unit);
1802                value!(unit_struct_escaped: UnitEscaped);
1803
1804                value!(enum_unit: Enum::Unit => "\n  <Unit/>\n");
1805                err!(enum_unit_escaped:
1806                    BTreeMap::from([("$value", Enum::UnitEscaped)])
1807                    => Unsupported("character `<` is not allowed at the start of an XML name `<\"&'>`"));
1808
1809                value!(newtype: Newtype(42) => "42");
1810                value!(enum_newtype: Enum::Newtype(42) => "\n  <Newtype>42</Newtype>\n");
1811
1812                err!(seq:
1813                    BTreeMap::from([("$value", vec![1, 2, 3])])
1814                    => Unsupported("consequent primitives would be serialized without delimiter and cannot be deserialized back"));
1815                value!(seq_empty: Vec::<usize>::new());
1816                err!(tuple:
1817                    BTreeMap::from([("$value", ("<\"&'>", "with\t\n\r spaces", 3usize))])
1818                    => Unsupported("consequent primitives would be serialized without delimiter and cannot be deserialized back"));
1819                err!(tuple_struct:
1820                    BTreeMap::from([("$value", Tuple("first", 42))])
1821                    => Unsupported("consequent primitives would be serialized without delimiter and cannot be deserialized back"));
1822                value!(enum_tuple: Enum::Tuple("first", 42)
1823                    => "\n  \
1824                        <Tuple>first</Tuple>\n  \
1825                        <Tuple>42</Tuple>\n");
1826
1827                // We cannot wrap map in any container and should not
1828                // flatten it, so it is impossible to serialize maps
1829                err!(map:
1830                    BTreeMap::from([("$value", BTreeMap::from([("_1", 2), ("_3", 4)]))])
1831                    => Unsupported("serialization of map types is not supported in `$value` field"));
1832                value!(struct_:
1833                    Struct { key: "answer", val: (42, 42) }
1834                    => "\n  \
1835                        <Struct>\n    \
1836                            <key>answer</key>\n    \
1837                            <val>42</val>\n    \
1838                            <val>42</val>\n  \
1839                        </Struct>\n");
1840                value!(enum_struct:
1841                    Enum::Struct { key: "answer", val: (42, 42) }
1842                    => "\n  \
1843                        <Struct>\n    \
1844                            <key>answer</key>\n    \
1845                            <val>42</val>\n    \
1846                            <val>42</val>\n  \
1847                        </Struct>\n");
1848            }
1849
1850            /// `$value` field inside a struct
1851            mod struct_ {
1852                use super::*;
1853                use pretty_assertions::assert_eq;
1854
1855                macro_rules! value {
1856                    ($name:ident: $data:expr => $expected:literal) => {
1857                        serialize_as!($name:
1858                            // Serialization started from ElementSerializer::serialize_struct
1859                            Value {
1860                                before: "answer",
1861                                content: $data,
1862                                after: "answer",
1863                            }
1864                            => concat!(
1865                                "<root>\n  <before>answer</before>",
1866                                $expected,
1867                                "<after>answer</after>\n</root>",
1868                            ));
1869                    };
1870                }
1871
1872                value!(false_: false => "false");
1873                value!(true_:  true  => "true");
1874
1875                value!(i8_:    -42i8                => "-42");
1876                value!(i16_:   -4200i16             => "-4200");
1877                value!(i32_:   -42000000i32         => "-42000000");
1878                value!(i64_:   -42000000000000i64   => "-42000000000000");
1879                value!(isize_: -42000000isize       => "-42000000");
1880
1881                value!(u8_:    42u8                => "42");
1882                value!(u16_:   4200u16             => "4200");
1883                value!(u32_:   42000000u32         => "42000000");
1884                value!(u64_:   42000000000000u64   => "42000000000000");
1885                value!(usize_: 42000000usize       => "42000000");
1886
1887                value!(i128_: -420000000000000000000000000000i128 => "-420000000000000000000000000000");
1888                value!(u128_:  420000000000000000000000000000u128 => "420000000000000000000000000000");
1889
1890                value!(f32_: 4.2f32 => "4.2");
1891                value!(f64_: 4.2f64 => "4.2");
1892
1893                value!(char_non_escaped: 'h' => "h");
1894                value!(char_lt:   '<' => "&lt;");
1895                value!(char_gt:   '>' => "&gt;");
1896                value!(char_amp:  '&' => "&amp;");
1897                value!(char_apos: '\'' => "&apos;");
1898                value!(char_quot: '"' => "&quot;");
1899                value!(char_space: ' ' => " ");
1900
1901                value!(str_non_escaped: "non-escaped string" => "non-escaped string");
1902                value!(str_escaped: "<\"escaped & string'>" => "&lt;&quot;escaped &amp; string&apos;&gt;");
1903
1904                err!(bytes:
1905                    Value {
1906                        before: "answer",
1907                        content: Bytes(b"<\"escaped & bytes'>"),
1908                        after: "answer",
1909                    }
1910                    => Unsupported("`serialize_bytes` not supported yet"));
1911
1912                value!(option_none: Option::<&str>::None => "");
1913                value!(option_some: Some("non-escaped string") => "non-escaped string");
1914                value!(option_some_empty_str: Some("") => "");
1915
1916                value!(unit: () => "\n  ");
1917                value!(unit_struct: Unit => "\n  ");
1918                value!(unit_struct_escaped: UnitEscaped => "\n  ");
1919
1920                value!(enum_unit: Enum::Unit => "\n  <Unit/>\n  ");
1921                err!(enum_unit_escaped:
1922                    Value {
1923                        before: "answer",
1924                        content: Enum::UnitEscaped,
1925                        after: "answer",
1926                    }
1927                    => Unsupported("character `<` is not allowed at the start of an XML name `<\"&'>`"));
1928
1929                value!(newtype: Newtype(42) => "42");
1930                value!(enum_newtype: Enum::Newtype(42) => "\n  <Newtype>42</Newtype>\n  ");
1931
1932                err!(seq:
1933                    Value {
1934                        before: "answer",
1935                        content: vec![1, 2, 3],
1936                        after: "answer",
1937                    }
1938                    => Unsupported("consequent primitives would be serialized without delimiter and cannot be deserialized back"));
1939                value!(seq_empty: Vec::<usize>::new() => "");
1940                err!(tuple:
1941                    Value {
1942                        before: "answer",
1943                        content: ("<\"&'>", "with\t\n\r spaces", 3usize),
1944                        after: "answer",
1945                    }
1946                    => Unsupported("consequent primitives would be serialized without delimiter and cannot be deserialized back"));
1947                err!(tuple_struct:
1948                    Value {
1949                        before: "answer",
1950                        content: Tuple("first", 42),
1951                        after: "answer",
1952                    }
1953                    => Unsupported("consequent primitives would be serialized without delimiter and cannot be deserialized back"));
1954                value!(enum_tuple: Enum::Tuple("first", 42)
1955                    => "\n  \
1956                        <Tuple>first</Tuple>\n  \
1957                        <Tuple>42</Tuple>\n  ");
1958
1959                // We cannot wrap map in any container and should not
1960                // flatten it, so it is impossible to serialize maps
1961                err!(map:
1962                    Value {
1963                        before: "answer",
1964                        content: BTreeMap::from([("_1", 2), ("_3", 4)]),
1965                        after: "answer",
1966                    }
1967                    => Unsupported("serialization of map types is not supported in `$value` field"));
1968                value!(struct_:
1969                    Value {
1970                        before: "answer",
1971                        content: Struct { key: "answer", val: (42, 42) },
1972                        after: "answer",
1973                    }
1974                    => "\n  \
1975                        <Value>\n    \
1976                            <before>answer</before>\n    \
1977                            <Struct>\n      \
1978                                <key>answer</key>\n      \
1979                                <val>42</val>\n      \
1980                                <val>42</val>\n    \
1981                            </Struct>\n    \
1982                            <after>answer</after>\n  \
1983                        </Value>\n  ");
1984                value!(enum_struct:
1985                    Enum::Struct { key: "answer", val: (42, 42) }
1986                    => "\n  \
1987                        <Struct>\n    \
1988                            <key>answer</key>\n    \
1989                            <val>42</val>\n    \
1990                            <val>42</val>\n  \
1991                        </Struct>\n  ");
1992            }
1993        }
1994
1995        mod attributes {
1996            use super::*;
1997            use pretty_assertions::assert_eq;
1998
1999            serialize_as!(map_attr: BTreeMap::from([("@key1", 1), ("@key2", 2)])
2000                => r#"<root key1="1" key2="2"/>"#);
2001            serialize_as!(map_mixed: BTreeMap::from([("@key1", 1), ("key2", 2)])
2002                => "<root key1=\"1\">\n  \
2003                        <key2>2</key2>\n\
2004                    </root>");
2005
2006            serialize_as!(struct_: Attributes { key: "answer", val: (42, 42) }
2007                => r#"<root key="answer" val="42 42"/>"#);
2008            serialize_as!(struct_before: AttributesBefore { key: "answer", val: 42 }
2009                => "<root key=\"answer\">\n  \
2010                        <val>42</val>\n\
2011                    </root>");
2012            serialize_as!(struct_after: AttributesAfter { key: "answer", val: 42 }
2013                => "<root val=\"42\">\n  \
2014                        <key>answer</key>\n\
2015                    </root>");
2016
2017            err!(enum_: Enum::Attributes { key: "answer", val: (42, 42) }
2018                => Unsupported("cannot serialize enum struct variant `Enum::Attributes`"));
2019
2020            /// Test for https://github.com/tafia/quick-xml/issues/252
2021            mod optional {
2022                use super::*;
2023                use pretty_assertions::assert_eq;
2024
2025                serialize_as!(none:
2026                    OptionalAttributes { a: None, b: None }
2027                    => r#"<root a=""/>"#);
2028                serialize_as!(some_empty_str:
2029                    OptionalAttributes {
2030                        a: Some(""),
2031                        b: Some("")
2032                    }
2033                    => r#"<root a="" b=""/>"#);
2034                serialize_as!(some_non_empty:
2035                    OptionalAttributes {
2036                        a: Some("a"),
2037                        b: Some("b")
2038                    }
2039                    => r#"<root a="a" b="b"/>"#);
2040            }
2041        }
2042
2043        /// Test for https://github.com/tafia/quick-xml/issues/252
2044        mod optional {
2045            use super::*;
2046            use pretty_assertions::assert_eq;
2047
2048            serialize_as!(none:
2049                OptionalElements { a: None, b: None }
2050                => "<root>\n  \
2051                        <a/>\n\
2052                    </root>");
2053            serialize_as!(some_empty_str:
2054                OptionalElements {
2055                    a: Some(""),
2056                    b: Some("")
2057                }
2058                => "<root>\n  \
2059                        <a/>\n  \
2060                        <b/>\n\
2061                    </root>");
2062            serialize_as!(some_non_empty:
2063                OptionalElements {
2064                    a: Some("a"),
2065                    b: Some("b")
2066                }
2067                => "<root>\n  \
2068                        <a>a</a>\n  \
2069                        <b>b</b>\n\
2070                    </root>");
2071        }
2072    }
2073
2074    mod expand_empty_elements {
2075        use super::*;
2076        use pretty_assertions::assert_eq;
2077
2078        /// Checks that given `$data` successfully serialized as `$expected`
2079        macro_rules! serialize_as {
2080            ($name:ident: $data:expr => $expected:expr) => {
2081                #[test]
2082                fn $name() {
2083                    let mut buffer = String::new();
2084                    let ser = ElementSerializer {
2085                        ser: ContentSerializer {
2086                            writer: &mut buffer,
2087                            level: QuoteLevel::Full,
2088                            indent: Indent::None,
2089                            write_indent: false,
2090                            text_format: TextFormat::Text,
2091                            allow_primitive: true,
2092                            empty_element_handling: EmptyElementHandling::Expanded,
2093                        },
2094                        key: XmlName("root"),
2095                    };
2096
2097                    let result = $data.serialize(ser).unwrap();
2098                    assert_eq!(buffer, $expected);
2099                    assert_eq!(result, WriteResult::Element);
2100                }
2101            };
2102        }
2103
2104        serialize_as!(option_some_empty: Some("") => "<root></root>");
2105        serialize_as!(option_some_empty_str: Some("") => "<root></root>");
2106
2107        serialize_as!(unit: () => "<root></root>");
2108        serialize_as!(unit_struct: Unit => "<root></root>");
2109        serialize_as!(unit_struct_escaped: UnitEscaped => "<root></root>");
2110
2111        serialize_as!(enum_unit: Enum::Unit => "<root>Unit</root>");
2112        serialize_as!(enum_unit_escaped: Enum::UnitEscaped => "<root>&lt;&quot;&amp;&apos;&gt;</root>");
2113    }
2114}