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