From f72559d027c3394105fc4a21d7d819d3c65310b3 Mon Sep 17 00:00:00 2001 From: Lennart <18233294+lennart-k@users.noreply.github.com> Date: Sun, 2 Nov 2025 18:33:54 +0100 Subject: [PATCH] caldav: Add supported-collation-set property --- .../report/calendar_query/text_match.rs | 11 +++++++++ .../caldav/src/calendar/methods/report/mod.rs | 2 +- crates/caldav/src/calendar/prop.rs | 24 +++++++++++++++++++ crates/caldav/src/calendar/resource.rs | 9 ++++++- .../src/calendar/test_files/propfind.outputs | 5 ++++ 5 files changed, 49 insertions(+), 2 deletions(-) diff --git a/crates/caldav/src/calendar/methods/report/calendar_query/text_match.rs b/crates/caldav/src/calendar/methods/report/calendar_query/text_match.rs index b8c4f27..9d8af6f 100644 --- a/crates/caldav/src/calendar/methods/report/calendar_query/text_match.rs +++ b/crates/caldav/src/calendar/methods/report/calendar_query/text_match.rs @@ -10,6 +10,7 @@ pub enum TextCollation { impl TextCollation { // Check whether a haystack contains a needle respecting the collation + #[must_use] pub fn match_text(&self, needle: &str, haystack: &str) -> bool { match self { // https://datatracker.ietf.org/doc/html/rfc4790#section-9.2 @@ -21,6 +22,15 @@ impl TextCollation { } } +impl AsRef for TextCollation { + fn as_ref(&self) -> &str { + match self { + Self::AsciiCasemap => "i;ascii-casemap", + Self::Octet => "i;octet", + } + } +} + impl ValueDeserialize for TextCollation { fn deserialize(val: &str) -> Result { match val { @@ -60,6 +70,7 @@ pub struct TextMatchElement { } impl TextMatchElement { + #[must_use] pub fn match_property(&self, property: &Property) -> bool { let Self { collation, diff --git a/crates/caldav/src/calendar/methods/report/mod.rs b/crates/caldav/src/calendar/methods/report/mod.rs index 2703f01..4d7ef6b 100644 --- a/crates/caldav/src/calendar/methods/report/mod.rs +++ b/crates/caldav/src/calendar/methods/report/mod.rs @@ -27,7 +27,7 @@ use sync_collection::handle_sync_collection; use tracing::instrument; mod calendar_multiget; -mod calendar_query; +pub mod calendar_query; mod sync_collection; #[derive(XmlDeserialize, XmlDocument, Clone, Debug, PartialEq)] diff --git a/crates/caldav/src/calendar/prop.rs b/crates/caldav/src/calendar/prop.rs index fa74bf6..cf3a0a7 100644 --- a/crates/caldav/src/calendar/prop.rs +++ b/crates/caldav/src/calendar/prop.rs @@ -3,6 +3,8 @@ use rustical_ical::CalendarObjectType; use rustical_xml::{XmlDeserialize, XmlSerialize}; use strum_macros::VariantArray; +use crate::calendar::methods::report::calendar_query::text_match::TextCollation; + #[derive(Debug, Clone, XmlSerialize, XmlDeserialize, PartialEq, Eq, From, Into)] pub struct SupportedCalendarComponent { #[xml(ty = "attr")] @@ -36,6 +38,28 @@ impl From for Vec { } } +#[derive(Debug, Clone, XmlSerialize, XmlDeserialize, PartialEq, Eq, From, Into)] +pub struct SupportedCollation(#[xml(ty = "text")] pub TextCollation); + +#[derive(Debug, Clone, XmlSerialize, XmlDeserialize, PartialEq, Eq)] +pub struct SupportedCollationSet( + #[xml( + ns = "rustical_dav::namespace::NS_CALDAV", + flatten, + rename = "supported-collation" + )] + pub Vec, +); + +impl Default for SupportedCollationSet { + fn default() -> Self { + Self(vec![ + SupportedCollation(TextCollation::AsciiCasemap), + SupportedCollation(TextCollation::Octet), + ]) + } +} + #[derive(Debug, Clone, XmlSerialize, PartialEq, Eq)] pub struct CalendarData { #[xml(ty = "attr")] diff --git a/crates/caldav/src/calendar/resource.rs b/crates/caldav/src/calendar/resource.rs index bec5de3..2c891eb 100644 --- a/crates/caldav/src/calendar/resource.rs +++ b/crates/caldav/src/calendar/resource.rs @@ -1,6 +1,6 @@ use super::prop::{SupportedCalendarComponentSet, SupportedCalendarData}; use crate::Error; -use crate::calendar::prop::ReportMethod; +use crate::calendar::prop::{ReportMethod, SupportedCollationSet}; use chrono::{DateTime, Utc}; use derive_more::derive::{From, Into}; use ical::IcalParser; @@ -39,6 +39,8 @@ pub enum CalendarProp { SupportedCalendarComponentSet(SupportedCalendarComponentSet), #[xml(ns = "rustical_dav::namespace::NS_CALDAV", skip_deserializing)] SupportedCalendarData(SupportedCalendarData), + #[xml(ns = "rustical_dav::namespace::NS_CALDAV", skip_deserializing)] + SupportedCollationSet(SupportedCollationSet), #[xml(ns = "rustical_dav::namespace::NS_DAV")] MaxResourceSize(i64), #[xml(skip_deserializing)] @@ -156,6 +158,9 @@ impl Resource for CalendarResource { CalendarPropName::SupportedCalendarData => { CalendarProp::SupportedCalendarData(SupportedCalendarData::default()) } + CalendarPropName::SupportedCollationSet => { + CalendarProp::SupportedCollationSet(SupportedCollationSet::default()) + } CalendarPropName::MaxResourceSize => CalendarProp::MaxResourceSize(10_000_000), CalendarPropName::SupportedReportSet => { CalendarProp::SupportedReportSet(SupportedReportSet::all()) @@ -244,6 +249,7 @@ impl Resource for CalendarResource { } CalendarProp::TimezoneServiceSet(_) | CalendarProp::SupportedCalendarData(_) + | CalendarProp::SupportedCollationSet(_) | CalendarProp::MaxResourceSize(_) | CalendarProp::SupportedReportSet(_) | CalendarProp::Source(_) @@ -283,6 +289,7 @@ impl Resource for CalendarResource { } CalendarPropName::TimezoneServiceSet | CalendarPropName::SupportedCalendarData + | CalendarPropName::SupportedCollationSet | CalendarPropName::MaxResourceSize | CalendarPropName::SupportedReportSet | CalendarPropName::Source diff --git a/crates/caldav/src/calendar/test_files/propfind.outputs b/crates/caldav/src/calendar/test_files/propfind.outputs index 881ee37..9330cdf 100644 --- a/crates/caldav/src/calendar/test_files/propfind.outputs +++ b/crates/caldav/src/calendar/test_files/propfind.outputs @@ -11,6 +11,7 @@ + @@ -160,6 +161,10 @@ END:VCALENDAR + + i;ascii-casemap + i;octet + 10000000