diff options
-rw-r--r-- | src/dav/caldecoder.rs | 33 | ||||
-rw-r--r-- | src/dav/calencoder.rs | 24 | ||||
-rw-r--r-- | src/dav/caltypes.rs | 45 | ||||
-rw-r--r-- | src/dav/mod.rs | 17 | ||||
-rw-r--r-- | src/dav/realization.rs | 7 |
5 files changed, 107 insertions, 19 deletions
diff --git a/src/dav/caldecoder.rs b/src/dav/caldecoder.rs new file mode 100644 index 0000000..75af4b7 --- /dev/null +++ b/src/dav/caldecoder.rs @@ -0,0 +1,33 @@ +use super::types as dav; +use super::caltypes::*; +use super::xml; +use super::error; + +// ---- ROOT ELEMENTS --- + +// ---- EXTENSIONS --- +impl xml::QRead<Violation> for Violation { + async fn qread(&self, xml: &mut xml::Reader<impl xml::IRead>) -> Result<Option<Self>, error::ParsingError> { + unreachable!(); + } +} + +impl xml::QRead<Property> for Property { + async fn qread(&self, xml: &mut xml::Reader<impl xml::IRead>) -> Result<Option<Self>, error::ParsingError> { + unreachable!(); + } +} + +impl xml::QRead<PropertyRequest> for PropertyRequest { + async fn qread(&self, xml: &mut xml::Reader<impl xml::IRead>) -> Result<Option<Self>, error::ParsingError> { + unreachable!(); + } +} + +impl xml::QRead<ResourceType> for ResourceType { + async fn qread(&self, xml: &mut xml::Reader<impl xml::IRead>) -> Result<Option<Self>, error::ParsingError> { + unreachable!(); + } +} + +// ---- INNER XML ---- diff --git a/src/dav/calencoder.rs b/src/dav/calencoder.rs index 01cecc3..d030aa1 100644 --- a/src/dav/calencoder.rs +++ b/src/dav/calencoder.rs @@ -662,19 +662,25 @@ impl QWrite for TimeRange { } } -/* #[cfg(test)] mod tests { use super::*; use crate::dav::types as dav; + use crate::dav::realization::Calendar; use tokio::io::AsyncWriteExt; use chrono::{Utc,TimeZone,DateTime}; - async fn serialize<C: Context, Q: QuickWritable<C>>(ctx: C, elem: &Q) -> String { + async fn serialize(elem: &impl QWrite) -> String { let mut buffer = Vec::new(); let mut tokio_buffer = tokio::io::BufWriter::new(&mut buffer); - let mut writer = Writer::new_with_indent(&mut tokio_buffer, b' ', 4); - elem.write(&mut writer, ctx).await.expect("xml serialization"); + let q = quick_xml::writer::Writer::new_with_indent(&mut tokio_buffer, b' ', 4); + let ns_to_apply = vec![ + ("xmlns:D".into(), "DAV:".into()), + ("xmlns:C".into(), "urn:ietf:params:xml:ns:caldav".into()), + ]; + let mut writer = Writer { q, ns_to_apply }; + + elem.qwrite(&mut writer).await.expect("xml serialization"); tokio_buffer.flush().await.expect("tokio buffer flush"); let got = std::str::from_utf8(buffer.as_slice()).unwrap(); @@ -684,8 +690,7 @@ mod tests { #[tokio::test] async fn basic_violation() { let got = serialize( - CalExtension { root: true }, - &dav::Error(vec![ + &dav::Error::<Calendar>(vec![ dav::Violation::Extension(Violation::ResourceMustBeNull), ]) ).await; @@ -700,8 +705,7 @@ mod tests { #[tokio::test] async fn rfc_calendar_query1_req() { let got = serialize( - CalExtension { root: true }, - &CalendarQuery { + &CalendarQuery::<Calendar> { selector: Some(CalendarSelector::Prop(dav::PropName(vec![ dav::PropertyRequest::GetEtag, dav::PropertyRequest::Extension(PropertyRequest::CalendarData(CalendarDataRequest { @@ -806,8 +810,7 @@ mod tests { #[tokio::test] async fn rfc_calendar_query1_res() { let got = serialize( - CalExtension { root: true }, - &dav::Multistatus { + &dav::Multistatus::<Calendar> { responses: vec![ dav::Response { href: dav::Href("http://cal.example.com/bernard/work/abcd2.ics".into()), @@ -877,4 +880,3 @@ mod tests { assert_eq!(&got, expected, "\n---GOT---\n{got}\n---EXP---\n{expected}\n"); } } -*/ diff --git a/src/dav/caltypes.rs b/src/dav/caltypes.rs index 585afe2..68e7baf 100644 --- a/src/dav/caltypes.rs +++ b/src/dav/caltypes.rs @@ -26,6 +26,7 @@ use super::types as dav; /// instruction in Section 12.13.2 of [RFC2518]. /// /// <!ELEMENT mkcalendar (DAV:set)> +#[derive(Debug, PartialEq)] pub struct MkCalendar<E: dav::Extension>(pub dav::Set<E>); @@ -42,6 +43,7 @@ pub struct MkCalendar<E: dav::Extension>(pub dav::Set<E>); /// Definition: /// /// <!ELEMENT mkcol-response (propstat+)> +#[derive(Debug, PartialEq)] pub struct MkCalendarResponse<E: dav::Extension>(pub Vec<dav::PropStat<E>>); // --- (REPORT PART) --- @@ -59,6 +61,7 @@ pub struct MkCalendarResponse<E: dav::Extension>(pub Vec<dav::PropStat<E>>); /// <!ELEMENT calendar-query ((DAV:allprop | /// DAV:propname | /// DAV:prop)?, filter, timezone?)> +#[derive(Debug, PartialEq)] pub struct CalendarQuery<E: dav::Extension> { pub selector: Option<CalendarSelector<E>>, pub filter: Filter, @@ -79,6 +82,7 @@ pub struct CalendarQuery<E: dav::Extension> { /// <!ELEMENT calendar-multiget ((DAV:allprop | /// DAV:propname | /// DAV:prop)?, DAV:href+)> +#[derive(Debug, PartialEq)] pub struct CalendarMultiget<E: dav::Extension> { pub selector: Option<CalendarSelector<E>>, pub href: Vec<dav::Href>, @@ -95,14 +99,17 @@ pub struct CalendarMultiget<E: dav::Extension> { /// /// Definition: /// <!ELEMENT free-busy-query (time-range)> +#[derive(Debug, PartialEq)] pub struct FreeBusyQuery(pub TimeRange); // ----- Hooks ----- +#[derive(Debug, PartialEq)] pub enum ResourceType { Calendar, } /// Check the matching Property object for documentation +#[derive(Debug, PartialEq)] pub enum PropertyRequest { CalendarDescription, CalendarTimezone, @@ -116,6 +123,8 @@ pub enum PropertyRequest { SupportedCollationSet, CalendarData(CalendarDataRequest), } + +#[derive(Debug, PartialEq)] pub enum Property { /// Name: calendar-description /// @@ -591,6 +600,7 @@ pub enum Property { CalendarData(CalendarDataPayload), } +#[derive(Debug, PartialEq)] pub enum Violation { /// (DAV:resource-must-be-null): A resource MUST NOT exist at the /// Request-URI; @@ -761,6 +771,7 @@ pub enum Violation { /// If the client chooses a collation not supported by the server, the /// server MUST respond with a CALDAV:supported-collation precondition /// error response. +#[derive(Debug, PartialEq)] pub struct SupportedCollation(pub Collation); /// <!ELEMENT calendar-data (#PCDATA)> @@ -769,6 +780,7 @@ pub struct SupportedCollation(pub Collation); /// when nested in the DAV:prop XML element in a calendaring /// REPORT response to specify the content of a returned /// calendar object resource. +#[derive(Debug, PartialEq)] pub struct CalendarDataPayload { pub mime: Option<CalendarDataSupport>, pub payload: String, @@ -781,6 +793,7 @@ pub struct CalendarDataPayload { /// when nested in the DAV:prop XML element in a calendaring /// REPORT request to specify which parts of calendar object /// resources should be returned in the response; +#[derive(Debug, PartialEq)] pub struct CalendarDataRequest { pub mime: Option<CalendarDataSupport>, pub comp: Option<Comp>, @@ -795,6 +808,7 @@ pub struct CalendarDataRequest { /// when nested in the CALDAV:supported-calendar-data property /// to specify a supported media type for calendar object /// resources; +#[derive(Debug, PartialEq)] pub struct CalendarDataEmpty(pub Option<CalendarDataSupport>); /// <!ATTLIST calendar-data content-type CDATA "text/calendar" @@ -803,6 +817,7 @@ pub struct CalendarDataEmpty(pub Option<CalendarDataSupport>); /// version value: a version string /// attributes can be used on all three variants of the /// CALDAV:calendar-data XML element. +#[derive(Debug, PartialEq)] pub struct CalendarDataSupport { pub content_type: String, pub version: String, @@ -828,10 +843,13 @@ pub struct CalendarDataSupport { /// However, the CALDAV:prop and CALDAV:allprop elements are defined /// in the "urn:ietf:params:xml:ns:caldav" namespace instead of the /// "DAV:" namespace. +#[derive(Debug, PartialEq)] pub struct Comp { pub name: Component, pub additional_rules: Option<CompInner>, } + +#[derive(Debug, PartialEq)] pub struct CompInner { pub prop_kind: PropKind, pub comp_kind: CompKind, @@ -850,6 +868,7 @@ pub struct CompInner { /// <C:comp name="VEVENT"/> /// <C:comp name="VTODO"/> /// </C:supported-calendar-component-set> +#[derive(Debug, PartialEq)] pub struct CompSupport(pub Component); /// Name: allcomp @@ -865,6 +884,7 @@ pub struct CompSupport(pub Component); /// Definition: /// /// <!ELEMENT allcomp EMPTY> +#[derive(Debug, PartialEq)] pub enum CompKind { AllComp, Comp(Vec<Comp>), @@ -888,6 +908,7 @@ pub enum CompKind { /// allprop element defined in [RFC2518]. However, the CALDAV:allprop /// element is defined in the "urn:ietf:params:xml:ns:caldav" /// namespace instead of the "DAV:" namespace. +#[derive(Debug, PartialEq)] pub enum PropKind { AllProp, Prop(Vec<CalProp>), @@ -917,11 +938,13 @@ pub enum PropKind { /// element defined in [RFC2518]. However, the CALDAV:prop element is /// defined in the "urn:ietf:params:xml:ns:caldav" namespace instead /// of the "DAV:" namespace. +#[derive(Debug, PartialEq)] pub struct CalProp { pub name: ComponentProperty, pub novalue: Option<bool>, } +#[derive(Debug, PartialEq)] pub enum RecurrenceModifier { Expand(Expand), LimitRecurrenceSet(LimitRecurrenceSet), @@ -967,6 +990,7 @@ pub enum RecurrenceModifier { /// end CDATA #REQUIRED> /// start value: an iCalendar "date with UTC time" /// end value: an iCalendar "date with UTC time" +#[derive(Debug, PartialEq)] pub struct Expand(pub DateTime<Utc>, pub DateTime<Utc>); /// CALDAV:limit-recurrence-set XML Element @@ -1014,6 +1038,7 @@ pub struct Expand(pub DateTime<Utc>, pub DateTime<Utc>); /// end CDATA #REQUIRED> /// start value: an iCalendar "date with UTC time" /// end value: an iCalendar "date with UTC time" +#[derive(Debug, PartialEq)] pub struct LimitRecurrenceSet(pub DateTime<Utc>, pub DateTime<Utc>); /// Name: limit-freebusy-set @@ -1044,9 +1069,11 @@ pub struct LimitRecurrenceSet(pub DateTime<Utc>, pub DateTime<Utc>); /// end CDATA #REQUIRED> /// start value: an iCalendar "date with UTC time" /// end value: an iCalendar "date with UTC time" +#[derive(Debug, PartialEq)] pub struct LimitFreebusySet(pub DateTime<Utc>, pub DateTime<Utc>); /// Used by CalendarQuery & CalendarMultiget +#[derive(Debug, PartialEq)] pub enum CalendarSelector<E: dav::Extension> { AllProp, PropName, @@ -1101,17 +1128,20 @@ pub enum CalendarSelector<E: dav::Extension> { /// <!ATTLIST comp-filter name CDATA #REQUIRED> /// name value: a calendar object or calendar component /// type (e.g., VEVENT) +#[derive(Debug, PartialEq)] pub struct CompFilter { pub name: Component, // Option 1 = None, Option 2, 3, 4 = Some pub additional_rules: Option<CompFilterRules>, } +#[derive(Debug, PartialEq)] pub enum CompFilterRules { // Option 2 IsNotDefined, // Options 3 & 4 Matches(CompFilterMatch), } +#[derive(Debug, PartialEq)] pub struct CompFilterMatch { pub time_range: Option<TimeRange>, pub prop_filter: Vec<PropFilter>, @@ -1162,22 +1192,26 @@ pub struct CompFilterMatch { /// /// <!ATTLIST prop-filter name CDATA #REQUIRED> /// name value: a calendar property name (e.g., ATTENDEE) +#[derive(Debug, PartialEq)] pub struct PropFilter { pub name: Component, // None = Option 1, Some() = Option 2, 3 & 4 pub additional_rules: Option<PropFilterRules>, } +#[derive(Debug, PartialEq)] pub enum PropFilterRules { // Option 2 IsNotDefined, // Options 3 & 4 Match(PropFilterMatch), } +#[derive(Debug, PartialEq)] pub struct PropFilterMatch { pub time_range: Option<TimeRange>, pub time_or_text: Option<TimeOrText>, pub param_filter: Vec<ParamFilter>, } +#[derive(Debug, PartialEq)] pub enum TimeOrText { Time(TimeRange), Text(TextMatch), @@ -1211,6 +1245,7 @@ pub enum TimeOrText { /// PCDATA value: string /// <!ATTLIST text-match collation CDATA "i;ascii-casemap" /// negate-condition (yes | no) "no"> +#[derive(Debug, PartialEq)] pub struct TextMatch { pub collation: Option<Collation>, pub negate_condition: Option<bool>, @@ -1246,10 +1281,12 @@ pub struct TextMatch { /// /// <!ATTLIST param-filter name CDATA #REQUIRED> /// name value: a property parameter name (e.g., PARTSTAT) +#[derive(Debug, PartialEq)] pub struct ParamFilter { pub name: PropertyParameter, pub additional_rules: Option<ParamFilterMatch>, } +#[derive(Debug, PartialEq)] pub enum ParamFilterMatch { IsNotDefined, Match(TextMatch), @@ -1305,6 +1342,7 @@ pub enum ParamFilterMatch { /// /// <!ELEMENT timezone (#PCDATA)> /// PCDATA value: an iCalendar object with exactly one VTIMEZONE +#[derive(Debug, PartialEq)] pub struct TimeZone(pub String); /// Name: filter @@ -1320,6 +1358,7 @@ pub struct TimeZone(pub String); /// /// Definition: /// <!ELEMENT filter (comp-filter)> +#[derive(Debug, PartialEq)] pub struct Filter(pub CompFilter); /// Name: time-range @@ -1331,6 +1370,7 @@ pub struct Filter(pub CompFilter); /// end CDATA #IMPLIED> /// start value: an iCalendar "date with UTC time" /// end value: an iCalendar "date with UTC time" +#[derive(Debug, PartialEq)] pub enum TimeRange { OnlyStart(DateTime<Utc>), OnlyEnd(DateTime<Utc>), @@ -1340,6 +1380,7 @@ pub enum TimeRange { // ----------------------- ENUM ATTRIBUTES --------------------- /// Known components +#[derive(Debug, PartialEq)] pub enum Component { VCalendar, VJournal, @@ -1368,9 +1409,11 @@ impl Component { /// name="VERSION", name="SUMMARY", etc. /// Can be set on different objects: VCalendar, VEvent, etc. /// Might be replaced by an enum later +#[derive(Debug, PartialEq)] pub struct ComponentProperty(pub String); /// like PARSTAT +#[derive(Debug, PartialEq)] pub struct PropertyParameter(pub String); impl PropertyParameter { pub fn as_str<'a>(&'a self) -> &'a str { @@ -1378,7 +1421,7 @@ impl PropertyParameter { } } -#[derive(Default)] +#[derive(Default,Debug,PartialEq)] pub enum Collation { #[default] AsciiCaseMap, diff --git a/src/dav/mod.rs b/src/dav/mod.rs index abc46e7..bff95e7 100644 --- a/src/dav/mod.rs +++ b/src/dav/mod.rs @@ -1,14 +1,25 @@ +// utils mod error; mod xml; + +// webdav mod types; +mod encoder; +mod decoder; + +// calendar mod caltypes; +mod calencoder; +mod caldecoder; + +// wip mod acltypes; mod versioningtypes; -mod encoder; -mod calencoder; -mod decoder; + +// final type mod realization; + use std::net::SocketAddr; use anyhow::{anyhow, Result}; diff --git a/src/dav/realization.rs b/src/dav/realization.rs index 22c9cfc..a02de94 100644 --- a/src/dav/realization.rs +++ b/src/dav/realization.rs @@ -28,14 +28,13 @@ impl dav::Extension for Core { type ResourceType = Disabled; } -/* // WebDAV with the base Calendar implementation (RFC4791) -pub struct CalendarMin {} -impl dav::Extension for CalendarMin +pub struct Calendar {} +impl dav::Extension for Calendar { type Error = cal::Violation; type Property = cal::Property; type PropertyRequest = cal::PropertyRequest; type ResourceType = cal::ResourceType; } -*/ + |