diff --git a/crates/dav/src/xml/multistatus.rs b/crates/dav/src/xml/multistatus.rs index b5a1a10..5e8cf25 100644 --- a/crates/dav/src/xml/multistatus.rs +++ b/crates/dav/src/xml/multistatus.rs @@ -47,6 +47,7 @@ pub enum PropstatWrapper { // #[derive(XmlSerialize)] +#[xml(ns = "crate::namespace::NS_DAV")] pub struct ResponseElement { pub href: String, #[xml(serialize_with = "xml_serialize_optional_status")] @@ -85,19 +86,13 @@ impl Default for ResponseElement { // // Extended by sync-token as specified in RFC 6578 #[derive(XmlSerialize, XmlRootTag)] -#[xml(root = b"multistatus")] +#[xml(root = b"multistatus", ns = "crate::namespace::NS_DAV")] +#[xml(ns_prefix(crate::namespace::NS_DAV = b"D"))] pub struct MultistatusElement { #[xml(rename = b"response", flatten)] pub responses: Vec>, #[xml(rename = b"response", flatten)] pub member_responses: Vec>, - // TODO: napespaces - // pub ns_dav: &'static str, - // pub ns_davpush: &'static str, - // pub ns_caldav: &'static str, - // pub ns_ical: &'static str, - // pub ns_calendarserver: &'static str, - // pub ns_carddav: &'static str, pub sync_token: Option, } @@ -106,12 +101,6 @@ impl Default for MultistatusElement Self { responses: vec![], member_responses: vec![], - // ns_dav: Namespace::Dav.as_str(), - // ns_davpush: Namespace::DavPush.as_str(), - // ns_caldav: Namespace::CalDAV.as_str(), - // ns_ical: Namespace::ICal.as_str(), - // ns_calendarserver: Namespace::CServer.as_str(), - // ns_carddav: Namespace::CardDAV.as_str(), sync_token: None, } } diff --git a/crates/xml/derive/src/attrs.rs b/crates/xml/derive/src/attrs.rs index 034464d..0c5b39b 100644 --- a/crates/xml/derive/src/attrs.rs +++ b/crates/xml/derive/src/attrs.rs @@ -1,3 +1,5 @@ +use std::collections::HashMap; + use darling::{util::Flag, FromDeriveInput, FromField, FromMeta, FromVariant}; use syn::LitByteStr; @@ -10,8 +12,7 @@ pub struct ContainerAttrs { pub struct TagAttrs { pub rename: Option, pub ns_strict: Flag, - // pub ns: Option, - pub ns: Option, + pub ns: Option, } #[derive(Default, FromVariant)] @@ -38,7 +39,9 @@ pub struct StructAttrs { pub container: ContainerAttrs, pub root: Option, - pub ns: Option, + pub ns: Option, + #[darling(default)] + pub ns_prefix: HashMap, pub allow_invalid: Flag, } diff --git a/crates/xml/derive/src/xml_struct.rs b/crates/xml/derive/src/xml_struct.rs index 0054105..a810040 100644 --- a/crates/xml/derive/src/xml_struct.rs +++ b/crates/xml/derive/src/xml_struct.rs @@ -57,10 +57,28 @@ impl NamedStruct { Some(ns) => quote! { Some(#ns) }, None => quote! { None }, }; + + let prefixes = if self.attrs.root.is_some() { + self.attrs + .ns_prefix + .iter() + .map(|(ns, prefix)| { + quote! { (#ns, #prefix.as_ref()) } + }) + .collect() + } else { + vec![] + }; + quote! { impl #impl_generics ::rustical_xml::XmlRootTag for #ident #type_generics #where_clause { fn root_tag() -> &'static [u8] { #root } fn root_ns() -> Option<::quick_xml::name::Namespace<'static>> { #ns } + fn root_ns_prefixes() -> ::std::collections::HashMap<::quick_xml::name::Namespace<'static>, &'static [u8]> { + ::std::collections::HashMap::from_iter(vec![ + #(#prefixes),* + ]) + } } } } @@ -224,6 +242,23 @@ impl NamedStruct { let is_empty = tag_writers.len() == 0; + // If we are the root element write the xmlns attributes + let prefix_attributes = if self.attrs.root.is_some() { + self.attrs + .ns_prefix + .iter() + .map(|(ns, prefix)| { + let attr_name = [b"xmlns:".as_ref(), &prefix.value()].concat(); + let a = syn::LitByteStr::new(&attr_name, prefix.span()); + quote! { + bytes_start.push_attribute((#a.as_ref(), #ns.as_ref())); + } + }) + .collect() + } else { + vec![] + }; + quote! { impl #impl_generics ::rustical_xml::XmlSerialize for #ident #type_generics #where_clause { fn serialize( @@ -252,6 +287,7 @@ impl NamedStruct { bytes_start.push_attribute((b"xmlns".as_ref(), ns.as_ref())); } } + #(#prefix_attributes);* if let Some(attrs) = self.attributes() { bytes_start.extend_attributes(attrs); } diff --git a/crates/xml/src/lib.rs b/crates/xml/src/lib.rs index e21993e..30484a2 100644 --- a/crates/xml/src/lib.rs +++ b/crates/xml/src/lib.rs @@ -98,4 +98,5 @@ impl XmlDeserialize for Unparsed { pub trait XmlRootTag { fn root_tag() -> &'static [u8]; fn root_ns() -> Option>; + fn root_ns_prefixes() -> HashMap, &'static [u8]>; } diff --git a/crates/xml/src/se.rs b/crates/xml/src/se.rs index ba57d7d..9283223 100644 --- a/crates/xml/src/se.rs +++ b/crates/xml/src/se.rs @@ -50,7 +50,7 @@ impl XmlSerializeRoot for T { &self, writer: &mut quick_xml::Writer, ) -> std::io::Result<()> { - let namespaces = HashMap::new(); + let namespaces = Self::root_ns_prefixes(); self.serialize(Self::root_ns(), Some(Self::root_tag()), &namespaces, writer) } }