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 /// `<` | `<`
337 /// `>` | `>`
338 /// `&` | `&`
339 /// `"` | `"`
340 /// `'` | `'`
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 /// `<` | `<`
352 /// `>` | `>`
353 /// `&` | `&`
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 /// `<` | `<`
365 /// `&` | `&`
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: &, <, >, ", '\">\
922 <element>special chars: &, <, >, \", '</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: &, <, >, ", '\">\
942 <element>special chars: &, <, >, \", '</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: &, <, >, ", '\">\
962 <element>special chars: &, <, >, \", '</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: &, <, >, ", '\">\
982 <element>special chars: &, <, >, ", '</element>\
983 </Example>"
984 );
985 }
986}