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