From 9ea9beb1433cc2c32bb3496efcebd88895a5e0a3 Mon Sep 17 00:00:00 2001 From: Lennart <18233294+lennart-k@users.noreply.github.com> Date: Sun, 5 Jan 2025 17:06:15 +0100 Subject: [PATCH] xml use tuple structs --- .../methods/report/calendar_multiget.rs | 7 ++-- .../calendar/methods/report/calendar_query.rs | 7 ++-- .../methods/report/sync_collection.rs | 7 ++-- crates/caldav/src/calendar/resource.rs | 20 +++-------- crates/caldav/src/principal/mod.rs | 10 ++---- .../methods/report/addressbook_multiget.rs | 7 ++-- .../methods/report/sync_collection.rs | 7 ++-- crates/carddav/src/addressbook/resource.rs | 10 ++---- crates/carddav/src/principal/mod.rs | 10 ++---- crates/dav/src/resource/methods/propfind.rs | 6 ++-- crates/dav/src/resource/methods/proppatch.rs | 34 +++++++------------ crates/dav/src/resource/mod.rs | 4 +-- crates/dav/src/resources/root.rs | 5 +-- crates/dav/src/xml/multistatus.rs | 7 +--- crates/dav/src/xml/propfind.rs | 12 ++----- crates/dav/src/xml/resourcetype.rs | 20 ++++------- crates/dav/src/xml/tag_list.rs | 25 +++----------- 17 files changed, 57 insertions(+), 141 deletions(-) diff --git a/crates/caldav/src/calendar/methods/report/calendar_multiget.rs b/crates/caldav/src/calendar/methods/report/calendar_multiget.rs index 321c763..7f3dbb5 100644 --- a/crates/caldav/src/calendar/methods/report/calendar_multiget.rs +++ b/crates/caldav/src/calendar/methods/report/calendar_multiget.rs @@ -78,10 +78,9 @@ pub async fn handle_calendar_multiget( PropfindType::Propname => { vec!["propname".to_owned()] } - PropfindType::Prop(PropElement { prop: prop_tags }) => prop_tags - .into_iter() - .map(|propname| propname.name) - .collect(), + PropfindType::Prop(PropElement(prop_tags)) => { + prop_tags.into_iter().map(|propname| propname.0).collect() + } }; let props: Vec<&str> = props.iter().map(String::as_str).collect(); diff --git a/crates/caldav/src/calendar/methods/report/calendar_query.rs b/crates/caldav/src/calendar/methods/report/calendar_query.rs index 36aa56e..c833a7a 100644 --- a/crates/caldav/src/calendar/methods/report/calendar_query.rs +++ b/crates/caldav/src/calendar/methods/report/calendar_query.rs @@ -207,10 +207,9 @@ pub async fn handle_calendar_query( PropfindType::Propname => { vec!["propname".to_owned()] } - PropfindType::Prop(PropElement { prop: prop_tags }) => prop_tags - .into_iter() - .map(|propname| propname.name) - .collect(), + PropfindType::Prop(PropElement(prop_tags)) => { + prop_tags.into_iter().map(|propname| propname.0).collect() + } }; let props: Vec<&str> = props.iter().map(String::as_str).collect(); diff --git a/crates/caldav/src/calendar/methods/report/sync_collection.rs b/crates/caldav/src/calendar/methods/report/sync_collection.rs index 1afed83..016f1b2 100644 --- a/crates/caldav/src/calendar/methods/report/sync_collection.rs +++ b/crates/caldav/src/calendar/methods/report/sync_collection.rs @@ -73,10 +73,9 @@ pub async fn handle_sync_collection( PropfindType::Propname => { vec!["propname".to_owned()] } - PropfindType::Prop(PropElement { prop: prop_tags }) => prop_tags - .into_iter() - .map(|propname| propname.name) - .collect(), + PropfindType::Prop(PropElement(prop_tags)) => { + prop_tags.into_iter().map(|propname| propname.0).collect() + } }; let props: Vec<&str> = props.iter().map(String::as_str).collect(); diff --git a/crates/caldav/src/calendar/resource.rs b/crates/caldav/src/calendar/resource.rs index cc0f014..112d7ee 100644 --- a/crates/caldav/src/calendar/resource.rs +++ b/crates/caldav/src/calendar/resource.rs @@ -100,25 +100,13 @@ impl Resource for CalendarResource { fn get_resourcetype(&self) -> Resourcetype { if self.0.subscription_url.is_none() { Resourcetype(&[ - ResourcetypeInner { - ns: rustical_dav::namespace::NS_DAV, - name: "collection", - }, - ResourcetypeInner { - ns: rustical_dav::namespace::NS_CALDAV, - name: "calendar", - }, + ResourcetypeInner(rustical_dav::namespace::NS_DAV, "collection"), + ResourcetypeInner(rustical_dav::namespace::NS_CALDAV, "calendar"), ]) } else { Resourcetype(&[ - ResourcetypeInner { - ns: rustical_dav::namespace::NS_DAV, - name: "collection", - }, - ResourcetypeInner { - ns: rustical_dav::namespace::NS_CALENDARSERVER, - name: "subscribed", - }, + ResourcetypeInner(rustical_dav::namespace::NS_DAV, "collection"), + ResourcetypeInner(rustical_dav::namespace::NS_CALENDARSERVER, "subscribed"), ]) } } diff --git a/crates/caldav/src/principal/mod.rs b/crates/caldav/src/principal/mod.rs index 62384d0..4c23fd8 100644 --- a/crates/caldav/src/principal/mod.rs +++ b/crates/caldav/src/principal/mod.rs @@ -59,14 +59,8 @@ impl Resource for PrincipalResource { fn get_resourcetype(&self) -> Resourcetype { Resourcetype(&[ - ResourcetypeInner { - ns: rustical_dav::namespace::NS_DAV, - name: "collection", - }, - ResourcetypeInner { - ns: rustical_dav::namespace::NS_DAV, - name: "principal", - }, + ResourcetypeInner(rustical_dav::namespace::NS_DAV, "collection"), + ResourcetypeInner(rustical_dav::namespace::NS_DAV, "principal"), ]) } diff --git a/crates/carddav/src/addressbook/methods/report/addressbook_multiget.rs b/crates/carddav/src/addressbook/methods/report/addressbook_multiget.rs index 8a956e4..44233c2 100644 --- a/crates/carddav/src/addressbook/methods/report/addressbook_multiget.rs +++ b/crates/carddav/src/addressbook/methods/report/addressbook_multiget.rs @@ -84,10 +84,9 @@ pub async fn handle_addressbook_multiget( PropfindType::Propname => { vec!["propname".to_owned()] } - PropfindType::Prop(PropElement { prop: prop_tags }) => prop_tags - .into_iter() - .map(|propname| propname.name) - .collect(), + PropfindType::Prop(PropElement(prop_tags)) => { + prop_tags.into_iter().map(|propname| propname.0).collect() + } }; let props: Vec<&str> = props.iter().map(String::as_str).collect(); diff --git a/crates/carddav/src/addressbook/methods/report/sync_collection.rs b/crates/carddav/src/addressbook/methods/report/sync_collection.rs index 955f41f..f22bea8 100644 --- a/crates/carddav/src/addressbook/methods/report/sync_collection.rs +++ b/crates/carddav/src/addressbook/methods/report/sync_collection.rs @@ -70,10 +70,9 @@ pub async fn handle_sync_collection( PropfindType::Propname => { vec!["propname".to_owned()] } - PropfindType::Prop(PropElement { prop: prop_tags }) => prop_tags - .into_iter() - .map(|propname| propname.name) - .collect(), + PropfindType::Prop(PropElement(prop_tags)) => { + prop_tags.into_iter().map(|propname| propname.0).collect() + } }; let props: Vec<&str> = props.iter().map(String::as_str).collect(); diff --git a/crates/carddav/src/addressbook/resource.rs b/crates/carddav/src/addressbook/resource.rs index b524103..cf79803 100644 --- a/crates/carddav/src/addressbook/resource.rs +++ b/crates/carddav/src/addressbook/resource.rs @@ -72,14 +72,8 @@ impl Resource for AddressbookResource { fn get_resourcetype(&self) -> Resourcetype { Resourcetype(&[ - ResourcetypeInner { - ns: rustical_dav::namespace::NS_DAV, - name: "collection", - }, - ResourcetypeInner { - ns: rustical_dav::namespace::NS_CARDDAV, - name: "addressbook", - }, + ResourcetypeInner(rustical_dav::namespace::NS_DAV, "collection"), + ResourcetypeInner(rustical_dav::namespace::NS_CARDDAV, "addressbook"), ]) } diff --git a/crates/carddav/src/principal/mod.rs b/crates/carddav/src/principal/mod.rs index 5989188..0689fc0 100644 --- a/crates/carddav/src/principal/mod.rs +++ b/crates/carddav/src/principal/mod.rs @@ -60,14 +60,8 @@ impl Resource for PrincipalResource { fn get_resourcetype(&self) -> Resourcetype { Resourcetype(&[ - ResourcetypeInner { - ns: rustical_dav::namespace::NS_DAV, - name: "collection", - }, - ResourcetypeInner { - ns: rustical_dav::namespace::NS_DAV, - name: "principal", - }, + ResourcetypeInner(rustical_dav::namespace::NS_DAV, "collection"), + ResourcetypeInner(rustical_dav::namespace::NS_DAV, "principal"), ]) } diff --git a/crates/dav/src/resource/methods/propfind.rs b/crates/dav/src/resource/methods/propfind.rs index 95be3ef..959dd6f 100644 --- a/crates/dav/src/resource/methods/propfind.rs +++ b/crates/dav/src/resource/methods/propfind.rs @@ -13,7 +13,7 @@ use actix_web::web::Data; use actix_web::web::Path; use actix_web::HttpRequest; use rustical_store::auth::User; -use rustical_xml::de::XmlDocument; +use rustical_xml::XmlDocument; use tracing::instrument; use tracing_actix_web::RootSpan; @@ -53,9 +53,9 @@ pub(crate) async fn route_propfind( let props = match &propfind.prop { PropfindType::Allprop => vec!["allprop"], PropfindType::Propname => vec!["propname"], - PropfindType::Prop(PropElement { prop: prop_tags }) => prop_tags + PropfindType::Prop(PropElement(prop_tags)) => prop_tags .iter() - .map(|propname| propname.name.as_str()) + .map(|propname| propname.0.as_str()) .collect(), }; diff --git a/crates/dav/src/resource/methods/proppatch.rs b/crates/dav/src/resource/methods/proppatch.rs index aef147b..453046d 100644 --- a/crates/dav/src/resource/methods/proppatch.rs +++ b/crates/dav/src/resource/methods/proppatch.rs @@ -26,10 +26,9 @@ enum SetPropertyPropWrapper { // We are #[derive(XmlDeserialize, Clone, Debug)] -struct SetPropertyPropWrapperWrapper { - #[xml(ty = "untagged")] - property: SetPropertyPropWrapper, -} +struct SetPropertyPropWrapperWrapper( + #[xml(ty = "untagged")] SetPropertyPropWrapper, +); // We are #[derive(XmlDeserialize, Clone, Debug)] @@ -39,16 +38,10 @@ struct SetPropertyElement { } #[derive(XmlDeserialize, Clone, Debug)] -struct TagName { - #[xml(ty = "tag_name")] - name: String, -} +struct TagName(#[xml(ty = "tag_name")] String); #[derive(XmlDeserialize, Clone, Debug)] -struct PropertyElement { - #[xml(ty = "untagged")] - property: TagName, -} +struct PropertyElement(#[xml(ty = "untagged")] TagName); #[derive(XmlDeserialize, Clone, Debug)] struct RemovePropertyElement { @@ -67,10 +60,7 @@ enum Operation { #[derive(XmlDeserialize, XmlRootTag, Clone, Debug)] #[xml(root = b"propertyupdate")] #[xml(ns = "crate::namespace::NS_DAV")] -struct PropertyupdateElement { - #[xml(ty = "untagged", flatten)] - operations: Vec>, -} +struct PropertyupdateElement(#[xml(ty = "untagged", flatten)] Vec>); #[instrument(parent = root_span.id(), skip(path, req, root_span, resource_service))] pub(crate) async fn route_proppatch( @@ -84,9 +74,9 @@ pub(crate) async fn route_proppatch( let href = req.path().to_owned(); // Extract operations - let PropertyupdateElement::::Prop>> { + let PropertyupdateElement::::Prop>>( operations, - } = XmlDocument::parse_str(&body).map_err(Error::XmlDeserializationError)?; + ) = XmlDocument::parse_str(&body).map_err(Error::XmlDeserializationError)?; let mut resource = resource_service.get_resource(&path).await?; let privileges = resource.get_user_privileges(&user)?; @@ -100,8 +90,10 @@ pub(crate) async fn route_proppatch( for operation in operations.into_iter() { match operation { - Operation::Set(SetPropertyElement { prop }) => { - match prop.property { + Operation::Set(SetPropertyElement { + prop: SetPropertyPropWrapperWrapper(property), + }) => { + match property { SetPropertyPropWrapper::Valid(prop) => { let propname: ::PropName = prop.clone().into(); let propname: &str = propname.into(); @@ -125,7 +117,7 @@ pub(crate) async fn route_proppatch( } } Operation::Remove(remove_el) => { - let propname = remove_el.prop.property.name; + let propname = remove_el.prop.0 .0; match <::PropName as FromStr>::from_str(&propname) { Ok(prop) => match resource.remove_prop(&prop) { Ok(()) => props_ok.push(propname), diff --git a/crates/dav/src/resource/mod.rs b/crates/dav/src/resource/mod.rs index 75e7886..a26ff69 100644 --- a/crates/dav/src/resource/mod.rs +++ b/crates/dav/src/resource/mod.rs @@ -207,9 +207,7 @@ pub trait Resource: Clone + 'static { let mut propstats = vec![PropstatWrapper::Normal(PropstatElement { status: StatusCode::OK, - prop: PropTagWrapper { - prop: prop_responses, - }, + prop: PropTagWrapper(prop_responses), })]; if !invalid_props.is_empty() { propstats.push(PropstatWrapper::TagList(PropstatElement { diff --git a/crates/dav/src/resources/root.rs b/crates/dav/src/resources/root.rs index a8bd4dd..5e083de 100644 --- a/crates/dav/src/resources/root.rs +++ b/crates/dav/src/resources/root.rs @@ -39,10 +39,7 @@ impl Resource for RootResource { type PrincipalResource = PR; fn get_resourcetype(&self) -> Resourcetype { - Resourcetype(&[ResourcetypeInner { - ns: crate::namespace::NS_DAV, - name: "collection", - }]) + Resourcetype(&[ResourcetypeInner(crate::namespace::NS_DAV, "collection")]) } fn get_prop( diff --git a/crates/dav/src/xml/multistatus.rs b/crates/dav/src/xml/multistatus.rs index dfbf673..fb9dd74 100644 --- a/crates/dav/src/xml/multistatus.rs +++ b/crates/dav/src/xml/multistatus.rs @@ -9,13 +9,8 @@ use actix_web::{ use quick_xml::name::Namespace; use rustical_xml::{XmlRootTag, XmlSerialize, XmlSerializeRoot}; -// Intermediate struct because of a serde limitation, see following article: -// https://stackoverflow.com/questions/78444158/unsupportedcannot-serialize-enum-newtype-variant-exampledata #[derive(XmlSerialize)] -pub struct PropTagWrapper { - #[xml(flatten, ty = "untagged")] - pub prop: Vec, -} +pub struct PropTagWrapper(#[xml(flatten, ty = "untagged")] pub Vec); // RFC 2518 // diff --git a/crates/dav/src/xml/propfind.rs b/crates/dav/src/xml/propfind.rs index c40fa29..d4f3d9c 100644 --- a/crates/dav/src/xml/propfind.rs +++ b/crates/dav/src/xml/propfind.rs @@ -4,21 +4,15 @@ use rustical_xml::XmlRootTag; #[derive(Debug, Clone, XmlDeserialize, XmlRootTag, PartialEq)] #[xml(root = b"propfind", ns = "crate::namespace::NS_DAV")] pub struct PropfindElement { - #[xml(ty = "untagged")] + #[xml(ns = "crate::namespace::NS_DAV")] pub prop: PropfindType, } #[derive(Debug, Clone, XmlDeserialize, PartialEq)] -pub struct PropElement { - #[xml(ty = "untagged", flatten)] - pub prop: Vec, -} +pub struct PropElement(#[xml(ty = "untagged", flatten)] pub Vec); #[derive(Debug, Clone, XmlDeserialize, PartialEq)] -pub struct Propname { - #[xml(ty = "tag_name")] - pub name: String, -} +pub struct Propname(#[xml(ty = "tag_name")] pub String); #[derive(Debug, Clone, XmlDeserialize, PartialEq)] pub enum PropfindType { diff --git a/crates/dav/src/xml/resourcetype.rs b/crates/dav/src/xml/resourcetype.rs index 2070787..1f54e54 100644 --- a/crates/dav/src/xml/resourcetype.rs +++ b/crates/dav/src/xml/resourcetype.rs @@ -4,12 +4,10 @@ use rustical_xml::XmlSerialize; pub struct Resourcetype(#[xml(flatten, ty = "untagged")] pub &'static [ResourcetypeInner]); #[derive(Debug, Clone, PartialEq, XmlSerialize)] -pub struct ResourcetypeInner { - #[xml(ty = "namespace")] - pub ns: quick_xml::name::Namespace<'static>, - #[xml(ty = "tag_name")] - pub name: &'static str, -} +pub struct ResourcetypeInner( + #[xml(ty = "namespace")] pub quick_xml::name::Namespace<'static>, + #[xml(ty = "tag_name")] pub &'static str, +); #[cfg(test)] mod tests { @@ -29,14 +27,8 @@ mod tests { let mut writer = quick_xml::Writer::new(&mut buf); Document { resourcetype: Resourcetype(&[ - ResourcetypeInner { - ns: crate::namespace::NS_DAV, - name: "displayname", - }, - ResourcetypeInner { - ns: crate::namespace::NS_CALENDARSERVER, - name: "calendar-color", - }, + ResourcetypeInner(crate::namespace::NS_DAV, "displayname"), + ResourcetypeInner(crate::namespace::NS_CALENDARSERVER, "calendar-color"), ]), } .serialize_root(&mut writer) diff --git a/crates/dav/src/xml/tag_list.rs b/crates/dav/src/xml/tag_list.rs index 0c82fc9..59962bc 100644 --- a/crates/dav/src/xml/tag_list.rs +++ b/crates/dav/src/xml/tag_list.rs @@ -15,20 +15,12 @@ impl XmlSerialize for TagList { writer: &mut quick_xml::Writer, ) -> std::io::Result<()> { #[derive(Debug, XmlSerialize, PartialEq)] - struct Inner { - #[xml(ty = "untagged", flatten)] - tags: Vec, - } + struct Inner(#[xml(ty = "untagged", flatten)] Vec); #[derive(Debug, XmlSerialize, PartialEq)] - struct Tag { - #[xml(ty = "tag_name")] - name: String, - } - Inner { - tags: self.0.iter().map(|t| Tag { name: t.to_owned() }).collect(), - } - .serialize(ns, tag, namespaces, writer) + struct Tag(#[xml(ty = "tag_name")] String); + Inner(self.0.iter().map(|t| Tag(t.to_owned())).collect()) + .serialize(ns, tag, namespaces, writer) } #[allow(refining_impl_trait)] @@ -36,12 +28,3 @@ impl XmlSerialize for TagList { None } } - -impl TagList { - pub fn inner(&self) -> &Vec { - &self.0 - } - pub fn into_inner(self) -> Vec { - self.0 - } -}