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(DeError::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::errors::serialize::DeError;
86use crate::writer::Indentation;
87use serde::ser::{self, Serialize};
88use serde::serde_if_integer128;
89use std::fmt::Write;
90use std::str::from_utf8;
91
92/// Serialize struct into a `Write`r.
93///
94/// # Examples
95///
96/// ```
97/// # use quick_xml::se::to_writer;
98/// # use serde::Serialize;
99/// # use pretty_assertions::assert_eq;
100/// #[derive(Serialize)]
101/// struct Root<'a> {
102/// #[serde(rename = "@attribute")]
103/// attribute: &'a str,
104/// element: &'a str,
105/// #[serde(rename = "$text")]
106/// text: &'a str,
107/// }
108///
109/// let data = Root {
110/// attribute: "attribute content",
111/// element: "element content",
112/// text: "text content",
113/// };
114///
115/// let mut buffer = String::new();
116/// to_writer(&mut buffer, &data).unwrap();
117/// assert_eq!(
118/// buffer,
119/// // The root tag name is automatically deduced from the struct name
120/// // This will not work for other types or struct with #[serde(flatten)] fields
121/// "<Root attribute=\"attribute content\">\
122/// <element>element content</element>\
123/// text content\
124/// </Root>"
125/// );
126/// ```
127pub fn to_writer<W, T>(mut writer: W, value: &T) -> Result<(), DeError>
128where
129 W: Write,
130 T: ?Sized + Serialize,
131{
132 value.serialize(Serializer::new(&mut writer))
133}
134
135/// Serialize struct into a `String`.
136///
137/// # Examples
138///
139/// ```
140/// # use quick_xml::se::to_string;
141/// # use serde::Serialize;
142/// # use pretty_assertions::assert_eq;
143/// #[derive(Serialize)]
144/// struct Root<'a> {
145/// #[serde(rename = "@attribute")]
146/// attribute: &'a str,
147/// element: &'a str,
148/// #[serde(rename = "$text")]
149/// text: &'a str,
150/// }
151///
152/// let data = Root {
153/// attribute: "attribute content",
154/// element: "element content",
155/// text: "text content",
156/// };
157///
158/// assert_eq!(
159/// to_string(&data).unwrap(),
160/// // The root tag name is automatically deduced from the struct name
161/// // This will not work for other types or struct with #[serde(flatten)] fields
162/// "<Root attribute=\"attribute content\">\
163/// <element>element content</element>\
164/// text content\
165/// </Root>"
166/// );
167/// ```
168pub fn to_string<T>(value: &T) -> Result<String, DeError>
169where
170 T: ?Sized + Serialize,
171{
172 let mut buffer = String::new();
173 to_writer(&mut buffer, value)?;
174 Ok(buffer)
175}
176
177/// Serialize struct into a `Write`r using specified root tag name.
178/// `root_tag` should be valid [XML name], otherwise error is returned.
179///
180/// # Examples
181///
182/// ```
183/// # use quick_xml::se::to_writer_with_root;
184/// # use serde::Serialize;
185/// # use pretty_assertions::assert_eq;
186/// #[derive(Serialize)]
187/// struct Root<'a> {
188/// #[serde(rename = "@attribute")]
189/// attribute: &'a str,
190/// element: &'a str,
191/// #[serde(rename = "$text")]
192/// text: &'a str,
193/// }
194///
195/// let data = Root {
196/// attribute: "attribute content",
197/// element: "element content",
198/// text: "text content",
199/// };
200///
201/// let mut buffer = String::new();
202/// to_writer_with_root(&mut buffer, "top-level", &data).unwrap();
203/// assert_eq!(
204/// buffer,
205/// "<top-level attribute=\"attribute content\">\
206/// <element>element content</element>\
207/// text content\
208/// </top-level>"
209/// );
210/// ```
211///
212/// [XML name]: https://www.w3.org/TR/xml11/#NT-Name
213pub fn to_writer_with_root<W, T>(mut writer: W, root_tag: &str, value: &T) -> Result<(), DeError>
214where
215 W: Write,
216 T: ?Sized + Serialize,
217{
218 value.serialize(Serializer::with_root(&mut writer, Some(root_tag))?)
219}
220
221/// Serialize struct into a `String` using specified root tag name.
222/// `root_tag` should be valid [XML name], otherwise error is returned.
223///
224/// # Examples
225///
226/// ```
227/// # use quick_xml::se::to_string_with_root;
228/// # use serde::Serialize;
229/// # use pretty_assertions::assert_eq;
230/// #[derive(Serialize)]
231/// struct Root<'a> {
232/// #[serde(rename = "@attribute")]
233/// attribute: &'a str,
234/// element: &'a str,
235/// #[serde(rename = "$text")]
236/// text: &'a str,
237/// }
238///
239/// let data = Root {
240/// attribute: "attribute content",
241/// element: "element content",
242/// text: "text content",
243/// };
244///
245/// assert_eq!(
246/// to_string_with_root("top-level", &data).unwrap(),
247/// "<top-level attribute=\"attribute content\">\
248/// <element>element content</element>\
249/// text content\
250/// </top-level>"
251/// );
252/// ```
253///
254/// [XML name]: https://www.w3.org/TR/xml11/#NT-Name
255pub fn to_string_with_root<T>(root_tag: &str, value: &T) -> Result<String, DeError>
256where
257 T: ?Sized + Serialize,
258{
259 let mut buffer = String::new();
260 to_writer_with_root(&mut buffer, root_tag, value)?;
261 Ok(buffer)
262}
263
264////////////////////////////////////////////////////////////////////////////////////////////////////
265
266/// Defines which characters would be escaped in [`Text`] events and attribute
267/// values.
268///
269/// [`Text`]: crate::events::Event::Text
270#[derive(Debug, Clone, Copy, PartialEq, Eq)]
271pub enum QuoteLevel {
272 /// Performs escaping, escape all characters that could have special meaning
273 /// in the XML. This mode is compatible with SGML specification.
274 ///
275 /// Characters that will be replaced:
276 ///
277 /// Original | Replacement
278 /// ---------|------------
279 /// `<` | `<`
280 /// `>` | `>`
281 /// `&` | `&`
282 /// `"` | `"`
283 /// `'` | `'`
284 Full,
285 /// Performs escaping that is compatible with SGML specification.
286 ///
287 /// This level adds escaping of `>` to the `Minimal` level, which is [required]
288 /// for compatibility with SGML.
289 ///
290 /// Characters that will be replaced:
291 ///
292 /// Original | Replacement
293 /// ---------|------------
294 /// `<` | `<`
295 /// `>` | `>`
296 /// `&` | `&`
297 ///
298 /// [required]: https://www.w3.org/TR/xml11/#syntax
299 Partial,
300 /// Performs the minimal possible escaping, escape only strictly necessary
301 /// characters.
302 ///
303 /// Characters that will be replaced:
304 ///
305 /// Original | Replacement
306 /// ---------|------------
307 /// `<` | `<`
308 /// `&` | `&`
309 Minimal,
310}
311
312////////////////////////////////////////////////////////////////////////////////////////////////////
313
314/// Implements serialization method by forwarding it to the serializer created by
315/// the helper method [`Serializer::ser`].
316macro_rules! forward {
317 ($name:ident($ty:ty)) => {
318 fn $name(self, value: $ty) -> Result<Self::Ok, Self::Error> {
319 self.ser(&concat!("`", stringify!($ty), "`"))?.$name(value)
320 }
321 };
322}
323
324////////////////////////////////////////////////////////////////////////////////////////////////////
325
326/// Almost all characters can form a name. Citation from <https://www.w3.org/TR/xml11/#sec-xml11>:
327///
328/// > The overall philosophy of names has changed since XML 1.0. Whereas XML 1.0
329/// > provided a rigid definition of names, wherein everything that was not permitted
330/// > was forbidden, XML 1.1 names are designed so that everything that is not
331/// > forbidden (for a specific reason) is permitted. Since Unicode will continue
332/// > to grow past version 4.0, further changes to XML can be avoided by allowing
333/// > almost any character, including those not yet assigned, in names.
334///
335/// <https://www.w3.org/TR/xml11/#NT-NameStartChar>
336const fn is_xml11_name_start_char(ch: char) -> bool {
337 match ch {
338 ':'
339 | 'A'..='Z'
340 | '_'
341 | 'a'..='z'
342 | '\u{00C0}'..='\u{00D6}'
343 | '\u{00D8}'..='\u{00F6}'
344 | '\u{00F8}'..='\u{02FF}'
345 | '\u{0370}'..='\u{037D}'
346 | '\u{037F}'..='\u{1FFF}'
347 | '\u{200C}'..='\u{200D}'
348 | '\u{2070}'..='\u{218F}'
349 | '\u{2C00}'..='\u{2FEF}'
350 | '\u{3001}'..='\u{D7FF}'
351 | '\u{F900}'..='\u{FDCF}'
352 | '\u{FDF0}'..='\u{FFFD}'
353 | '\u{10000}'..='\u{EFFFF}' => true,
354 _ => false,
355 }
356}
357/// <https://www.w3.org/TR/xml11/#NT-NameChar>
358const fn is_xml11_name_char(ch: char) -> bool {
359 match ch {
360 '-' | '.' | '0'..='9' | '\u{00B7}' | '\u{0300}'..='\u{036F}' | '\u{203F}'..='\u{2040}' => {
361 true
362 }
363 _ => is_xml11_name_start_char(ch),
364 }
365}
366
367/// Helper struct to self-defense from errors
368#[derive(Clone, Copy, Debug, PartialEq)]
369pub(self) struct XmlName<'n>(&'n str);
370
371impl<'n> XmlName<'n> {
372 /// Checks correctness of the XML name according to [XML 1.1 specification]
373 ///
374 /// [XML 1.1 specification]: https://www.w3.org/TR/xml11/#NT-Name
375 pub fn try_from(name: &'n str) -> Result<XmlName<'n>, DeError> {
376 //TODO: Customization point: allow user to decide if he want to reject or encode the name
377 match name.chars().next() {
378 Some(ch) if !is_xml11_name_start_char(ch) => Err(DeError::Unsupported(
379 format!("character `{ch}` is not allowed at the start of an XML name `{name}`")
380 .into(),
381 )),
382 _ => match name.matches(|ch| !is_xml11_name_char(ch)).next() {
383 Some(s) => Err(DeError::Unsupported(
384 format!("character `{s}` is not allowed in an XML name `{name}`").into(),
385 )),
386 None => Ok(XmlName(name)),
387 },
388 }
389 }
390}
391
392////////////////////////////////////////////////////////////////////////////////////////////////////
393
394pub(crate) enum Indent<'i> {
395 /// No indent should be written before the element
396 None,
397 /// The specified indent should be written. The type owns the buffer with indent
398 Owned(Indentation),
399 /// The specified indent should be written. The type borrows buffer with indent
400 /// from its owner
401 Borrow(&'i mut Indentation),
402}
403
404impl<'i> Indent<'i> {
405 pub fn borrow(&mut self) -> Indent {
406 match self {
407 Self::None => Indent::None,
408 Self::Owned(ref mut i) => Indent::Borrow(i),
409 Self::Borrow(i) => Indent::Borrow(i),
410 }
411 }
412
413 pub fn increase(&mut self) {
414 match self {
415 Self::None => {}
416 Self::Owned(i) => i.grow(),
417 Self::Borrow(i) => i.grow(),
418 }
419 }
420
421 pub fn decrease(&mut self) {
422 match self {
423 Self::None => {}
424 Self::Owned(i) => i.shrink(),
425 Self::Borrow(i) => i.shrink(),
426 }
427 }
428
429 pub fn write_indent<W: std::fmt::Write>(&mut self, mut writer: W) -> Result<(), DeError> {
430 match self {
431 Self::None => {}
432 Self::Owned(i) => {
433 writer.write_char('\n')?;
434 writer.write_str(from_utf8(i.current())?)?;
435 }
436 Self::Borrow(i) => {
437 writer.write_char('\n')?;
438 writer.write_str(from_utf8(i.current())?)?;
439 }
440 }
441 Ok(())
442 }
443}
444
445////////////////////////////////////////////////////////////////////////////////////////////////////
446
447/// A Serializer
448pub struct Serializer<'w, 'r, W: Write> {
449 ser: ContentSerializer<'w, 'r, W>,
450 /// Name of the root tag. If not specified, deduced from the structure name
451 root_tag: Option<XmlName<'r>>,
452}
453
454impl<'w, 'r, W: Write> Serializer<'w, 'r, W> {
455 /// Creates a new `Serializer` that uses struct name as a root tag name.
456 ///
457 /// Note, that attempt to serialize a non-struct (including unit structs
458 /// and newtype structs) will end up to an error. Use `with_root` to create
459 /// serializer with explicitly defined root element name
460 pub fn new(writer: &'w mut W) -> Self {
461 Self {
462 ser: ContentSerializer {
463 writer,
464 level: QuoteLevel::Full,
465 indent: Indent::None,
466 write_indent: false,
467 expand_empty_elements: false,
468 },
469 root_tag: None,
470 }
471 }
472
473 /// Creates a new `Serializer` that uses specified root tag name. `name` should
474 /// be valid [XML name], otherwise error is returned.
475 ///
476 /// # Examples
477 ///
478 /// When serializing a primitive type, only its representation will be written:
479 ///
480 /// ```
481 /// # use pretty_assertions::assert_eq;
482 /// # use serde::Serialize;
483 /// # use quick_xml::se::Serializer;
484 ///
485 /// let mut buffer = String::new();
486 /// let ser = Serializer::with_root(&mut buffer, Some("root")).unwrap();
487 ///
488 /// "node".serialize(ser).unwrap();
489 /// assert_eq!(buffer, "<root>node</root>");
490 /// ```
491 ///
492 /// When serializing a struct, newtype struct, unit struct or tuple `root_tag`
493 /// is used as tag name of root(s) element(s):
494 ///
495 /// ```
496 /// # use pretty_assertions::assert_eq;
497 /// # use serde::Serialize;
498 /// # use quick_xml::se::Serializer;
499 ///
500 /// #[derive(Debug, PartialEq, Serialize)]
501 /// struct Struct {
502 /// question: String,
503 /// answer: u32,
504 /// }
505 ///
506 /// let mut buffer = String::new();
507 /// let ser = Serializer::with_root(&mut buffer, Some("root")).unwrap();
508 ///
509 /// let data = Struct {
510 /// question: "The Ultimate Question of Life, the Universe, and Everything".into(),
511 /// answer: 42,
512 /// };
513 ///
514 /// data.serialize(ser).unwrap();
515 /// assert_eq!(
516 /// buffer,
517 /// "<root>\
518 /// <question>The Ultimate Question of Life, the Universe, and Everything</question>\
519 /// <answer>42</answer>\
520 /// </root>"
521 /// );
522 /// ```
523 ///
524 /// [XML name]: https://www.w3.org/TR/xml11/#NT-Name
525 pub fn with_root(writer: &'w mut W, root_tag: Option<&'r str>) -> Result<Self, DeError> {
526 Ok(Self {
527 ser: ContentSerializer {
528 writer,
529 level: QuoteLevel::Full,
530 indent: Indent::None,
531 write_indent: false,
532 expand_empty_elements: false,
533 },
534 root_tag: root_tag.map(|tag| XmlName::try_from(tag)).transpose()?,
535 })
536 }
537
538 /// Enable or disable expansion of empty elements. Defaults to `false`.
539 ///
540 /// # Examples
541 ///
542 /// ```
543 /// # use pretty_assertions::assert_eq;
544 /// # use serde::Serialize;
545 /// # use quick_xml::se::Serializer;
546 ///
547 /// #[derive(Debug, PartialEq, Serialize)]
548 /// struct Struct {
549 /// question: Option<String>,
550 /// }
551 ///
552 /// let mut buffer = String::new();
553 /// let mut ser = Serializer::new(&mut buffer);
554 /// ser.expand_empty_elements(true);
555 ///
556 /// let data = Struct {
557 /// question: None,
558 /// };
559 ///
560 /// data.serialize(ser).unwrap();
561 /// assert_eq!(
562 /// buffer,
563 /// "<Struct><question></question></Struct>"
564 /// );
565 /// ```
566 pub fn expand_empty_elements(&mut self, expand: bool) -> &mut Self {
567 self.ser.expand_empty_elements = expand;
568 self
569 }
570
571 /// Configure indent for a serializer
572 pub fn indent(&mut self, indent_char: char, indent_size: usize) -> &mut Self {
573 self.ser.indent = Indent::Owned(Indentation::new(indent_char as u8, indent_size));
574 self
575 }
576
577 /// Set the indent object for a serializer
578 pub(crate) fn set_indent(&mut self, indent: Indent<'r>) -> &mut Self {
579 self.ser.indent = indent;
580 self
581 }
582
583 /// Creates actual serializer or returns an error if root tag is not defined.
584 /// In that case `err` contains the name of type that cannot be serialized.
585 fn ser(self, err: &str) -> Result<ElementSerializer<'w, 'r, W>, DeError> {
586 if let Some(key) = self.root_tag {
587 Ok(ElementSerializer { ser: self.ser, key })
588 } else {
589 Err(DeError::Unsupported(
590 format!("cannot serialize {} without defined root tag", err).into(),
591 ))
592 }
593 }
594
595 /// Creates actual serializer using root tag or a specified `key` if root tag
596 /// is not defined. Returns an error if root tag is not defined and a `key`
597 /// does not conform [XML rules](XmlName::try_from) for names.
598 fn ser_name(self, key: &'static str) -> Result<ElementSerializer<'w, 'r, W>, DeError> {
599 Ok(ElementSerializer {
600 ser: self.ser,
601 key: match self.root_tag {
602 Some(key) => key,
603 None => XmlName::try_from(key)?,
604 },
605 })
606 }
607}
608
609impl<'w, 'r, W: Write> ser::Serializer for Serializer<'w, 'r, W> {
610 type Ok = ();
611 type Error = DeError;
612
613 type SerializeSeq = ElementSerializer<'w, 'r, W>;
614 type SerializeTuple = ElementSerializer<'w, 'r, W>;
615 type SerializeTupleStruct = ElementSerializer<'w, 'r, W>;
616 type SerializeTupleVariant = Tuple<'w, 'r, W>;
617 type SerializeMap = Map<'w, 'r, W>;
618 type SerializeStruct = Struct<'w, 'r, W>;
619 type SerializeStructVariant = Struct<'w, 'r, W>;
620
621 forward!(serialize_bool(bool));
622
623 forward!(serialize_i8(i8));
624 forward!(serialize_i16(i16));
625 forward!(serialize_i32(i32));
626 forward!(serialize_i64(i64));
627
628 forward!(serialize_u8(u8));
629 forward!(serialize_u16(u16));
630 forward!(serialize_u32(u32));
631 forward!(serialize_u64(u64));
632
633 serde_if_integer128! {
634 forward!(serialize_i128(i128));
635 forward!(serialize_u128(u128));
636 }
637
638 forward!(serialize_f32(f32));
639 forward!(serialize_f64(f64));
640
641 forward!(serialize_char(char));
642 forward!(serialize_str(&str));
643 forward!(serialize_bytes(&[u8]));
644
645 fn serialize_none(self) -> Result<Self::Ok, DeError> {
646 Ok(())
647 }
648
649 fn serialize_some<T: ?Sized + Serialize>(self, value: &T) -> Result<Self::Ok, DeError> {
650 value.serialize(self)
651 }
652
653 fn serialize_unit(self) -> Result<Self::Ok, DeError> {
654 self.ser("`()`")?.serialize_unit()
655 }
656
657 fn serialize_unit_struct(self, name: &'static str) -> Result<Self::Ok, DeError> {
658 self.ser_name(name)?.serialize_unit_struct(name)
659 }
660
661 fn serialize_unit_variant(
662 self,
663 name: &'static str,
664 _variant_index: u32,
665 variant: &'static str,
666 ) -> Result<Self::Ok, DeError> {
667 if variant == TEXT_KEY {
668 // We should write some text but we don't known what text to write
669 Err(DeError::Unsupported(
670 format!(
671 "cannot serialize enum unit variant `{}::$text` as text content value",
672 name
673 )
674 .into(),
675 ))
676 } else {
677 let name = XmlName::try_from(variant)?;
678 self.ser.write_empty(name)
679 }
680 }
681
682 fn serialize_newtype_struct<T: ?Sized + Serialize>(
683 self,
684 name: &'static str,
685 value: &T,
686 ) -> Result<Self::Ok, DeError> {
687 self.ser_name(name)?.serialize_newtype_struct(name, value)
688 }
689
690 fn serialize_newtype_variant<T: ?Sized + Serialize>(
691 self,
692 _name: &'static str,
693 _variant_index: u32,
694 variant: &'static str,
695 value: &T,
696 ) -> Result<Self::Ok, DeError> {
697 if variant == TEXT_KEY {
698 value.serialize(self.ser.into_simple_type_serializer())?;
699 Ok(())
700 } else {
701 let ser = ElementSerializer {
702 ser: self.ser,
703 key: XmlName::try_from(variant)?,
704 };
705 value.serialize(ser)
706 }
707 }
708
709 fn serialize_seq(self, len: Option<usize>) -> Result<Self::SerializeSeq, DeError> {
710 self.ser("sequence")?.serialize_seq(len)
711 }
712
713 fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple, DeError> {
714 self.ser("unnamed tuple")?.serialize_tuple(len)
715 }
716
717 fn serialize_tuple_struct(
718 self,
719 name: &'static str,
720 len: usize,
721 ) -> Result<Self::SerializeTupleStruct, DeError> {
722 self.ser_name(name)?.serialize_tuple_struct(name, len)
723 }
724
725 fn serialize_tuple_variant(
726 self,
727 name: &'static str,
728 _variant_index: u32,
729 variant: &'static str,
730 len: usize,
731 ) -> Result<Self::SerializeTupleVariant, DeError> {
732 if variant == TEXT_KEY {
733 self.ser
734 .into_simple_type_serializer()
735 .serialize_tuple_struct(name, len)
736 .map(Tuple::Text)
737 } else {
738 let ser = ElementSerializer {
739 ser: self.ser,
740 key: XmlName::try_from(variant)?,
741 };
742 ser.serialize_tuple_struct(name, len).map(Tuple::Element)
743 }
744 }
745
746 fn serialize_map(self, len: Option<usize>) -> Result<Self::SerializeMap, DeError> {
747 self.ser("map")?.serialize_map(len)
748 }
749
750 fn serialize_struct(
751 self,
752 name: &'static str,
753 len: usize,
754 ) -> Result<Self::SerializeStruct, DeError> {
755 self.ser_name(name)?.serialize_struct(name, len)
756 }
757
758 fn serialize_struct_variant(
759 self,
760 name: &'static str,
761 _variant_index: u32,
762 variant: &'static str,
763 len: usize,
764 ) -> Result<Self::SerializeStructVariant, DeError> {
765 if variant == TEXT_KEY {
766 Err(DeError::Unsupported(
767 format!(
768 "cannot serialize enum struct variant `{}::$text` as text content value",
769 name
770 )
771 .into(),
772 ))
773 } else {
774 let ser = ElementSerializer {
775 ser: self.ser,
776 key: XmlName::try_from(variant)?,
777 };
778 ser.serialize_struct(name, len)
779 }
780 }
781}