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}