quick_xml/se/
element.rs

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