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 /// `<` | `<`
338 /// `>` | `>`
339 /// `&` | `&`
340 /// `"` | `"`
341 /// `'` | `'`
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 /// `<` | `<`
353 /// `>` | `>`
354 /// `&` | `&`
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 /// `<` | `<`
366 /// `&` | `&`
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: &, <, >, ", '\">\
923 <element>special chars: &, <, >, \", '</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: &, <, >, ", '\">\
943 <element>special chars: &, <, >, \", '</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: &, <, >, ", '\">\
963 <element>special chars: &, <, >, \", '</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: &, <, >, ", '\">\
983 <element>special chars: &, <, >, ", '</element>\
984 </Example>"
985 );
986 }
987}