diff --git a/Cargo.lock b/Cargo.lock index 6018f0c..8ac9a71 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2703,6 +2703,8 @@ dependencies = [ "rustical_xml", "serde", "sha2", + "strum", + "strum_macros", "thiserror 2.0.12", "tokio", "tower", @@ -2733,6 +2735,8 @@ dependencies = [ "rustical_store", "rustical_xml", "serde", + "strum", + "strum_macros", "thiserror 2.0.12", "tokio", "tower", @@ -2758,6 +2762,7 @@ dependencies = [ "quick-xml", "rustical_xml", "serde", + "strum", "thiserror 2.0.12", "tokio", "tower", @@ -3435,6 +3440,25 @@ version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" +[[package]] +name = "strum" +version = "0.27.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f64def088c51c9510a8579e3c5d67c65349dcf755e5479ad3d010aa6454e2c32" + +[[package]] +name = "strum_macros" +version = "0.27.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c77a8c5abcaf0f9ce05d62342b7d298c346515365c36b673df4ebe3ced01fde8" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "rustversion", + "syn", +] + [[package]] name = "subtle" version = "2.6.1" diff --git a/crates/caldav/Cargo.toml b/crates/caldav/Cargo.toml index cbd0b9b..117cfed 100644 --- a/crates/caldav/Cargo.toml +++ b/crates/caldav/Cargo.toml @@ -35,3 +35,5 @@ rustical_ical.workspace = true http.workspace = true headers.workspace = true tower-http.workspace = true +strum.workspace = true +strum_macros.workspace = true diff --git a/crates/caldav/src/calendar/prop.rs b/crates/caldav/src/calendar/prop.rs index 306786e..e16e658 100644 --- a/crates/caldav/src/calendar/prop.rs +++ b/crates/caldav/src/calendar/prop.rs @@ -1,6 +1,7 @@ use derive_more::derive::{From, Into}; use rustical_ical::CalendarObjectType; use rustical_xml::{XmlDeserialize, XmlSerialize}; +use strum_macros::VariantArray; #[derive(Debug, Clone, XmlSerialize, XmlDeserialize, PartialEq, From, Into)] pub struct SupportedCalendarComponent { @@ -58,39 +59,12 @@ pub struct SupportedCalendarData { calendar_data: CalendarData, } -#[derive(Debug, Clone, XmlSerialize, PartialEq)] +#[derive(Debug, Clone, XmlSerialize, PartialEq, VariantArray)] pub enum ReportMethod { + #[xml(ns = "rustical_dav::namespace::NS_CALDAV")] CalendarQuery, + #[xml(ns = "rustical_dav::namespace::NS_CALDAV")] CalendarMultiget, + #[xml(ns = "rustical_dav::namespace::NS_DAV")] SyncCollection, } - -#[derive(Debug, Clone, XmlSerialize, PartialEq)] -pub struct ReportWrapper { - report: ReportMethod, -} - -// RFC 3253 section-3.1.5 -#[derive(Debug, Clone, XmlSerialize, PartialEq)] -pub struct SupportedReportSet { - #[xml(flatten)] - supported_report: Vec, -} - -impl Default for SupportedReportSet { - fn default() -> Self { - Self { - supported_report: vec![ - ReportWrapper { - report: ReportMethod::CalendarQuery, - }, - ReportWrapper { - report: ReportMethod::CalendarMultiget, - }, - ReportWrapper { - report: ReportMethod::SyncCollection, - }, - ], - } - } -} diff --git a/crates/caldav/src/calendar/resource.rs b/crates/caldav/src/calendar/resource.rs index f42c7ca..7ba2e4c 100644 --- a/crates/caldav/src/calendar/resource.rs +++ b/crates/caldav/src/calendar/resource.rs @@ -1,5 +1,6 @@ -use super::prop::{SupportedCalendarComponentSet, SupportedCalendarData, SupportedReportSet}; +use super::prop::{SupportedCalendarComponentSet, SupportedCalendarData}; use crate::Error; +use crate::calendar::prop::ReportMethod; use chrono::{DateTime, Utc}; use derive_more::derive::{From, Into}; use rustical_dav::extensions::{ @@ -7,7 +8,7 @@ use rustical_dav::extensions::{ }; use rustical_dav::privileges::UserPrivilegeSet; use rustical_dav::resource::{PrincipalUri, Resource, ResourceName}; -use rustical_dav::xml::{HrefElement, Resourcetype, ResourcetypeInner}; +use rustical_dav::xml::{HrefElement, Resourcetype, ResourcetypeInner, SupportedReportSet}; use rustical_dav_push::DavPushExtension; use rustical_ical::CalDateTime; use rustical_store::Calendar; @@ -40,8 +41,8 @@ pub enum CalendarProp { #[xml(ns = "rustical_dav::namespace::NS_DAV")] MaxResourceSize(i64), #[xml(skip_deserializing)] - #[xml(ns = "rustical_dav::namespace::NS_CALDAV")] - SupportedReportSet(SupportedReportSet), + #[xml(ns = "rustical_dav::namespace::NS_DAV")] + SupportedReportSet(SupportedReportSet), #[xml(ns = "rustical_dav::namespace::NS_CALENDARSERVER")] Source(Option), #[xml(skip_deserializing)] @@ -150,7 +151,7 @@ impl Resource for CalendarResource { } CalendarPropName::MaxResourceSize => CalendarProp::MaxResourceSize(10000000), CalendarPropName::SupportedReportSet => { - CalendarProp::SupportedReportSet(SupportedReportSet::default()) + CalendarProp::SupportedReportSet(SupportedReportSet::all()) } CalendarPropName::Source => CalendarProp::Source( self.cal.subscription_url.to_owned().map(HrefElement::from), diff --git a/crates/carddav/Cargo.toml b/crates/carddav/Cargo.toml index 45b7711..aaf28f3 100644 --- a/crates/carddav/Cargo.toml +++ b/crates/carddav/Cargo.toml @@ -32,3 +32,5 @@ http.workspace = true tower-http.workspace = true percent-encoding.workspace = true ical.workspace = true +strum.workspace = true +strum_macros.workspace = true diff --git a/crates/carddav/src/addressbook/prop.rs b/crates/carddav/src/addressbook/prop.rs index 08ca4ec..21f3013 100644 --- a/crates/carddav/src/addressbook/prop.rs +++ b/crates/carddav/src/addressbook/prop.rs @@ -1,6 +1,10 @@ -use rustical_dav::extensions::{CommonPropertiesProp, SyncTokenExtensionProp}; +use rustical_dav::{ + extensions::{CommonPropertiesProp, SyncTokenExtensionProp}, + xml::SupportedReportSet, +}; use rustical_dav_push::DavPushExtensionProp; use rustical_xml::{EnumVariants, PropName, XmlDeserialize, XmlSerialize}; +use strum_macros::VariantArray; #[derive(XmlDeserialize, XmlSerialize, PartialEq, Clone, EnumVariants, PropName)] #[xml(unit_variants_ident = "AddressbookPropName")] @@ -10,8 +14,8 @@ pub enum AddressbookProp { AddressbookDescription(Option), #[xml(ns = "rustical_dav::namespace::NS_CARDDAV", skip_deserializing)] SupportedAddressData(SupportedAddressData), - #[xml(ns = "rustical_dav::namespace::NS_CARDDAV", skip_deserializing)] - SupportedReportSet(SupportedReportSet), + #[xml(ns = "rustical_dav::namespace::NS_DAV", skip_deserializing)] + SupportedReportSet(SupportedReportSet), #[xml(ns = "rustical_dav::namespace::NS_DAV")] MaxResourceSize(i64), } @@ -56,37 +60,10 @@ impl Default for SupportedAddressData { } } -#[derive(Debug, Clone, XmlSerialize, PartialEq)] +#[derive(Debug, Clone, XmlSerialize, PartialEq, VariantArray)] pub enum ReportMethod { #[xml(ns = "rustical_dav::namespace::NS_CARDDAV")] AddressbookMultiget, + #[xml(ns = "rustical_dav::namespace::NS_DAV")] SyncCollection, } - -#[derive(Debug, Clone, XmlSerialize, PartialEq)] -pub struct SupportedReportWrapper { - #[xml(ns = "rustical_dav::namespace::NS_CARDDAV")] - report: ReportMethod, -} - -// RFC 3253 section-3.1.5 -#[derive(Debug, Clone, XmlSerialize, PartialEq)] -pub struct SupportedReportSet { - #[xml(ns = "rustical_dav::namespace::NS_CARDDAV", flatten)] - supported_report: &'static [SupportedReportWrapper], -} - -impl Default for SupportedReportSet { - fn default() -> Self { - Self { - supported_report: &[ - SupportedReportWrapper { - report: ReportMethod::AddressbookMultiget, - }, - SupportedReportWrapper { - report: ReportMethod::SyncCollection, - }, - ], - } - } -} diff --git a/crates/carddav/src/addressbook/resource.rs b/crates/carddav/src/addressbook/resource.rs index 29a17f5..c6c13d7 100644 --- a/crates/carddav/src/addressbook/resource.rs +++ b/crates/carddav/src/addressbook/resource.rs @@ -1,4 +1,4 @@ -use super::prop::{SupportedAddressData, SupportedReportSet}; +use super::prop::SupportedAddressData; use crate::Error; use crate::addressbook::prop::{ AddressbookProp, AddressbookPropName, AddressbookPropWrapper, AddressbookPropWrapperName, @@ -7,7 +7,7 @@ use derive_more::derive::{From, Into}; use rustical_dav::extensions::{CommonPropertiesExtension, SyncTokenExtension}; use rustical_dav::privileges::UserPrivilegeSet; use rustical_dav::resource::{PrincipalUri, Resource, ResourceName}; -use rustical_dav::xml::{Resourcetype, ResourcetypeInner}; +use rustical_dav::xml::{Resourcetype, ResourcetypeInner, SupportedReportSet}; use rustical_dav_push::DavPushExtension; use rustical_store::Addressbook; use rustical_store::auth::User; @@ -60,7 +60,7 @@ impl Resource for AddressbookResource { AddressbookProp::MaxResourceSize(10000000) } AddressbookPropName::SupportedReportSet => { - AddressbookProp::SupportedReportSet(SupportedReportSet::default()) + AddressbookProp::SupportedReportSet(SupportedReportSet::all()) } AddressbookPropName::AddressbookDescription => { AddressbookProp::AddressbookDescription(self.0.description.to_owned()) diff --git a/crates/dav/Cargo.toml b/crates/dav/Cargo.toml index b725ada..f59ef27 100644 --- a/crates/dav/Cargo.toml +++ b/crates/dav/Cargo.toml @@ -25,3 +25,4 @@ tracing.workspace = true tokio.workspace = true http.workspace = true headers.workspace = true +strum.workspace = true diff --git a/crates/dav/src/xml/mod.rs b/crates/dav/src/xml/mod.rs index 34d1012..2c0f454 100644 --- a/crates/dav/src/xml/mod.rs +++ b/crates/dav/src/xml/mod.rs @@ -11,3 +11,5 @@ pub use tag_list::TagList; mod error; pub mod sync_collection; pub use error::ErrorElement; +mod report_set; +pub use report_set::SupportedReportSet; diff --git a/crates/dav/src/xml/report_set.rs b/crates/dav/src/xml/report_set.rs new file mode 100644 index 0000000..4134c27 --- /dev/null +++ b/crates/dav/src/xml/report_set.rs @@ -0,0 +1,34 @@ +use rustical_xml::XmlSerialize; +use strum::VariantArray; + +// RFC 3253 section-3.1.5 +#[derive(Debug, Clone, XmlSerialize, PartialEq)] +pub struct SupportedReportSet { + #[xml(flatten)] + #[xml(ns = "crate::namespace::NS_DAV")] + supported_report: Vec>, +} + +impl SupportedReportSet { + pub fn new(methods: Vec) -> Self { + Self { + supported_report: methods + .into_iter() + .map(|method| ReportWrapper { report: method }) + .collect(), + } + } + + pub fn all() -> Self + where + T: VariantArray, + { + Self::new(T::VARIANTS.to_vec()) + } +} + +#[derive(Debug, Clone, XmlSerialize, PartialEq)] +pub struct ReportWrapper { + #[xml(ns = "crate::namespace::NS_DAV")] + report: T, +}