rustical_xml/
se.rs

1use crate::XmlRootTag;
2use quick_xml::{
3    events::{attributes::Attribute, BytesStart, Event},
4    name::{Namespace, QName},
5};
6use std::collections::HashMap;
7pub use xml_derive::XmlSerialize;
8
9pub trait XmlSerialize {
10    fn serialize<W: std::io::Write>(
11        &self,
12        ns: Option<Namespace>,
13        tag: Option<&[u8]>,
14        namespaces: &HashMap<Namespace, &[u8]>,
15        writer: &mut quick_xml::Writer<W>,
16    ) -> std::io::Result<()>;
17
18    fn attributes<'a>(&self) -> Option<impl IntoIterator<Item: Into<Attribute<'a>>>>;
19}
20
21impl<T: XmlSerialize> XmlSerialize for Option<T> {
22    fn serialize<W: std::io::Write>(
23        &self,
24        ns: Option<Namespace>,
25        tag: Option<&[u8]>,
26        namespaces: &HashMap<Namespace, &[u8]>,
27        writer: &mut quick_xml::Writer<W>,
28    ) -> std::io::Result<()> {
29        if let Some(some) = self {
30            some.serialize(ns, tag, namespaces, writer)
31        } else {
32            Ok(())
33        }
34    }
35
36    #[allow(refining_impl_trait)]
37    fn attributes<'a>(&self) -> Option<Vec<Attribute<'a>>> {
38        None
39    }
40}
41
42pub trait XmlSerializeRoot {
43    fn serialize_root<W: std::io::Write>(
44        &self,
45        writer: &mut quick_xml::Writer<W>,
46    ) -> std::io::Result<()>;
47}
48
49impl<T: XmlSerialize + XmlRootTag> XmlSerializeRoot for T {
50    fn serialize_root<W: std::io::Write>(
51        &self,
52        writer: &mut quick_xml::Writer<W>,
53    ) -> std::io::Result<()> {
54        let namespaces = Self::root_ns_prefixes();
55        self.serialize(Self::root_ns(), Some(Self::root_tag()), &namespaces, writer)
56    }
57}
58
59impl XmlSerialize for () {
60    fn serialize<W: std::io::Write>(
61        &self,
62        ns: Option<Namespace>,
63        tag: Option<&[u8]>,
64        namespaces: &HashMap<Namespace, &[u8]>,
65        writer: &mut quick_xml::Writer<W>,
66    ) -> std::io::Result<()> {
67        let prefix = ns
68            .map(|ns| namespaces.get(&ns))
69            .unwrap_or(None)
70            .map(|prefix| {
71                if !prefix.is_empty() {
72                    [*prefix, b":"].concat()
73                } else {
74                    Vec::new()
75                }
76            });
77        let has_prefix = prefix.is_some();
78        let tagname = tag.map(|tag| [&prefix.unwrap_or_default(), tag].concat());
79        let qname = tagname.as_ref().map(|tagname| QName(tagname));
80        if let Some(qname) = &qname {
81            let mut bytes_start = BytesStart::from(qname.to_owned());
82            if !has_prefix {
83                if let Some(ns) = &ns {
84                    bytes_start.push_attribute((b"xmlns".as_ref(), ns.as_ref()));
85                }
86            }
87            writer.write_event(Event::Empty(bytes_start))?;
88        }
89        Ok(())
90    }
91
92    #[allow(refining_impl_trait)]
93    fn attributes<'a>(&self) -> Option<Vec<quick_xml::events::attributes::Attribute<'a>>> {
94        None
95    }
96}