xmlity_quick_xml/
ser.rs

1use core::str;
2use std::borrow::Cow;
3use std::collections::BTreeMap;
4use std::io::Write;
5
6use quick_xml::events::{BytesCData, BytesDecl, BytesEnd, BytesPI, BytesStart, BytesText, Event};
7use quick_xml::writer::Writer as QuickXmlWriter;
8
9use xmlity::ser::IncludePrefix;
10use xmlity::{ser, ExpandedName, Prefix, QName, Serialize, XmlNamespace};
11
12use crate::{declaration_into_attribute, Attribute, OwnedQuickName, XmlnsDeclaration};
13
14use super::Error;
15
16fn serializer_to_string<T>(serializer: QuickXmlWriter<Vec<u8>>, value: &T) -> Result<String, Error>
17where
18    T: Serialize,
19{
20    let mut serializer = Serializer::from(serializer);
21    value.serialize(&mut serializer)?;
22    let bytes = serializer.into_inner();
23
24    String::from_utf8(bytes).map_err(Error::InvalidUtf8)
25}
26
27pub fn to_string<T>(value: &T) -> Result<String, Error>
28where
29    T: Serialize,
30{
31    serializer_to_string(QuickXmlWriter::new(Vec::new()), value)
32}
33
34pub fn to_string_pretty<T>(value: &T, indentation: usize) -> Result<String, Error>
35where
36    T: Serialize,
37{
38    serializer_to_string(
39        QuickXmlWriter::new_with_indent(Vec::new(), b' ', indentation),
40        value,
41    )
42}
43
44struct NamespaceScope<'a> {
45    pub defined_namespaces: BTreeMap<Prefix<'a>, XmlNamespace<'a>>,
46}
47
48impl<'a> NamespaceScope<'a> {
49    pub fn new() -> Self {
50        Self {
51            defined_namespaces: BTreeMap::new(),
52        }
53    }
54
55    const XML_PREFIX: Prefix<'static> = Prefix::new_dangerous("xml");
56    const XML_NAMESPACE: XmlNamespace<'static> =
57        XmlNamespace::new_dangerous("http://www.w3.org/XML/1998/namespace");
58
59    pub fn top_scope() -> Self {
60        let mut scope = Self::new();
61        scope
62            .defined_namespaces
63            .insert(Self::XML_PREFIX, Self::XML_NAMESPACE);
64        scope
65    }
66
67    pub fn get_namespace<'b>(&'b self, prefix: &'b Prefix<'b>) -> Option<&'b XmlNamespace<'a>> {
68        self.defined_namespaces.get(prefix)
69    }
70}
71
72struct NamespaceScopeContainer<'a> {
73    scopes: Vec<NamespaceScope<'a>>,
74    prefix_generator: PrefixGenerator,
75}
76
77struct PrefixGenerator {
78    count: usize,
79}
80
81impl PrefixGenerator {
82    pub fn index_to_name(index: usize) -> Prefix<'static> {
83        // 0 = a0
84        // 1 = a1
85        // 26 = b0
86        // 27 = b1
87        // 52 = c0
88        // 53 = c1
89        // ...
90
91        let letter = (index / 26) as u8 + b'a';
92        let number = (index % 26) as u8 + b'0';
93        let mut name = String::with_capacity(2);
94        name.push(letter as char);
95        name.push(number as char);
96        Prefix::new(name).expect("Invalid prefix generated")
97    }
98
99    pub fn new() -> Self {
100        Self { count: 0 }
101    }
102
103    pub fn new_prefix(&mut self) -> Prefix<'static> {
104        let name = Self::index_to_name(self.count);
105        self.count += 1;
106        name
107    }
108}
109
110impl<'a> NamespaceScopeContainer<'a> {
111    pub fn new() -> Self {
112        Self {
113            scopes: vec![NamespaceScope::top_scope()],
114            prefix_generator: PrefixGenerator::new(),
115        }
116    }
117
118    pub fn push_scope(&mut self) {
119        self.scopes.push(NamespaceScope::new())
120    }
121
122    pub fn pop_scope(&mut self) -> Option<NamespaceScope> {
123        self.scopes.pop()
124    }
125
126    pub fn get_namespace<'b>(&'b self, prefix: &'b Prefix<'b>) -> Option<&'b XmlNamespace<'a>> {
127        self.scopes
128            .iter()
129            .rev()
130            .find_map(|a| a.get_namespace(prefix))
131    }
132
133    /// Find matching prefix
134    pub fn find_matching_namespace<'b>(
135        &'b self,
136        namespace: &'b XmlNamespace<'b>,
137    ) -> Option<&'b Prefix<'a>> {
138        self.scopes.iter().rev().find_map(|a| {
139            a.defined_namespaces
140                .iter()
141                .find(|(_, found_namespace)| namespace == *found_namespace)
142                .map(|(prefix, _)| prefix)
143        })
144    }
145
146    /// This function takes in a namespace and tries to resolve it in different ways depending on the options provided. Unless `always_declare` is true, it will try to use an existing declaration. Otherwise, or if the namespace has not yet been declared, it will provide a declaration.
147    pub fn resolve_namespace<'b>(
148        &'b mut self,
149        namespace: &'b XmlNamespace<'b>,
150        preferred_prefix: Option<&'b Prefix<'b>>,
151        always_declare: IncludePrefix,
152    ) -> (Prefix<'b>, Option<XmlnsDeclaration<'b>>) {
153        let existing_prefix = self
154            .find_matching_namespace(namespace)
155            // If we should always declare, we simply pretend it's not declared yet.
156            .filter(|_p| always_declare != IncludePrefix::Always);
157
158        if let Some(existing_prefix) = existing_prefix {
159            return (existing_prefix.clone(), None);
160        }
161
162        // If the namespace is not declared, use the specifically requested preferred prefix...
163        // ...if it is not already used and not the same as the existing prefix.
164        let prefix = preferred_prefix
165            .filter(|p| self.get_namespace(p).is_none_or(|n| n == namespace))
166            // If the preferred prefix is not available, use the preferred namespace prefix from the serializer...
167            .or_else(|| {
168                preferred_prefix
169                    // ...if it is not already used and not the same as the existing prefix.
170                    .filter(|p| self.get_namespace(p).is_none_or(|n| n == namespace))
171            })
172            .cloned()
173            // If the preferred namespace prefix is not available, use a random prefix.
174            .unwrap_or_else(|| self.prefix_generator.new_prefix());
175
176        let xmlns = XmlnsDeclaration::new(prefix.clone(), namespace.clone());
177
178        self.scopes.last_mut().map(|a| {
179            a.defined_namespaces
180                .insert(prefix.clone().into_owned(), namespace.clone().into_owned())
181        });
182
183        (prefix, Some(xmlns))
184    }
185
186    pub fn resolve_name<'b>(
187        &mut self,
188        name: ExpandedName<'b>,
189        preferred_prefix: Option<&Prefix<'b>>,
190        always_declare: IncludePrefix,
191    ) -> (QName<'b>, Option<XmlnsDeclaration<'b>>) {
192        let (prefix, declaration) = name
193            .namespace()
194            .map(|namespace| self.resolve_namespace(namespace, preferred_prefix, always_declare))
195            .unzip();
196
197        let declaration = declaration.flatten().map(|a| a.into_owned());
198        let resolved_prefix = prefix.map(|a| a.into_owned());
199
200        let name = name.to_q_name(resolved_prefix);
201        (name.into_owned(), declaration)
202    }
203}
204
205pub struct Serializer<W: Write> {
206    writer: QuickXmlWriter<W>,
207    preferred_namespace_prefixes: BTreeMap<XmlNamespace<'static>, Prefix<'static>>,
208    namespace_scopes: NamespaceScopeContainer<'static>,
209}
210
211impl<W: Write> Serializer<W> {
212    pub fn new(writer: QuickXmlWriter<W>) -> Self {
213        Self::new_with_namespaces(writer, BTreeMap::new())
214    }
215
216    pub fn new_with_namespaces(
217        writer: QuickXmlWriter<W>,
218        preferred_namespace_prefixes: BTreeMap<XmlNamespace<'static>, Prefix<'static>>,
219    ) -> Self {
220        Self {
221            writer,
222            preferred_namespace_prefixes,
223            namespace_scopes: NamespaceScopeContainer::new(),
224        }
225    }
226
227    pub fn into_inner(self) -> W {
228        self.writer.into_inner()
229    }
230
231    pub fn push_namespace_scope(&mut self) {
232        self.namespace_scopes.push_scope()
233    }
234
235    pub fn pop_namespace_scope(&mut self) {
236        self.namespace_scopes.pop_scope();
237    }
238
239    pub fn add_preferred_prefix(
240        &mut self,
241        namespace: XmlNamespace<'static>,
242        prefix: Prefix<'static>,
243    ) {
244        self.preferred_namespace_prefixes.insert(namespace, prefix);
245    }
246
247    pub fn resolve_name<'b>(
248        &mut self,
249        name: ExpandedName<'b>,
250        preferred_prefix: Option<&Prefix<'b>>,
251        always_declare: IncludePrefix,
252    ) -> (QName<'b>, Option<XmlnsDeclaration<'b>>) {
253        let name2 = name.clone();
254        let preferred_prefix = preferred_prefix.or_else(|| {
255            name2
256                .namespace()
257                .and_then(|a| self.preferred_namespace_prefixes.get(a))
258        });
259
260        self.namespace_scopes
261            .resolve_name(name, preferred_prefix, always_declare)
262    }
263}
264
265impl<W: Write> From<QuickXmlWriter<W>> for Serializer<W> {
266    fn from(writer: QuickXmlWriter<W>) -> Self {
267        Self::new(writer)
268    }
269}
270
271impl<W: Write> From<W> for Serializer<W> {
272    fn from(writer: W) -> Self {
273        Self::new(QuickXmlWriter::new(writer))
274    }
275}
276
277pub struct SerializeElement<'s, W: Write> {
278    serializer: &'s mut Serializer<W>,
279    name: ExpandedName<'static>,
280    attributes: Vec<Attribute<'static>>,
281    preferred_prefix: Option<Prefix<'static>>,
282    enforce_prefix: IncludePrefix,
283}
284
285pub struct AttributeSerializer<'t> {
286    name: ExpandedName<'static>,
287    on_end_add_to: &'t mut Vec<Attribute<'static>>,
288    preferred_prefix: Option<Prefix<'static>>,
289    enforce_prefix: IncludePrefix,
290}
291
292impl ser::SerializeAttributeAccess for AttributeSerializer<'_> {
293    type Ok = ();
294    type Error = Error;
295
296    fn include_prefix(&mut self, should_enforce: IncludePrefix) -> Result<Self::Ok, Self::Error> {
297        self.enforce_prefix = should_enforce;
298        Ok(())
299    }
300
301    fn preferred_prefix(
302        &mut self,
303        preferred_prefix: Option<xmlity::Prefix<'_>>,
304    ) -> Result<Self::Ok, Self::Error> {
305        self.preferred_prefix = preferred_prefix.map(Prefix::into_owned);
306        Ok(())
307    }
308
309    fn end<S: AsRef<str>>(self, value: S) -> Result<Self::Ok, Self::Error> {
310        self.on_end_add_to.push(Attribute {
311            name: self.name.into_owned(),
312            value: value.as_ref().to_owned(),
313            preferred_prefix: self.preferred_prefix,
314            enforce_prefix: self.enforce_prefix,
315        });
316
317        Ok(())
318    }
319}
320
321pub struct AttributeVecSerializer<'t> {
322    attributes: &'t mut Vec<Attribute<'static>>,
323}
324
325impl ser::AttributeSerializer for AttributeVecSerializer<'_> {
326    type Error = Error;
327
328    type Ok = ();
329    type SerializeAttribute<'a>
330        = AttributeSerializer<'a>
331    where
332        Self: 'a;
333
334    fn serialize_attribute(
335        &mut self,
336        name: &'_ ExpandedName<'_>,
337    ) -> Result<Self::SerializeAttribute<'_>, Self::Error> {
338        Ok(Self::SerializeAttribute {
339            name: name.clone().into_owned(),
340            on_end_add_to: &mut self.attributes,
341            preferred_prefix: None,
342            enforce_prefix: IncludePrefix::default(),
343        })
344    }
345
346    fn serialize_none(&mut self) -> Result<Self::Ok, Self::Error> {
347        Ok(())
348    }
349}
350
351/// This exists to allow us to transfer the practically completed BytesStart out of `finish_start` to then become the `quick_xml` BytesStart which is only exists by references to data.
352pub struct OwnedBytesStart {
353    name: OwnedQuickName,
354    attributes: Vec<(OwnedQuickName, Vec<u8>)>,
355}
356
357impl OwnedBytesStart {
358    pub fn as_quick_xml(&self) -> BytesStart<'_> {
359        BytesStart::from(self.name.as_ref()).with_attributes(self.attributes.iter().map(
360            |(key, value)| quick_xml::events::attributes::Attribute {
361                key: key.as_ref(),
362                value: Cow::Borrowed(value),
363            },
364        ))
365    }
366}
367
368impl<'s, W: Write> SerializeElement<'s, W> {
369    fn finish_start(self) -> (OwnedBytesStart, QName<'static>, &'s mut Serializer<W>) {
370        let Self {
371            serializer,
372            name,
373            attributes,
374            enforce_prefix,
375            preferred_prefix,
376        } = self;
377
378        let mut resolve_name_or_declare =
379            |name: &ExpandedName<'_>,
380             preferred_prefix: Option<&Prefix<'_>>,
381             enforce_prefix: IncludePrefix|
382             -> (QName<'static>, Option<XmlnsDeclaration<'static>>) {
383                let (qname, decl) =
384                    serializer.resolve_name(name.clone(), preferred_prefix, enforce_prefix);
385
386                (qname.into_owned(), decl.map(|a| a.into_owned()))
387            };
388
389        let (elem_qname, elem_name_decl) =
390            resolve_name_or_declare(&name, preferred_prefix.as_ref(), enforce_prefix);
391
392        let (attr_prefixes, attr_decls): (Vec<_>, Vec<_>) = attributes
393            .iter()
394            .map(|a| &a.name)
395            .map(|name| resolve_name_or_declare(name, None, IncludePrefix::default()))
396            .unzip();
397
398        let decls = elem_name_decl
399            .into_iter()
400            .chain(attr_decls.into_iter().flatten())
401            .collect::<Vec<_>>();
402
403        // Add declared namespaces first
404        let mut q_attributes = decls
405            .iter()
406            .map(|decl| declaration_into_attribute(decl.clone()))
407            .map(|attr| {
408                (
409                    OwnedQuickName::new(&attr.name),
410                    attr.value.as_bytes().to_owned(),
411                )
412            })
413            .collect::<Vec<_>>();
414
415        // Then add the attributes
416        q_attributes.extend(
417            attributes
418                .into_iter()
419                .zip(attr_prefixes)
420                .map(|(attr, qname)| attr.resolve(qname.prefix().cloned()))
421                .map(|attr| {
422                    (
423                        OwnedQuickName::new(&attr.name),
424                        attr.value.as_bytes().to_owned(),
425                    )
426                }),
427        );
428
429        let bytes_start = OwnedBytesStart {
430            name: OwnedQuickName::new(&elem_qname),
431            attributes: q_attributes,
432        };
433
434        (bytes_start, elem_qname, serializer)
435    }
436}
437
438impl<W: Write> ser::SerializeAttributes for SerializeElement<'_, W> {
439    type Ok = ();
440    type Error = Error;
441
442    fn serialize_attribute<A: ser::SerializeAttribute>(
443        &mut self,
444        a: &A,
445    ) -> Result<Self::Ok, Self::Error> {
446        a.serialize_attribute(AttributeVecSerializer {
447            attributes: &mut self.attributes,
448        })
449    }
450}
451
452impl<'s, W: Write> ser::SerializeElement for SerializeElement<'s, W> {
453    type ChildrenSerializeSeq = ChildrenSerializeSeq<'s, W>;
454
455    fn include_prefix(&mut self, should_enforce: IncludePrefix) -> Result<Self::Ok, Self::Error> {
456        self.enforce_prefix = should_enforce;
457        Ok(())
458    }
459    fn preferred_prefix(
460        &mut self,
461        preferred_prefix: Option<Prefix<'_>>,
462    ) -> Result<Self::Ok, Self::Error> {
463        self.preferred_prefix = preferred_prefix.map(Prefix::into_owned);
464        Ok(())
465    }
466
467    fn serialize_children(self) -> Result<Self::ChildrenSerializeSeq, Self::Error> {
468        self.serializer.push_namespace_scope();
469        let (bytes_start, end_name, serializer) = self.finish_start();
470
471        Ok(ChildrenSerializeSeq {
472            bytes_start: Some(bytes_start),
473            serializer,
474            end_name,
475        })
476    }
477
478    fn end(self) -> Result<Self::Ok, Self::Error> {
479        self.serializer.push_namespace_scope();
480        let (bytes_start, _, serializer) = self.finish_start();
481
482        serializer
483            .writer
484            .write_event(Event::Empty(bytes_start.as_quick_xml()))
485            .map_err(Error::Io)?;
486
487        serializer.pop_namespace_scope();
488
489        Ok(())
490    }
491}
492
493pub struct ChildrenSerializeSeq<'s, W: Write> {
494    bytes_start: Option<OwnedBytesStart>,
495    serializer: &'s mut Serializer<W>,
496    end_name: QName<'static>,
497}
498
499impl<W: Write> ser::SerializeSeq for ChildrenSerializeSeq<'_, W> {
500    type Ok = ();
501    type Error = Error;
502
503    fn serialize_element<V: Serialize>(&mut self, value: &V) -> Result<Self::Ok, Self::Error> {
504        value.serialize(SerializerWithPossibleBytesStart {
505            serializer: self.serializer,
506            possible_bytes_start: Some(&mut self.bytes_start),
507        })
508    }
509
510    fn end(self) -> Result<Self::Ok, Self::Error> {
511        // If we have a bytes_start, then we never wrote the start event, so we need to write an empty element instead.
512        if let Some(bytes_start) = self.bytes_start {
513            self.serializer
514                .writer
515                .write_event(Event::Empty(bytes_start.as_quick_xml()))
516                .map_err(Error::Io)?;
517        } else {
518            let end_name = OwnedQuickName::new(&self.end_name);
519
520            let bytes_end = BytesEnd::from(end_name.as_ref());
521
522            self.serializer
523                .writer
524                .write_event(Event::End(bytes_end))
525                .map_err(Error::Io)?;
526        }
527
528        self.serializer.pop_namespace_scope();
529
530        Ok(())
531    }
532}
533
534pub struct SerializeSeq<'e, 'b, W: Write> {
535    serializer: &'e mut Serializer<W>,
536    possible_bytes_start: Option<&'b mut Option<OwnedBytesStart>>,
537}
538
539impl<W: Write> ser::SerializeSeq for SerializeSeq<'_, '_, W> {
540    type Ok = ();
541    type Error = Error;
542
543    fn serialize_element<V: Serialize>(&mut self, v: &V) -> Result<Self::Ok, Self::Error> {
544        v.serialize(SerializerWithPossibleBytesStart {
545            serializer: self.serializer,
546            possible_bytes_start: self.possible_bytes_start.as_deref_mut(),
547        })
548    }
549
550    fn end(self) -> Result<Self::Ok, Self::Error> {
551        Ok(())
552    }
553}
554
555impl<'s, W: Write> xmlity::Serializer for &'s mut Serializer<W> {
556    type Ok = ();
557    type Error = Error;
558    type SerializeElement = SerializeElement<'s, W>;
559    type SerializeSeq = SerializeSeq<'s, 'static, W>;
560
561    fn serialize_cdata<S: AsRef<str>>(self, text: S) -> Result<Self::Ok, Self::Error> {
562        self.writer
563            .write_event(Event::CData(BytesCData::new(text.as_ref())))
564            .map_err(Error::Io)
565    }
566
567    fn serialize_text<S: AsRef<str>>(self, text: S) -> Result<Self::Ok, Self::Error> {
568        self.writer
569            .write_event(Event::Text(BytesText::from_escaped(text.as_ref())))
570            .map_err(Error::Io)
571    }
572
573    fn serialize_element<'a>(
574        self,
575        name: &'a ExpandedName<'a>,
576    ) -> Result<Self::SerializeElement, Self::Error> {
577        Ok(SerializeElement {
578            serializer: self,
579            name: name.clone().into_owned(),
580            attributes: Vec::new(),
581            preferred_prefix: None,
582            enforce_prefix: IncludePrefix::default(),
583        })
584    }
585
586    fn serialize_seq(self) -> Result<Self::SerializeSeq, Self::Error> {
587        Ok(SerializeSeq {
588            serializer: self,
589            possible_bytes_start: None,
590        })
591    }
592
593    fn serialize_decl<S: AsRef<str>>(
594        self,
595        version: S,
596        encoding: Option<S>,
597        standalone: Option<S>,
598    ) -> Result<Self::Ok, Self::Error> {
599        self.writer
600            .write_event(Event::Decl(BytesDecl::new(
601                version.as_ref(),
602                encoding.as_ref().map(|s| s.as_ref()),
603                standalone.as_ref().map(|s| s.as_ref()),
604            )))
605            .map_err(Error::Io)
606    }
607
608    fn serialize_pi<S: AsRef<[u8]>>(self, text: S) -> Result<Self::Ok, Self::Error> {
609        self.writer
610            .write_event(Event::PI(BytesPI::new(
611                str::from_utf8(text.as_ref()).unwrap(),
612            )))
613            .map_err(Error::Io)
614    }
615
616    fn serialize_comment<S: AsRef<[u8]>>(self, text: S) -> Result<Self::Ok, Self::Error> {
617        self.writer
618            .write_event(Event::Comment(BytesText::from_escaped(
619                str::from_utf8(text.as_ref()).unwrap(),
620            )))
621            .map_err(Error::Io)
622    }
623
624    fn serialize_doctype<S: AsRef<[u8]>>(self, text: S) -> Result<Self::Ok, Self::Error> {
625        self.writer
626            .write_event(Event::DocType(BytesText::from_escaped(
627                str::from_utf8(text.as_ref()).unwrap(),
628            )))
629            .map_err(Error::Io)
630    }
631
632    fn serialize_none(self) -> Result<Self::Ok, Self::Error> {
633        Ok(())
634    }
635}
636
637pub struct SerializerWithPossibleBytesStart<'a, 'b, W: Write> {
638    serializer: &'a mut Serializer<W>,
639    possible_bytes_start: Option<&'b mut Option<OwnedBytesStart>>,
640}
641
642impl<W: Write> SerializerWithPossibleBytesStart<'_, '_, W> {
643    pub fn try_start(&mut self) -> Result<(), Error> {
644        if let Some(bytes_start) = self.possible_bytes_start.take().and_then(Option::take) {
645            self.serializer
646                .writer
647                .write_event(Event::Start(bytes_start.as_quick_xml()))
648                .map_err(Error::Io)?;
649        }
650        Ok(())
651    }
652}
653
654impl<'s, 'b, W: Write> xmlity::Serializer for SerializerWithPossibleBytesStart<'s, 'b, W> {
655    type Ok = ();
656    type Error = Error;
657    type SerializeElement = SerializeElement<'s, W>;
658    type SerializeSeq = SerializeSeq<'s, 'b, W>;
659
660    fn serialize_cdata<S: AsRef<str>>(mut self, text: S) -> Result<Self::Ok, Self::Error> {
661        self.try_start()?;
662        self.serializer.serialize_cdata(text)
663    }
664
665    fn serialize_text<S: AsRef<str>>(mut self, text: S) -> Result<Self::Ok, Self::Error> {
666        self.try_start()?;
667        self.serializer.serialize_text(text)
668    }
669
670    fn serialize_element<'a>(
671        mut self,
672        name: &'a ExpandedName<'a>,
673    ) -> Result<Self::SerializeElement, Self::Error> {
674        self.try_start()?;
675        self.serializer.serialize_element(name)
676    }
677
678    fn serialize_seq(self) -> Result<Self::SerializeSeq, Self::Error> {
679        Ok(SerializeSeq {
680            serializer: self.serializer,
681            possible_bytes_start: self.possible_bytes_start,
682        })
683    }
684
685    fn serialize_decl<S: AsRef<str>>(
686        mut self,
687        version: S,
688        encoding: Option<S>,
689        standalone: Option<S>,
690    ) -> Result<Self::Ok, Self::Error> {
691        self.try_start()?;
692        self.serializer
693            .serialize_decl(version, encoding, standalone)
694    }
695
696    fn serialize_pi<S: AsRef<[u8]>>(mut self, text: S) -> Result<Self::Ok, Self::Error> {
697        self.try_start()?;
698        self.serializer.serialize_pi(text)
699    }
700
701    fn serialize_comment<S: AsRef<[u8]>>(mut self, text: S) -> Result<Self::Ok, Self::Error> {
702        self.try_start()?;
703        self.serializer.serialize_comment(text)
704    }
705
706    fn serialize_doctype<S: AsRef<[u8]>>(mut self, text: S) -> Result<Self::Ok, Self::Error> {
707        self.try_start()?;
708        self.serializer.serialize_doctype(text)
709    }
710
711    fn serialize_none(self) -> Result<Self::Ok, Self::Error> {
712        Ok(())
713    }
714}