mirror of
https://github.com/lennart-k/rustical.git
synced 2025-12-13 22:52:22 +00:00
xml: Add namespace prefixes
This commit is contained in:
@@ -47,6 +47,7 @@ pub enum PropstatWrapper<T: XmlSerialize> {
|
|||||||
// <!ELEMENT response (href, ((href*, status)|(propstat+)),
|
// <!ELEMENT response (href, ((href*, status)|(propstat+)),
|
||||||
// responsedescription?) >
|
// responsedescription?) >
|
||||||
#[derive(XmlSerialize)]
|
#[derive(XmlSerialize)]
|
||||||
|
#[xml(ns = "crate::namespace::NS_DAV")]
|
||||||
pub struct ResponseElement<PropstatType: XmlSerialize> {
|
pub struct ResponseElement<PropstatType: XmlSerialize> {
|
||||||
pub href: String,
|
pub href: String,
|
||||||
#[xml(serialize_with = "xml_serialize_optional_status")]
|
#[xml(serialize_with = "xml_serialize_optional_status")]
|
||||||
@@ -85,19 +86,13 @@ impl<PT: XmlSerialize> Default for ResponseElement<PT> {
|
|||||||
// <!ELEMENT multistatus (response+, responsedescription?) >
|
// <!ELEMENT multistatus (response+, responsedescription?) >
|
||||||
// Extended by sync-token as specified in RFC 6578
|
// Extended by sync-token as specified in RFC 6578
|
||||||
#[derive(XmlSerialize, XmlRootTag)]
|
#[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<PropType: XmlSerialize, MemberPropType: XmlSerialize> {
|
pub struct MultistatusElement<PropType: XmlSerialize, MemberPropType: XmlSerialize> {
|
||||||
#[xml(rename = b"response", flatten)]
|
#[xml(rename = b"response", flatten)]
|
||||||
pub responses: Vec<ResponseElement<PropType>>,
|
pub responses: Vec<ResponseElement<PropType>>,
|
||||||
#[xml(rename = b"response", flatten)]
|
#[xml(rename = b"response", flatten)]
|
||||||
pub member_responses: Vec<ResponseElement<MemberPropType>>,
|
pub member_responses: Vec<ResponseElement<MemberPropType>>,
|
||||||
// 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<String>,
|
pub sync_token: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -106,12 +101,6 @@ impl<T1: XmlSerialize, T2: XmlSerialize> Default for MultistatusElement<T1, T2>
|
|||||||
Self {
|
Self {
|
||||||
responses: vec![],
|
responses: vec![],
|
||||||
member_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,
|
sync_token: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use darling::{util::Flag, FromDeriveInput, FromField, FromMeta, FromVariant};
|
use darling::{util::Flag, FromDeriveInput, FromField, FromMeta, FromVariant};
|
||||||
use syn::LitByteStr;
|
use syn::LitByteStr;
|
||||||
|
|
||||||
@@ -10,8 +12,7 @@ pub struct ContainerAttrs {
|
|||||||
pub struct TagAttrs {
|
pub struct TagAttrs {
|
||||||
pub rename: Option<LitByteStr>,
|
pub rename: Option<LitByteStr>,
|
||||||
pub ns_strict: Flag,
|
pub ns_strict: Flag,
|
||||||
// pub ns: Option<LitByteStr>,
|
pub ns: Option<syn::Path>,
|
||||||
pub ns: Option<syn::ExprPath>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, FromVariant)]
|
#[derive(Default, FromVariant)]
|
||||||
@@ -38,7 +39,9 @@ pub struct StructAttrs {
|
|||||||
pub container: ContainerAttrs,
|
pub container: ContainerAttrs,
|
||||||
|
|
||||||
pub root: Option<LitByteStr>,
|
pub root: Option<LitByteStr>,
|
||||||
pub ns: Option<syn::ExprPath>,
|
pub ns: Option<syn::Path>,
|
||||||
|
#[darling(default)]
|
||||||
|
pub ns_prefix: HashMap<syn::Path, LitByteStr>,
|
||||||
pub allow_invalid: Flag,
|
pub allow_invalid: Flag,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -57,10 +57,28 @@ impl NamedStruct {
|
|||||||
Some(ns) => quote! { Some(#ns) },
|
Some(ns) => quote! { Some(#ns) },
|
||||||
None => quote! { None },
|
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! {
|
quote! {
|
||||||
impl #impl_generics ::rustical_xml::XmlRootTag for #ident #type_generics #where_clause {
|
impl #impl_generics ::rustical_xml::XmlRootTag for #ident #type_generics #where_clause {
|
||||||
fn root_tag() -> &'static [u8] { #root }
|
fn root_tag() -> &'static [u8] { #root }
|
||||||
fn root_ns() -> Option<::quick_xml::name::Namespace<'static>> { #ns }
|
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;
|
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! {
|
quote! {
|
||||||
impl #impl_generics ::rustical_xml::XmlSerialize for #ident #type_generics #where_clause {
|
impl #impl_generics ::rustical_xml::XmlSerialize for #ident #type_generics #where_clause {
|
||||||
fn serialize<W: ::std::io::Write>(
|
fn serialize<W: ::std::io::Write>(
|
||||||
@@ -252,6 +287,7 @@ impl NamedStruct {
|
|||||||
bytes_start.push_attribute((b"xmlns".as_ref(), ns.as_ref()));
|
bytes_start.push_attribute((b"xmlns".as_ref(), ns.as_ref()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#(#prefix_attributes);*
|
||||||
if let Some(attrs) = self.attributes() {
|
if let Some(attrs) = self.attributes() {
|
||||||
bytes_start.extend_attributes(attrs);
|
bytes_start.extend_attributes(attrs);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -98,4 +98,5 @@ impl XmlDeserialize for Unparsed {
|
|||||||
pub trait XmlRootTag {
|
pub trait XmlRootTag {
|
||||||
fn root_tag() -> &'static [u8];
|
fn root_tag() -> &'static [u8];
|
||||||
fn root_ns() -> Option<Namespace<'static>>;
|
fn root_ns() -> Option<Namespace<'static>>;
|
||||||
|
fn root_ns_prefixes() -> HashMap<Namespace<'static>, &'static [u8]>;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ impl<T: XmlSerialize + XmlRootTag> XmlSerializeRoot for T {
|
|||||||
&self,
|
&self,
|
||||||
writer: &mut quick_xml::Writer<W>,
|
writer: &mut quick_xml::Writer<W>,
|
||||||
) -> std::io::Result<()> {
|
) -> std::io::Result<()> {
|
||||||
let namespaces = HashMap::new();
|
let namespaces = Self::root_ns_prefixes();
|
||||||
self.serialize(Self::root_ns(), Some(Self::root_tag()), &namespaces, writer)
|
self.serialize(Self::root_ns(), Some(Self::root_tag()), &namespaces, writer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user