xmlity_quick_xml/
ser.rs

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