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