Fix and simplify support-report-set

This commit is contained in:
Lennart
2025-06-12 17:39:42 +02:00
parent 89adbcf13f
commit 41d5c72e4e
10 changed files with 88 additions and 71 deletions

24
Cargo.lock generated
View File

@@ -2703,6 +2703,8 @@ dependencies = [
"rustical_xml", "rustical_xml",
"serde", "serde",
"sha2", "sha2",
"strum",
"strum_macros",
"thiserror 2.0.12", "thiserror 2.0.12",
"tokio", "tokio",
"tower", "tower",
@@ -2733,6 +2735,8 @@ dependencies = [
"rustical_store", "rustical_store",
"rustical_xml", "rustical_xml",
"serde", "serde",
"strum",
"strum_macros",
"thiserror 2.0.12", "thiserror 2.0.12",
"tokio", "tokio",
"tower", "tower",
@@ -2758,6 +2762,7 @@ dependencies = [
"quick-xml", "quick-xml",
"rustical_xml", "rustical_xml",
"serde", "serde",
"strum",
"thiserror 2.0.12", "thiserror 2.0.12",
"tokio", "tokio",
"tower", "tower",
@@ -3435,6 +3440,25 @@ version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" 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]] [[package]]
name = "subtle" name = "subtle"
version = "2.6.1" version = "2.6.1"

View File

@@ -35,3 +35,5 @@ rustical_ical.workspace = true
http.workspace = true http.workspace = true
headers.workspace = true headers.workspace = true
tower-http.workspace = true tower-http.workspace = true
strum.workspace = true
strum_macros.workspace = true

View File

@@ -1,6 +1,7 @@
use derive_more::derive::{From, Into}; use derive_more::derive::{From, Into};
use rustical_ical::CalendarObjectType; use rustical_ical::CalendarObjectType;
use rustical_xml::{XmlDeserialize, XmlSerialize}; use rustical_xml::{XmlDeserialize, XmlSerialize};
use strum_macros::VariantArray;
#[derive(Debug, Clone, XmlSerialize, XmlDeserialize, PartialEq, From, Into)] #[derive(Debug, Clone, XmlSerialize, XmlDeserialize, PartialEq, From, Into)]
pub struct SupportedCalendarComponent { pub struct SupportedCalendarComponent {
@@ -58,39 +59,12 @@ pub struct SupportedCalendarData {
calendar_data: CalendarData, calendar_data: CalendarData,
} }
#[derive(Debug, Clone, XmlSerialize, PartialEq)] #[derive(Debug, Clone, XmlSerialize, PartialEq, VariantArray)]
pub enum ReportMethod { pub enum ReportMethod {
#[xml(ns = "rustical_dav::namespace::NS_CALDAV")]
CalendarQuery, CalendarQuery,
#[xml(ns = "rustical_dav::namespace::NS_CALDAV")]
CalendarMultiget, CalendarMultiget,
#[xml(ns = "rustical_dav::namespace::NS_DAV")]
SyncCollection, 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<ReportWrapper>,
}
impl Default for SupportedReportSet {
fn default() -> Self {
Self {
supported_report: vec![
ReportWrapper {
report: ReportMethod::CalendarQuery,
},
ReportWrapper {
report: ReportMethod::CalendarMultiget,
},
ReportWrapper {
report: ReportMethod::SyncCollection,
},
],
}
}
}

View File

@@ -1,5 +1,6 @@
use super::prop::{SupportedCalendarComponentSet, SupportedCalendarData, SupportedReportSet}; use super::prop::{SupportedCalendarComponentSet, SupportedCalendarData};
use crate::Error; use crate::Error;
use crate::calendar::prop::ReportMethod;
use chrono::{DateTime, Utc}; use chrono::{DateTime, Utc};
use derive_more::derive::{From, Into}; use derive_more::derive::{From, Into};
use rustical_dav::extensions::{ use rustical_dav::extensions::{
@@ -7,7 +8,7 @@ use rustical_dav::extensions::{
}; };
use rustical_dav::privileges::UserPrivilegeSet; use rustical_dav::privileges::UserPrivilegeSet;
use rustical_dav::resource::{PrincipalUri, Resource, ResourceName}; 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_dav_push::DavPushExtension;
use rustical_ical::CalDateTime; use rustical_ical::CalDateTime;
use rustical_store::Calendar; use rustical_store::Calendar;
@@ -40,8 +41,8 @@ pub enum CalendarProp {
#[xml(ns = "rustical_dav::namespace::NS_DAV")] #[xml(ns = "rustical_dav::namespace::NS_DAV")]
MaxResourceSize(i64), MaxResourceSize(i64),
#[xml(skip_deserializing)] #[xml(skip_deserializing)]
#[xml(ns = "rustical_dav::namespace::NS_CALDAV")] #[xml(ns = "rustical_dav::namespace::NS_DAV")]
SupportedReportSet(SupportedReportSet), SupportedReportSet(SupportedReportSet<ReportMethod>),
#[xml(ns = "rustical_dav::namespace::NS_CALENDARSERVER")] #[xml(ns = "rustical_dav::namespace::NS_CALENDARSERVER")]
Source(Option<HrefElement>), Source(Option<HrefElement>),
#[xml(skip_deserializing)] #[xml(skip_deserializing)]
@@ -150,7 +151,7 @@ impl Resource for CalendarResource {
} }
CalendarPropName::MaxResourceSize => CalendarProp::MaxResourceSize(10000000), CalendarPropName::MaxResourceSize => CalendarProp::MaxResourceSize(10000000),
CalendarPropName::SupportedReportSet => { CalendarPropName::SupportedReportSet => {
CalendarProp::SupportedReportSet(SupportedReportSet::default()) CalendarProp::SupportedReportSet(SupportedReportSet::all())
} }
CalendarPropName::Source => CalendarProp::Source( CalendarPropName::Source => CalendarProp::Source(
self.cal.subscription_url.to_owned().map(HrefElement::from), self.cal.subscription_url.to_owned().map(HrefElement::from),

View File

@@ -32,3 +32,5 @@ http.workspace = true
tower-http.workspace = true tower-http.workspace = true
percent-encoding.workspace = true percent-encoding.workspace = true
ical.workspace = true ical.workspace = true
strum.workspace = true
strum_macros.workspace = true

View File

@@ -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_dav_push::DavPushExtensionProp;
use rustical_xml::{EnumVariants, PropName, XmlDeserialize, XmlSerialize}; use rustical_xml::{EnumVariants, PropName, XmlDeserialize, XmlSerialize};
use strum_macros::VariantArray;
#[derive(XmlDeserialize, XmlSerialize, PartialEq, Clone, EnumVariants, PropName)] #[derive(XmlDeserialize, XmlSerialize, PartialEq, Clone, EnumVariants, PropName)]
#[xml(unit_variants_ident = "AddressbookPropName")] #[xml(unit_variants_ident = "AddressbookPropName")]
@@ -10,8 +14,8 @@ pub enum AddressbookProp {
AddressbookDescription(Option<String>), AddressbookDescription(Option<String>),
#[xml(ns = "rustical_dav::namespace::NS_CARDDAV", skip_deserializing)] #[xml(ns = "rustical_dav::namespace::NS_CARDDAV", skip_deserializing)]
SupportedAddressData(SupportedAddressData), SupportedAddressData(SupportedAddressData),
#[xml(ns = "rustical_dav::namespace::NS_CARDDAV", skip_deserializing)] #[xml(ns = "rustical_dav::namespace::NS_DAV", skip_deserializing)]
SupportedReportSet(SupportedReportSet), SupportedReportSet(SupportedReportSet<ReportMethod>),
#[xml(ns = "rustical_dav::namespace::NS_DAV")] #[xml(ns = "rustical_dav::namespace::NS_DAV")]
MaxResourceSize(i64), MaxResourceSize(i64),
} }
@@ -56,37 +60,10 @@ impl Default for SupportedAddressData {
} }
} }
#[derive(Debug, Clone, XmlSerialize, PartialEq)] #[derive(Debug, Clone, XmlSerialize, PartialEq, VariantArray)]
pub enum ReportMethod { pub enum ReportMethod {
#[xml(ns = "rustical_dav::namespace::NS_CARDDAV")] #[xml(ns = "rustical_dav::namespace::NS_CARDDAV")]
AddressbookMultiget, AddressbookMultiget,
#[xml(ns = "rustical_dav::namespace::NS_DAV")]
SyncCollection, 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,
},
],
}
}
}

View File

@@ -1,4 +1,4 @@
use super::prop::{SupportedAddressData, SupportedReportSet}; use super::prop::SupportedAddressData;
use crate::Error; use crate::Error;
use crate::addressbook::prop::{ use crate::addressbook::prop::{
AddressbookProp, AddressbookPropName, AddressbookPropWrapper, AddressbookPropWrapperName, AddressbookProp, AddressbookPropName, AddressbookPropWrapper, AddressbookPropWrapperName,
@@ -7,7 +7,7 @@ use derive_more::derive::{From, Into};
use rustical_dav::extensions::{CommonPropertiesExtension, SyncTokenExtension}; use rustical_dav::extensions::{CommonPropertiesExtension, SyncTokenExtension};
use rustical_dav::privileges::UserPrivilegeSet; use rustical_dav::privileges::UserPrivilegeSet;
use rustical_dav::resource::{PrincipalUri, Resource, ResourceName}; 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_dav_push::DavPushExtension;
use rustical_store::Addressbook; use rustical_store::Addressbook;
use rustical_store::auth::User; use rustical_store::auth::User;
@@ -60,7 +60,7 @@ impl Resource for AddressbookResource {
AddressbookProp::MaxResourceSize(10000000) AddressbookProp::MaxResourceSize(10000000)
} }
AddressbookPropName::SupportedReportSet => { AddressbookPropName::SupportedReportSet => {
AddressbookProp::SupportedReportSet(SupportedReportSet::default()) AddressbookProp::SupportedReportSet(SupportedReportSet::all())
} }
AddressbookPropName::AddressbookDescription => { AddressbookPropName::AddressbookDescription => {
AddressbookProp::AddressbookDescription(self.0.description.to_owned()) AddressbookProp::AddressbookDescription(self.0.description.to_owned())

View File

@@ -25,3 +25,4 @@ tracing.workspace = true
tokio.workspace = true tokio.workspace = true
http.workspace = true http.workspace = true
headers.workspace = true headers.workspace = true
strum.workspace = true

View File

@@ -11,3 +11,5 @@ pub use tag_list::TagList;
mod error; mod error;
pub mod sync_collection; pub mod sync_collection;
pub use error::ErrorElement; pub use error::ErrorElement;
mod report_set;
pub use report_set::SupportedReportSet;

View File

@@ -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<T: XmlSerialize + 'static> {
#[xml(flatten)]
#[xml(ns = "crate::namespace::NS_DAV")]
supported_report: Vec<ReportWrapper<T>>,
}
impl<T: XmlSerialize + Clone + 'static> SupportedReportSet<T> {
pub fn new(methods: Vec<T>) -> 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<T: XmlSerialize> {
#[xml(ns = "crate::namespace::NS_DAV")]
report: T,
}