use crate::XmlRootTag; use quick_xml::{ events::{BytesStart, Event, attributes::Attribute}, name::{Namespace, QName}, }; use std::collections::HashMap; pub use xml_derive::XmlSerialize; pub trait XmlSerialize { fn serialize( &self, ns: Option, tag: Option<&[u8]>, namespaces: &HashMap, writer: &mut quick_xml::Writer<&mut Vec>, ) -> std::io::Result<()>; fn attributes<'a>(&self) -> Option>>; } impl XmlSerialize for Option { fn serialize( &self, ns: Option, tag: Option<&[u8]>, namespaces: &HashMap, writer: &mut quick_xml::Writer<&mut Vec>, ) -> std::io::Result<()> { if let Some(some) = self { some.serialize(ns, tag, namespaces, writer) } else { Ok(()) } } fn attributes<'a>(&self) -> Option>> { None } } pub trait XmlSerializeRoot { fn serialize_root(&self, writer: &mut quick_xml::Writer<&mut Vec>) -> std::io::Result<()>; fn serialize_to_string(&self) -> std::io::Result { let mut buf: Vec<_> = b"\n".into(); let mut writer = quick_xml::Writer::new_with_indent(&mut buf, b' ', 4); self.serialize_root(&mut writer)?; Ok(String::from_utf8_lossy(&buf).to_string()) } } impl XmlSerializeRoot for T { fn serialize_root(&self, writer: &mut quick_xml::Writer<&mut Vec>) -> std::io::Result<()> { let namespaces = Self::root_ns_prefixes(); self.serialize(Self::root_ns(), Some(Self::root_tag()), &namespaces, writer) } } impl XmlSerialize for () { fn serialize( &self, ns: Option, tag: Option<&[u8]>, namespaces: &HashMap, writer: &mut quick_xml::Writer<&mut Vec>, ) -> std::io::Result<()> { let prefix = ns .map(|ns| namespaces.get(&ns)) .unwrap_or(None) .map(|prefix| { if !prefix.is_empty() { [*prefix, b":"].concat() } else { Vec::new() } }); let has_prefix = prefix.is_some(); let tagname = tag.map(|tag| [&prefix.unwrap_or_default(), tag].concat()); let qname = tagname.as_ref().map(|tagname| QName(tagname)); if let Some(qname) = &qname { let mut bytes_start = BytesStart::from(qname.to_owned()); if !has_prefix { if let Some(ns) = &ns { bytes_start.push_attribute((b"xmlns".as_ref(), ns.as_ref())); } } writer.write_event(Event::Empty(bytes_start))?; } Ok(()) } fn attributes<'a>(&self) -> Option>> { None } }