quick_xml/se/
mod.rs

1//! Module to handle custom serde `Serializer`
2
3/// Implements writing primitives to the underlying writer.
4/// Implementor must provide `write_str(self, &str) -> Result<(), DeError>` method
5macro_rules! write_primitive {
6    ($method:ident ( $ty:ty )) => {
7        fn $method(mut self, value: $ty) -> Result<Self::Ok, Self::Error> {
8            self.write_str(&value.to_string())?;
9            Ok(self.writer)
10        }
11    };
12    () => {
13        fn serialize_bool(mut self, value: bool) -> Result<Self::Ok, Self::Error> {
14            self.write_str(if value { "true" } else { "false" })?;
15            Ok(self.writer)
16        }
17
18        write_primitive!(serialize_i8(i8));
19        write_primitive!(serialize_i16(i16));
20        write_primitive!(serialize_i32(i32));
21        write_primitive!(serialize_i64(i64));
22
23        write_primitive!(serialize_u8(u8));
24        write_primitive!(serialize_u16(u16));
25        write_primitive!(serialize_u32(u32));
26        write_primitive!(serialize_u64(u64));
27
28        serde_if_integer128! {
29            write_primitive!(serialize_i128(i128));
30            write_primitive!(serialize_u128(u128));
31        }
32
33        write_primitive!(serialize_f32(f32));
34        write_primitive!(serialize_f64(f64));
35
36        fn serialize_char(self, value: char) -> Result<Self::Ok, Self::Error> {
37            self.serialize_str(&value.to_string())
38        }
39
40        fn serialize_bytes(self, _value: &[u8]) -> Result<Self::Ok, Self::Error> {
41            //TODO: customization point - allow user to decide how to encode bytes
42            Err(Self::Error::Unsupported(
43                "`serialize_bytes` not supported yet".into(),
44            ))
45        }
46
47        fn serialize_none(self) -> Result<Self::Ok, Self::Error> {
48            Ok(self.writer)
49        }
50
51        fn serialize_some<T: ?Sized + Serialize>(self, value: &T) -> Result<Self::Ok, Self::Error> {
52            value.serialize(self)
53        }
54
55        fn serialize_unit_variant(
56            self,
57            _name: &'static str,
58            _variant_index: u32,
59            variant: &'static str,
60        ) -> Result<Self::Ok, Self::Error> {
61            self.serialize_str(variant)
62        }
63
64        fn serialize_newtype_struct<T: ?Sized + Serialize>(
65            self,
66            _name: &'static str,
67            value: &T,
68        ) -> Result<Self::Ok, Self::Error> {
69            value.serialize(self)
70        }
71    };
72}
73
74////////////////////////////////////////////////////////////////////////////////////////////////////
75
76mod content;
77mod element;
78pub(crate) mod key;
79pub(crate) mod simple_type;
80mod text;
81
82use self::content::ContentSerializer;
83use self::element::{ElementSerializer, Map, Struct, Tuple};
84use crate::de::TEXT_KEY;
85use crate::writer::{Indentation, ToFmtWrite};
86use serde::ser::{self, Serialize};
87use serde::serde_if_integer128;
88use std::fmt::Write;
89use std::str::from_utf8;
90
91pub use self::simple_type::SimpleTypeSerializer;
92pub use crate::errors::serialize::SeError;
93
94/// Serialize struct into a `Write`r.
95///
96/// Returns the classification of the last written type.
97///
98/// # Examples
99///
100/// ```
101/// # use quick_xml::se::to_writer;
102/// # use serde::Serialize;
103/// # use pretty_assertions::assert_eq;
104/// #[derive(Serialize)]
105/// struct Root<'a> {
106///     #[serde(rename = "@attribute")]
107///     attribute: &'a str,
108///     element: &'a str,
109///     #[serde(rename = "$text")]
110///     text: &'a str,
111/// }
112///
113/// let data = Root {
114///     attribute: "attribute content",
115///     element: "element content",
116///     text: "text content",
117/// };
118///
119/// let mut buffer = String::new();
120/// to_writer(&mut buffer, &data).unwrap();
121/// assert_eq!(
122///     buffer,
123///     // The root tag name is automatically deduced from the struct name
124///     // This will not work for other types or struct with #[serde(flatten)] fields
125///     "<Root attribute=\"attribute content\">\
126///         <element>element content</element>\
127///         text content\
128///     </Root>"
129/// );
130/// ```
131pub fn to_writer<W, T>(mut writer: W, value: &T) -> Result<WriteResult, SeError>
132where
133    W: Write,
134    T: ?Sized + Serialize,
135{
136    value.serialize(Serializer::new(&mut writer))
137}
138
139/// Serialize struct into a `io::Write`r restricted to utf-8 encoding.
140///
141/// Returns the classification of the last written type.
142///
143/// # Examples
144///
145/// ```
146/// # use quick_xml::se::to_utf8_io_writer;
147/// # use serde::Serialize;
148/// # use pretty_assertions::assert_eq;
149/// # use std::io::BufWriter;
150/// # use std::str;
151/// #[derive(Serialize)]
152/// struct Root<'a> {
153///     #[serde(rename = "@attribute")]
154///     attribute: &'a str,
155///     element: &'a str,
156///     #[serde(rename = "$text")]
157///     text: &'a str,
158/// }
159///
160/// let data = Root {
161///     attribute: "attribute content",
162///     element: "element content",
163///     text: "text content",
164/// };
165///
166/// let mut buffer = Vec::new();
167/// to_utf8_io_writer(&mut BufWriter::new(&mut buffer), &data).unwrap();
168///
169/// assert_eq!(
170///     str::from_utf8(&buffer).unwrap(),
171///     // The root tag name is automatically deduced from the struct name
172///     // This will not work for other types or struct with #[serde(flatten)] fields
173///     "<Root attribute=\"attribute content\">\
174///         <element>element content</element>\
175///         text content\
176///     </Root>"
177/// );
178/// ```
179pub fn to_utf8_io_writer<W, T>(writer: W, value: &T) -> Result<WriteResult, SeError>
180where
181    W: std::io::Write,
182    T: ?Sized + Serialize,
183{
184    value.serialize(Serializer::new(&mut ToFmtWrite(writer)))
185}
186
187/// Serialize struct into a `String`.
188///
189/// # Examples
190///
191/// ```
192/// # use quick_xml::se::to_string;
193/// # use serde::Serialize;
194/// # use pretty_assertions::assert_eq;
195/// #[derive(Serialize)]
196/// struct Root<'a> {
197///     #[serde(rename = "@attribute")]
198///     attribute: &'a str,
199///     element: &'a str,
200///     #[serde(rename = "$text")]
201///     text: &'a str,
202/// }
203///
204/// let data = Root {
205///     attribute: "attribute content",
206///     element: "element content",
207///     text: "text content",
208/// };
209///
210/// assert_eq!(
211///     to_string(&data).unwrap(),
212///     // The root tag name is automatically deduced from the struct name
213///     // This will not work for other types or struct with #[serde(flatten)] fields
214///     "<Root attribute=\"attribute content\">\
215///         <element>element content</element>\
216///         text content\
217///     </Root>"
218/// );
219/// ```
220pub fn to_string<T>(value: &T) -> Result<String, SeError>
221where
222    T: ?Sized + Serialize,
223{
224    let mut buffer = String::new();
225    to_writer(&mut buffer, value)?;
226    Ok(buffer)
227}
228
229/// Serialize struct into a `Write`r using specified root tag name.
230/// `root_tag` should be valid [XML name], otherwise error is returned.
231///
232/// Returns the classification of the last written type.
233///
234/// # Examples
235///
236/// ```
237/// # use quick_xml::se::to_writer_with_root;
238/// # use serde::Serialize;
239/// # use pretty_assertions::assert_eq;
240/// #[derive(Serialize)]
241/// struct Root<'a> {
242///     #[serde(rename = "@attribute")]
243///     attribute: &'a str,
244///     element: &'a str,
245///     #[serde(rename = "$text")]
246///     text: &'a str,
247/// }
248///
249/// let data = Root {
250///     attribute: "attribute content",
251///     element: "element content",
252///     text: "text content",
253/// };
254///
255/// let mut buffer = String::new();
256/// to_writer_with_root(&mut buffer, "top-level", &data).unwrap();
257/// assert_eq!(
258///     buffer,
259///     "<top-level attribute=\"attribute content\">\
260///         <element>element content</element>\
261///         text content\
262///     </top-level>"
263/// );
264/// ```
265///
266/// [XML name]: https://www.w3.org/TR/xml11/#NT-Name
267pub fn to_writer_with_root<W, T>(
268    mut writer: W,
269    root_tag: &str,
270    value: &T,
271) -> Result<WriteResult, SeError>
272where
273    W: Write,
274    T: ?Sized + Serialize,
275{
276    value.serialize(Serializer::with_root(&mut writer, Some(root_tag))?)
277}
278
279/// Serialize struct into a `String` using specified root tag name.
280/// `root_tag` should be valid [XML name], otherwise error is returned.
281///
282/// # Examples
283///
284/// ```
285/// # use quick_xml::se::to_string_with_root;
286/// # use serde::Serialize;
287/// # use pretty_assertions::assert_eq;
288/// #[derive(Serialize)]
289/// struct Root<'a> {
290///     #[serde(rename = "@attribute")]
291///     attribute: &'a str,
292///     element: &'a str,
293///     #[serde(rename = "$text")]
294///     text: &'a str,
295/// }
296///
297/// let data = Root {
298///     attribute: "attribute content",
299///     element: "element content",
300///     text: "text content",
301/// };
302///
303/// assert_eq!(
304///     to_string_with_root("top-level", &data).unwrap(),
305///     "<top-level attribute=\"attribute content\">\
306///         <element>element content</element>\
307///         text content\
308///     </top-level>"
309/// );
310/// ```
311///
312/// [XML name]: https://www.w3.org/TR/xml11/#NT-Name
313pub fn to_string_with_root<T>(root_tag: &str, value: &T) -> Result<String, SeError>
314where
315    T: ?Sized + Serialize,
316{
317    let mut buffer = String::new();
318    to_writer_with_root(&mut buffer, root_tag, value)?;
319    Ok(buffer)
320}
321
322////////////////////////////////////////////////////////////////////////////////////////////////////
323
324/// Defines which characters would be escaped in [`Text`] events and attribute
325/// values.
326///
327/// [`Text`]: crate::events::Event::Text
328#[derive(Debug, Clone, Copy, PartialEq, Eq)]
329pub enum QuoteLevel {
330    /// Performs escaping, escape all characters that could have special meaning
331    /// in the XML. This mode is compatible with SGML specification.
332    ///
333    /// Characters that will be replaced:
334    ///
335    /// Original | Replacement
336    /// ---------|------------
337    /// `<`      | `&lt;`
338    /// `>`      | `&gt;`
339    /// `&`      | `&amp;`
340    /// `"`      | `&quot;`
341    /// `'`      | `&apos;`
342    Full,
343    /// Performs escaping that is compatible with SGML specification.
344    ///
345    /// This level adds escaping of `>` to the `Minimal` level, which is [required]
346    /// for compatibility with SGML.
347    ///
348    /// Characters that will be replaced:
349    ///
350    /// Original | Replacement
351    /// ---------|------------
352    /// `<`      | `&lt;`
353    /// `>`      | `&gt;`
354    /// `&`      | `&amp;`
355    ///
356    /// [required]: https://www.w3.org/TR/xml11/#syntax
357    Partial,
358    /// Performs the minimal possible escaping, escape only strictly necessary
359    /// characters.
360    ///
361    /// Characters that will be replaced:
362    ///
363    /// Original | Replacement
364    /// ---------|------------
365    /// `<`      | `&lt;`
366    /// `&`      | `&amp;`
367    Minimal,
368}
369
370/// Classification of the type written by the serializer.
371#[derive(Debug, Clone, Copy, PartialEq, Eq)]
372pub enum WriteResult {
373    /// Text with insignificant spaces was written, for example a number. Adding indent to the
374    /// serialized data does not change meaning of the data.
375    Text,
376    /// The XML tag was written. Adding indent to the serialized data does not change meaning of the data.
377    Element,
378    /// Nothing was written (i. e. serialized type not represented in XML a all). Adding indent to the
379    /// serialized data does not change meaning of the data. This is returned for units, unit structs
380    /// and unit variants.
381    Nothing,
382    /// Text with significant spaces was written, for example a string. Adding indent to the
383    /// serialized data may change meaning of the data.
384    SensitiveText,
385    /// `None` was serialized and nothing was written. `None` does not represented in XML,
386    /// but adding indent after it may change meaning of the data.
387    SensitiveNothing,
388}
389
390impl WriteResult {
391    /// Returns `true` if indent should be written after the object (if configured) and `false` otherwise.
392    #[inline]
393    pub fn allow_indent(&self) -> bool {
394        matches!(self, Self::Element | Self::Nothing)
395    }
396
397    /// Returns `true` if self is `Text` or `SensitiveText`.
398    #[inline]
399    pub fn is_text(&self) -> bool {
400        matches!(self, Self::Text | Self::SensitiveText)
401    }
402}
403
404////////////////////////////////////////////////////////////////////////////////////////////////////
405
406/// Implements serialization method by forwarding it to the serializer created by
407/// the helper method [`Serializer::ser`].
408macro_rules! forward {
409    ($name:ident($ty:ty)) => {
410        fn $name(self, value: $ty) -> Result<Self::Ok, Self::Error> {
411            self.ser(&concat!("`", stringify!($ty), "`"))?.$name(value)
412        }
413    };
414}
415
416////////////////////////////////////////////////////////////////////////////////////////////////////
417
418/// Almost all characters can form a name. Citation from <https://www.w3.org/TR/xml11/#sec-xml11>:
419///
420/// > The overall philosophy of names has changed since XML 1.0. Whereas XML 1.0
421/// > provided a rigid definition of names, wherein everything that was not permitted
422/// > was forbidden, XML 1.1 names are designed so that everything that is not
423/// > forbidden (for a specific reason) is permitted. Since Unicode will continue
424/// > to grow past version 4.0, further changes to XML can be avoided by allowing
425/// > almost any character, including those not yet assigned, in names.
426///
427/// <https://www.w3.org/TR/xml11/#NT-NameStartChar>
428const fn is_xml11_name_start_char(ch: char) -> bool {
429    match ch {
430        ':'
431        | 'A'..='Z'
432        | '_'
433        | 'a'..='z'
434        | '\u{00C0}'..='\u{00D6}'
435        | '\u{00D8}'..='\u{00F6}'
436        | '\u{00F8}'..='\u{02FF}'
437        | '\u{0370}'..='\u{037D}'
438        | '\u{037F}'..='\u{1FFF}'
439        | '\u{200C}'..='\u{200D}'
440        | '\u{2070}'..='\u{218F}'
441        | '\u{2C00}'..='\u{2FEF}'
442        | '\u{3001}'..='\u{D7FF}'
443        | '\u{F900}'..='\u{FDCF}'
444        | '\u{FDF0}'..='\u{FFFD}'
445        | '\u{10000}'..='\u{EFFFF}' => true,
446        _ => false,
447    }
448}
449/// <https://www.w3.org/TR/xml11/#NT-NameChar>
450const fn is_xml11_name_char(ch: char) -> bool {
451    match ch {
452        '-' | '.' | '0'..='9' | '\u{00B7}' | '\u{0300}'..='\u{036F}' | '\u{203F}'..='\u{2040}' => {
453            true
454        }
455        _ => is_xml11_name_start_char(ch),
456    }
457}
458
459/// Helper struct to self-defense from errors
460#[derive(Clone, Copy, Debug, PartialEq)]
461pub(self) struct XmlName<'n>(&'n str);
462
463impl<'n> XmlName<'n> {
464    /// Checks correctness of the XML name according to [XML 1.1 specification]
465    ///
466    /// [XML 1.1 specification]: https://www.w3.org/TR/xml11/#NT-Name
467    pub fn try_from(name: &'n str) -> Result<XmlName<'n>, SeError> {
468        //TODO: Customization point: allow user to decide if he want to reject or encode the name
469        match name.chars().next() {
470            Some(ch) if !is_xml11_name_start_char(ch) => Err(SeError::Unsupported(
471                format!("character `{ch}` is not allowed at the start of an XML name `{name}`")
472                    .into(),
473            )),
474            _ => match name.matches(|ch| !is_xml11_name_char(ch)).next() {
475                Some(s) => Err(SeError::Unsupported(
476                    format!("character `{s}` is not allowed in an XML name `{name}`").into(),
477                )),
478                None => Ok(XmlName(name)),
479            },
480        }
481    }
482}
483
484////////////////////////////////////////////////////////////////////////////////////////////////////
485
486pub(crate) enum Indent<'i> {
487    /// No indent should be written before the element
488    None,
489    /// The specified indent should be written. The type owns the buffer with indent
490    Owned(Indentation),
491    /// The specified indent should be written. The type borrows buffer with indent
492    /// from its owner
493    Borrow(&'i mut Indentation),
494}
495
496impl<'i> Indent<'i> {
497    pub fn borrow(&mut self) -> Indent {
498        match self {
499            Self::None => Indent::None,
500            Self::Owned(ref mut i) => Indent::Borrow(i),
501            Self::Borrow(i) => Indent::Borrow(i),
502        }
503    }
504
505    pub fn increase(&mut self) {
506        match self {
507            Self::None => {}
508            Self::Owned(i) => i.grow(),
509            Self::Borrow(i) => i.grow(),
510        }
511    }
512
513    pub fn decrease(&mut self) {
514        match self {
515            Self::None => {}
516            Self::Owned(i) => i.shrink(),
517            Self::Borrow(i) => i.shrink(),
518        }
519    }
520
521    pub fn write_indent<W: std::fmt::Write>(&mut self, mut writer: W) -> Result<(), SeError> {
522        match self {
523            Self::None => {}
524            Self::Owned(i) => {
525                writer.write_char('\n')?;
526                writer.write_str(from_utf8(i.current())?)?;
527            }
528            Self::Borrow(i) => {
529                writer.write_char('\n')?;
530                writer.write_str(from_utf8(i.current())?)?;
531            }
532        }
533        Ok(())
534    }
535}
536
537////////////////////////////////////////////////////////////////////////////////////////////////////
538
539/// A Serializer.
540///
541/// Returns the classification of the last written type.
542pub struct Serializer<'w, 'r, W: Write> {
543    ser: ContentSerializer<'w, 'r, W>,
544    /// Name of the root tag. If not specified, deduced from the structure name
545    root_tag: Option<XmlName<'r>>,
546}
547
548impl<'w, 'r, W: Write> Serializer<'w, 'r, W> {
549    /// Creates a new `Serializer` that uses struct name as a root tag name.
550    ///
551    /// Note, that attempt to serialize a non-struct (including unit structs
552    /// and newtype structs) will end up to an error. Use `with_root` to create
553    /// serializer with explicitly defined root element name
554    pub fn new(writer: &'w mut W) -> Self {
555        Self {
556            ser: ContentSerializer {
557                writer,
558                level: QuoteLevel::Partial,
559                indent: Indent::None,
560                write_indent: false,
561                allow_primitive: true,
562                expand_empty_elements: false,
563            },
564            root_tag: None,
565        }
566    }
567
568    /// Creates a new `Serializer` that uses specified root tag name. `name` should
569    /// be valid [XML name], otherwise error is returned.
570    ///
571    /// # Examples
572    ///
573    /// When serializing a primitive type, only its representation will be written:
574    ///
575    /// ```
576    /// # use pretty_assertions::assert_eq;
577    /// # use serde::Serialize;
578    /// # use quick_xml::se::Serializer;
579    ///
580    /// let mut buffer = String::new();
581    /// let ser = Serializer::with_root(&mut buffer, Some("root")).unwrap();
582    ///
583    /// "node".serialize(ser).unwrap();
584    /// assert_eq!(buffer, "<root>node</root>");
585    /// ```
586    ///
587    /// When serializing a struct, newtype struct, unit struct or tuple `root_tag`
588    /// is used as tag name of root(s) element(s):
589    ///
590    /// ```
591    /// # use pretty_assertions::assert_eq;
592    /// # use serde::Serialize;
593    /// # use quick_xml::se::Serializer;
594    ///
595    /// #[derive(Debug, PartialEq, Serialize)]
596    /// struct Struct {
597    ///     question: String,
598    ///     answer: u32,
599    /// }
600    ///
601    /// let mut buffer = String::new();
602    /// let ser = Serializer::with_root(&mut buffer, Some("root")).unwrap();
603    ///
604    /// let data = Struct {
605    ///     question: "The Ultimate Question of Life, the Universe, and Everything".into(),
606    ///     answer: 42,
607    /// };
608    ///
609    /// data.serialize(ser).unwrap();
610    /// assert_eq!(
611    ///     buffer,
612    ///     "<root>\
613    ///         <question>The Ultimate Question of Life, the Universe, and Everything</question>\
614    ///         <answer>42</answer>\
615    ///      </root>"
616    /// );
617    /// ```
618    ///
619    /// [XML name]: https://www.w3.org/TR/xml11/#NT-Name
620    pub fn with_root(writer: &'w mut W, root_tag: Option<&'r str>) -> Result<Self, SeError> {
621        Ok(Self {
622            ser: ContentSerializer {
623                writer,
624                level: QuoteLevel::Partial,
625                indent: Indent::None,
626                write_indent: false,
627                allow_primitive: true,
628                expand_empty_elements: false,
629            },
630            root_tag: root_tag.map(|tag| XmlName::try_from(tag)).transpose()?,
631        })
632    }
633
634    /// Enable or disable expansion of empty elements. Defaults to `false`.
635    ///
636    /// # Examples
637    ///
638    /// ```
639    /// # use pretty_assertions::assert_eq;
640    /// # use serde::Serialize;
641    /// # use quick_xml::se::Serializer;
642    ///
643    /// #[derive(Debug, PartialEq, Serialize)]
644    /// struct Struct {
645    ///     question: Option<String>,
646    /// }
647    ///
648    /// let mut buffer = String::new();
649    /// let mut ser = Serializer::new(&mut buffer);
650    /// ser.expand_empty_elements(true);
651    ///
652    /// let data = Struct {
653    ///   question: None,
654    /// };
655    ///
656    /// data.serialize(ser).unwrap();
657    /// assert_eq!(
658    ///     buffer,
659    ///     "<Struct><question></question></Struct>"
660    /// );
661    /// ```
662    pub fn expand_empty_elements(&mut self, expand: bool) -> &mut Self {
663        self.ser.expand_empty_elements = expand;
664        self
665    }
666
667    /// Configure indent for a serializer
668    pub fn indent(&mut self, indent_char: char, indent_size: usize) -> &mut Self {
669        self.ser.indent = Indent::Owned(Indentation::new(indent_char as u8, indent_size));
670        self
671    }
672
673    /// Set the level of quoting used when writing texts
674    ///
675    /// Default: [`QuoteLevel::Minimal`]
676    pub fn set_quote_level(&mut self, level: QuoteLevel) -> &mut Self {
677        self.ser.level = level;
678        self
679    }
680
681    /// Set the indent object for a serializer
682    pub(crate) fn set_indent(&mut self, indent: Indent<'r>) -> &mut Self {
683        self.ser.indent = indent;
684        self
685    }
686
687    /// Creates actual serializer or returns an error if root tag is not defined.
688    /// In that case `err` contains the name of type that cannot be serialized.
689    fn ser(self, err: &str) -> Result<ElementSerializer<'w, 'r, W>, SeError> {
690        if let Some(key) = self.root_tag {
691            Ok(ElementSerializer { ser: self.ser, key })
692        } else {
693            Err(SeError::Unsupported(
694                format!("cannot serialize {} without defined root tag", err).into(),
695            ))
696        }
697    }
698
699    /// Creates actual serializer using root tag or a specified `key` if root tag
700    /// is not defined. Returns an error if root tag is not defined and a `key`
701    /// does not conform [XML rules](XmlName::try_from) for names.
702    fn ser_name(self, key: &'static str) -> Result<ElementSerializer<'w, 'r, W>, SeError> {
703        Ok(ElementSerializer {
704            ser: self.ser,
705            key: match self.root_tag {
706                Some(key) => key,
707                None => XmlName::try_from(key)?,
708            },
709        })
710    }
711}
712
713impl<'w, 'r, W: Write> ser::Serializer for Serializer<'w, 'r, W> {
714    type Ok = WriteResult;
715    type Error = SeError;
716
717    type SerializeSeq = ElementSerializer<'w, 'r, W>;
718    type SerializeTuple = ElementSerializer<'w, 'r, W>;
719    type SerializeTupleStruct = ElementSerializer<'w, 'r, W>;
720    type SerializeTupleVariant = Tuple<'w, 'r, W>;
721    type SerializeMap = Map<'w, 'r, W>;
722    type SerializeStruct = Struct<'w, 'r, W>;
723    type SerializeStructVariant = Struct<'w, 'r, W>;
724
725    forward!(serialize_bool(bool));
726
727    forward!(serialize_i8(i8));
728    forward!(serialize_i16(i16));
729    forward!(serialize_i32(i32));
730    forward!(serialize_i64(i64));
731
732    forward!(serialize_u8(u8));
733    forward!(serialize_u16(u16));
734    forward!(serialize_u32(u32));
735    forward!(serialize_u64(u64));
736
737    serde_if_integer128! {
738        forward!(serialize_i128(i128));
739        forward!(serialize_u128(u128));
740    }
741
742    forward!(serialize_f32(f32));
743    forward!(serialize_f64(f64));
744
745    forward!(serialize_char(char));
746    forward!(serialize_str(&str));
747    forward!(serialize_bytes(&[u8]));
748
749    fn serialize_none(self) -> Result<Self::Ok, Self::Error> {
750        // Do not write indent after `Option` field with `None` value, because
751        // this can be `Option<String>`. Unfortunately, we do not known what the
752        // type the option contains, so have no chance to adapt our behavior to it.
753        // The safe variant is not to write indent
754        Ok(WriteResult::SensitiveNothing)
755    }
756
757    fn serialize_some<T: ?Sized + Serialize>(self, value: &T) -> Result<Self::Ok, Self::Error> {
758        value.serialize(self)
759    }
760
761    fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
762        self.ser("`()`")?.serialize_unit()
763    }
764
765    fn serialize_unit_struct(self, name: &'static str) -> Result<Self::Ok, Self::Error> {
766        self.ser_name(name)?.serialize_unit_struct(name)
767    }
768
769    fn serialize_unit_variant(
770        self,
771        name: &'static str,
772        _variant_index: u32,
773        variant: &'static str,
774    ) -> Result<Self::Ok, Self::Error> {
775        if variant == TEXT_KEY {
776            // We should write some text but we don't known what text to write
777            Err(SeError::Unsupported(
778                format!(
779                    "cannot serialize enum unit variant `{}::$text` as text content value",
780                    name
781                )
782                .into(),
783            ))
784        } else {
785            let name = XmlName::try_from(variant)?;
786            self.ser.write_empty(name)
787        }
788    }
789
790    fn serialize_newtype_struct<T: ?Sized + Serialize>(
791        self,
792        name: &'static str,
793        value: &T,
794    ) -> Result<Self::Ok, Self::Error> {
795        self.ser_name(name)?.serialize_newtype_struct(name, value)
796    }
797
798    fn serialize_newtype_variant<T: ?Sized + Serialize>(
799        self,
800        _name: &'static str,
801        _variant_index: u32,
802        variant: &'static str,
803        value: &T,
804    ) -> Result<Self::Ok, Self::Error> {
805        if variant == TEXT_KEY {
806            value.serialize(self.ser.into_simple_type_serializer()?)?;
807            // Do not write indent after `$text` variant because it may be interpreted as
808            // part of content when deserialize
809            Ok(WriteResult::SensitiveText)
810        } else {
811            let ser = ElementSerializer {
812                ser: self.ser,
813                key: XmlName::try_from(variant)?,
814            };
815            value.serialize(ser)
816        }
817    }
818
819    fn serialize_seq(self, len: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> {
820        self.ser("sequence")?.serialize_seq(len)
821    }
822
823    fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple, Self::Error> {
824        self.ser("unnamed tuple")?.serialize_tuple(len)
825    }
826
827    fn serialize_tuple_struct(
828        self,
829        name: &'static str,
830        len: usize,
831    ) -> Result<Self::SerializeTupleStruct, Self::Error> {
832        self.ser_name(name)?.serialize_tuple_struct(name, len)
833    }
834
835    fn serialize_tuple_variant(
836        self,
837        name: &'static str,
838        _variant_index: u32,
839        variant: &'static str,
840        len: usize,
841    ) -> Result<Self::SerializeTupleVariant, Self::Error> {
842        if variant == TEXT_KEY {
843            self.ser
844                .into_simple_type_serializer()?
845                .serialize_tuple_struct(name, len)
846                .map(Tuple::Text)
847        } else {
848            let ser = ElementSerializer {
849                ser: self.ser,
850                key: XmlName::try_from(variant)?,
851            };
852            ser.serialize_tuple_struct(name, len).map(Tuple::Element)
853        }
854    }
855
856    fn serialize_map(self, len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
857        self.ser("map")?.serialize_map(len)
858    }
859
860    fn serialize_struct(
861        self,
862        name: &'static str,
863        len: usize,
864    ) -> Result<Self::SerializeStruct, Self::Error> {
865        self.ser_name(name)?.serialize_struct(name, len)
866    }
867
868    fn serialize_struct_variant(
869        self,
870        name: &'static str,
871        _variant_index: u32,
872        variant: &'static str,
873        len: usize,
874    ) -> Result<Self::SerializeStructVariant, Self::Error> {
875        if variant == TEXT_KEY {
876            Err(SeError::Unsupported(
877                format!(
878                    "cannot serialize enum struct variant `{}::$text` as text content value",
879                    name
880                )
881                .into(),
882            ))
883        } else {
884            let ser = ElementSerializer {
885                ser: self.ser,
886                key: XmlName::try_from(variant)?,
887            };
888            ser.serialize_struct(name, len)
889        }
890    }
891}
892
893#[cfg(test)]
894mod quote_level {
895    use super::*;
896    use pretty_assertions::assert_eq;
897    use serde::Serialize;
898
899    #[derive(Debug, PartialEq, Serialize)]
900    struct Element(&'static str);
901
902    #[derive(Debug, PartialEq, Serialize)]
903    struct Example {
904        #[serde(rename = "@attribute")]
905        attribute: &'static str,
906        element: Element,
907    }
908
909    #[test]
910    fn default_() {
911        let example = Example {
912            attribute: "special chars: &, <, >, \", '",
913            element: Element("special chars: &, <, >, \", '"),
914        };
915
916        let mut buffer = String::new();
917        let ser = Serializer::new(&mut buffer);
918
919        example.serialize(ser).unwrap();
920        assert_eq!(
921            buffer,
922            "<Example attribute=\"special chars: &amp;, &lt;, &gt;, &quot;, '\">\
923                <element>special chars: &amp;, &lt;, &gt;, \", '</element>\
924            </Example>"
925        );
926    }
927
928    #[test]
929    fn minimal() {
930        let example = Example {
931            attribute: "special chars: &, <, >, \", '",
932            element: Element("special chars: &, <, >, \", '"),
933        };
934
935        let mut buffer = String::new();
936        let mut ser = Serializer::new(&mut buffer);
937        ser.set_quote_level(QuoteLevel::Minimal);
938
939        example.serialize(ser).unwrap();
940        assert_eq!(
941            buffer,
942            "<Example attribute=\"special chars: &amp;, &lt;, >, &quot;, '\">\
943                <element>special chars: &amp;, &lt;, >, \", '</element>\
944            </Example>"
945        );
946    }
947
948    #[test]
949    fn partial() {
950        let example = Example {
951            attribute: "special chars: &, <, >, \", '",
952            element: Element("special chars: &, <, >, \", '"),
953        };
954
955        let mut buffer = String::new();
956        let mut ser = Serializer::new(&mut buffer);
957        ser.set_quote_level(QuoteLevel::Partial);
958
959        example.serialize(ser).unwrap();
960        assert_eq!(
961            buffer,
962            "<Example attribute=\"special chars: &amp;, &lt;, &gt;, &quot;, '\">\
963                <element>special chars: &amp;, &lt;, &gt;, \", '</element>\
964            </Example>"
965        );
966    }
967
968    #[test]
969    fn full() {
970        let example = Example {
971            attribute: "special chars: &, <, >, \", '",
972            element: Element("special chars: &, <, >, \", '"),
973        };
974
975        let mut buffer = String::new();
976        let mut ser = Serializer::new(&mut buffer);
977        ser.set_quote_level(QuoteLevel::Full);
978
979        example.serialize(ser).unwrap();
980        assert_eq!(
981            buffer,
982            "<Example attribute=\"special chars: &amp;, &lt;, &gt;, &quot;, &apos;\">\
983                <element>special chars: &amp;, &lt;, &gt;, &quot;, &apos;</element>\
984            </Example>"
985        );
986    }
987}