Coverage Report

Created: 2026-05-16 07:06

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