diff options
-rw-r--r-- | Cargo.lock | 1 | ||||
-rw-r--r-- | aero-dav/Cargo.toml | 1 | ||||
-rw-r--r-- | aero-dav/src/caldecoder.rs | 22 | ||||
-rw-r--r-- | aero-dav/src/calencoder.rs | 19 | ||||
-rw-r--r-- | aero-dav/src/caltypes.rs | 7 | ||||
-rw-r--r-- | aero-dav/src/realization.rs | 73 | ||||
-rw-r--r-- | aero-dav/src/syncdecoder.rs | 68 | ||||
-rw-r--r-- | aero-dav/src/syncencoder.rs | 57 | ||||
-rw-r--r-- | aero-dav/src/synctypes.rs | 17 | ||||
-rw-r--r-- | aero-dav/src/types.rs | 1 | ||||
-rw-r--r-- | aero-dav/src/versioningdecoder.rs | 81 | ||||
-rw-r--r-- | aero-dav/src/versioningencoder.rs | 62 | ||||
-rw-r--r-- | aero-dav/src/versioningtypes.rs | 20 |
13 files changed, 414 insertions, 15 deletions
@@ -70,6 +70,7 @@ dependencies = [ "http 1.1.0", "quick-xml", "tokio", + "tracing", ] [[package]] diff --git a/aero-dav/Cargo.toml b/aero-dav/Cargo.toml index 92929b1..c847f68 100644 --- a/aero-dav/Cargo.toml +++ b/aero-dav/Cargo.toml @@ -12,3 +12,4 @@ http.workspace = true chrono.workspace = true tokio.workspace = true futures.workspace = true +tracing.workspace = true diff --git a/aero-dav/src/caldecoder.rs b/aero-dav/src/caldecoder.rs index ff79845..0df867f 100644 --- a/aero-dav/src/caldecoder.rs +++ b/aero-dav/src/caldecoder.rs @@ -104,6 +104,28 @@ impl QRead<FreeBusyQuery> for FreeBusyQuery { } } +impl QRead<ReportTypeName> for ReportTypeName { + async fn qread(xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> { + if xml.maybe_open(DAV_URN, "calendar-query").await?.is_some() { + xml.close().await?; + return Ok(Self::Query); + } + if xml + .maybe_open(DAV_URN, "calendar-multiget") + .await? + .is_some() + { + xml.close().await?; + return Ok(Self::Multiget); + } + if xml.maybe_open(DAV_URN, "free-busy-query").await?.is_some() { + xml.close().await?; + return Ok(Self::FreeBusy); + } + Err(ParsingError::Recoverable) + } +} + // ---- EXTENSIONS --- impl QRead<Violation> for Violation { async fn qread(xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> { diff --git a/aero-dav/src/calencoder.rs b/aero-dav/src/calencoder.rs index 48c93d0..a41747f 100644 --- a/aero-dav/src/calencoder.rs +++ b/aero-dav/src/calencoder.rs @@ -33,6 +33,25 @@ impl<E: Extension> QWrite for MkCalendarResponse<E> { } // ----------------------- REPORT METHOD ------------------------------------- +impl QWrite for ReportTypeName { + async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> { + match self { + Self::Query => { + let start = xml.create_dav_element("calendar-query"); + xml.q.write_event_async(Event::Empty(start)).await + } + Self::Multiget => { + let start = xml.create_dav_element("calendar-multiget"); + xml.q.write_event_async(Event::Empty(start)).await + } + Self::FreeBusy => { + let start = xml.create_dav_element("free-busy-query"); + xml.q.write_event_async(Event::Empty(start)).await + } + } + } +} + impl<E: Extension> QWrite for ReportType<E> { async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> { match self { diff --git a/aero-dav/src/caltypes.rs b/aero-dav/src/caltypes.rs index a763653..a4f6fef 100644 --- a/aero-dav/src/caltypes.rs +++ b/aero-dav/src/caltypes.rs @@ -51,6 +51,13 @@ pub struct MkCalendarResponse<E: dav::Extension>(pub Vec<dav::PropStat<E>>); // --- (REPORT PART) --- #[derive(Debug, PartialEq, Clone)] +pub enum ReportTypeName { + Query, + Multiget, + FreeBusy, +} + +#[derive(Debug, PartialEq, Clone)] pub enum ReportType<E: dav::Extension> { Query(CalendarQuery<E>), Multiget(CalendarMultiget<E>), diff --git a/aero-dav/src/realization.rs b/aero-dav/src/realization.rs index 0f3aec4..b37e0f1 100644 --- a/aero-dav/src/realization.rs +++ b/aero-dav/src/realization.rs @@ -3,6 +3,7 @@ use super::caltypes as cal; use super::error; use super::synctypes as sync; use super::types as dav; +use super::versioningtypes as vers; use super::xml; #[derive(Debug, PartialEq, Clone)] @@ -33,6 +34,7 @@ impl dav::Extension for Core { type PropertyRequest = Disabled; type ResourceType = Disabled; type ReportType = Disabled; + type ReportTypeName = Disabled; } // WebDAV with the base Calendar implementation (RFC4791) @@ -44,6 +46,7 @@ impl dav::Extension for Calendar { type PropertyRequest = cal::PropertyRequest; type ResourceType = cal::ResourceType; type ReportType = cal::ReportType<Calendar>; + type ReportTypeName = cal::ReportTypeName; } // ACL @@ -55,6 +58,7 @@ impl dav::Extension for Acl { type PropertyRequest = acl::PropertyRequest; type ResourceType = acl::ResourceType; type ReportType = Disabled; + type ReportTypeName = Disabled; } // All merged @@ -62,27 +66,38 @@ impl dav::Extension for Acl { pub struct All {} impl dav::Extension for All { type Error = cal::Violation; - type Property = Property; + type Property = Property<All>; type PropertyRequest = PropertyRequest; type ResourceType = ResourceType; type ReportType = ReportType<All>; + type ReportTypeName = ReportTypeName; } #[derive(Debug, PartialEq, Clone)] -pub enum Property { +pub enum Property<E: dav::Extension> { Cal(cal::Property), Acl(acl::Property), + Sync(sync::Property), + Vers(vers::Property<E>), } -impl xml::QRead<Property> for Property { +impl<E: dav::Extension> xml::QRead<Property<E>> for Property<E> { async fn qread(xml: &mut xml::Reader<impl xml::IRead>) -> Result<Self, error::ParsingError> { match cal::Property::qread(xml).await { Err(error::ParsingError::Recoverable) => (), - otherwise => return otherwise.map(Property::Cal), + otherwise => return otherwise.map(Property::<E>::Cal), } - acl::Property::qread(xml).await.map(Property::Acl) + match acl::Property::qread(xml).await { + Err(error::ParsingError::Recoverable) => (), + otherwise => return otherwise.map(Property::Acl), + } + match sync::Property::qread(xml).await { + Err(error::ParsingError::Recoverable) => (), + otherwise => return otherwise.map(Property::Sync), + } + vers::Property::qread(xml).await.map(Property::Vers) } } -impl xml::QWrite for Property { +impl<E: dav::Extension> xml::QWrite for Property<E> { async fn qwrite( &self, xml: &mut xml::Writer<impl xml::IWrite>, @@ -90,6 +105,8 @@ impl xml::QWrite for Property { match self { Self::Cal(c) => c.qwrite(xml).await, Self::Acl(a) => a.qwrite(xml).await, + Self::Sync(s) => s.qwrite(xml).await, + Self::Vers(v) => v.qwrite(xml).await, } } } @@ -98,6 +115,8 @@ impl xml::QWrite for Property { pub enum PropertyRequest { Cal(cal::PropertyRequest), Acl(acl::PropertyRequest), + Sync(sync::PropertyRequest), + Vers(vers::PropertyRequest), } impl xml::QRead<PropertyRequest> for PropertyRequest { async fn qread(xml: &mut xml::Reader<impl xml::IRead>) -> Result<Self, error::ParsingError> { @@ -105,9 +124,17 @@ impl xml::QRead<PropertyRequest> for PropertyRequest { Err(error::ParsingError::Recoverable) => (), otherwise => return otherwise.map(PropertyRequest::Cal), } - acl::PropertyRequest::qread(xml) + match acl::PropertyRequest::qread(xml).await { + Err(error::ParsingError::Recoverable) => (), + otherwise => return otherwise.map(PropertyRequest::Acl), + } + match sync::PropertyRequest::qread(xml).await { + Err(error::ParsingError::Recoverable) => (), + otherwise => return otherwise.map(PropertyRequest::Sync), + } + vers::PropertyRequest::qread(xml) .await - .map(PropertyRequest::Acl) + .map(PropertyRequest::Vers) } } impl xml::QWrite for PropertyRequest { @@ -118,6 +145,8 @@ impl xml::QWrite for PropertyRequest { match self { Self::Cal(c) => c.qwrite(xml).await, Self::Acl(a) => a.qwrite(xml).await, + Self::Sync(s) => s.qwrite(xml).await, + Self::Vers(v) => v.qwrite(xml).await, } } } @@ -175,3 +204,31 @@ impl<E: dav::Extension> xml::QWrite for ReportType<E> { } } } + +#[derive(Debug, PartialEq, Clone)] +pub enum ReportTypeName { + Cal(cal::ReportTypeName), + Sync(sync::ReportTypeName), +} +impl xml::QRead<ReportTypeName> for ReportTypeName { + async fn qread(xml: &mut xml::Reader<impl xml::IRead>) -> Result<Self, error::ParsingError> { + match cal::ReportTypeName::qread(xml).await { + Err(error::ParsingError::Recoverable) => (), + otherwise => return otherwise.map(ReportTypeName::Cal), + } + sync::ReportTypeName::qread(xml) + .await + .map(ReportTypeName::Sync) + } +} +impl xml::QWrite for ReportTypeName { + async fn qwrite( + &self, + xml: &mut xml::Writer<impl xml::IWrite>, + ) -> Result<(), quick_xml::Error> { + match self { + Self::Cal(c) => c.qwrite(xml).await, + Self::Sync(s) => s.qwrite(xml).await, + } + } +} diff --git a/aero-dav/src/syncdecoder.rs b/aero-dav/src/syncdecoder.rs index 8e035ab..d81f8d4 100644 --- a/aero-dav/src/syncdecoder.rs +++ b/aero-dav/src/syncdecoder.rs @@ -5,6 +5,34 @@ use super::synctypes::*; use super::types as dav; use super::xml::{IRead, QRead, Reader, DAV_URN}; +impl QRead<PropertyRequest> for PropertyRequest { + async fn qread(xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> { + let mut dirty = false; + let mut m_cdr = None; + xml.maybe_read(&mut m_cdr, &mut dirty).await?; + m_cdr.ok_or(ParsingError::Recoverable).map(Self::SyncToken) + } +} + +impl QRead<Property> for Property { + async fn qread(xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> { + let mut dirty = false; + let mut m_cdr = None; + xml.maybe_read(&mut m_cdr, &mut dirty).await?; + m_cdr.ok_or(ParsingError::Recoverable).map(Self::SyncToken) + } +} + +impl QRead<ReportTypeName> for ReportTypeName { + async fn qread(xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> { + if xml.maybe_open(DAV_URN, "sync-collection").await?.is_some() { + xml.close().await?; + return Ok(Self::SyncCollection); + } + Err(ParsingError::Recoverable) + } +} + impl<E: dav::Extension> QRead<SyncCollection<E>> for SyncCollection<E> { async fn qread(xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> { xml.open(DAV_URN, "sync-collection").await?; @@ -75,7 +103,7 @@ impl QRead<SyncLevel> for SyncLevel { #[cfg(test)] mod tests { use super::*; - use crate::realization::All; + use crate::realization::{self, All}; use crate::types as dav; use crate::versioningtypes as vers; use crate::xml::Node; @@ -172,4 +200,42 @@ mod tests { assert_eq!(got, expected); } } + + #[tokio::test] + async fn prop_req() { + let expected = dav::PropName::<All>(vec![dav::PropertyRequest::Extension( + realization::PropertyRequest::Sync(PropertyRequest::SyncToken( + SyncTokenRequest::InitialSync, + )), + )]); + let src = r#"<prop xmlns="DAV:"><sync-token/></prop>"#; + let got = deserialize::<dav::PropName<All>>(src).await; + assert_eq!(got, expected); + } + + #[tokio::test] + async fn prop_val() { + let expected = dav::PropValue::<All>(vec![ + dav::Property::Extension(realization::Property::Sync(Property::SyncToken(SyncToken( + "http://example.com/ns/sync/1232".into(), + )))), + dav::Property::Extension(realization::Property::Vers( + vers::Property::SupportedReportSet(vec![vers::SupportedReport( + vers::ReportName::Extension(realization::ReportTypeName::Sync( + ReportTypeName::SyncCollection, + )), + )]), + )), + ]); + let src = r#"<prop xmlns="DAV:"> + <sync-token>http://example.com/ns/sync/1232</sync-token> + <supported-report-set> + <supported-report> + <report><sync-collection/></report> + </supported-report> + </supported-report-set> + </prop>"#; + let got = deserialize::<dav::PropValue<All>>(src).await; + assert_eq!(got, expected); + } } diff --git a/aero-dav/src/syncencoder.rs b/aero-dav/src/syncencoder.rs index 22b288b..59ad6cc 100644 --- a/aero-dav/src/syncencoder.rs +++ b/aero-dav/src/syncencoder.rs @@ -5,6 +5,33 @@ use super::synctypes::*; use super::types::Extension; use super::xml::{IWrite, QWrite, Writer}; +impl QWrite for Property { + async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> { + match self { + Self::SyncToken(token) => token.qwrite(xml).await, + } + } +} + +impl QWrite for PropertyRequest { + async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> { + match self { + Self::SyncToken(token) => token.qwrite(xml).await, + } + } +} + +impl QWrite for ReportTypeName { + async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> { + match self { + Self::SyncCollection => { + let start = xml.create_dav_element("sync-collection"); + xml.q.write_event_async(Event::Empty(start)).await + } + } + } +} + impl<E: Extension> QWrite for SyncCollection<E> { async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> { let start = xml.create_dav_element("sync-collection"); @@ -72,7 +99,7 @@ impl QWrite for SyncLevel { #[cfg(test)] mod tests { use super::*; - use crate::realization::All; + use crate::realization::{self, All}; use crate::types as dav; use crate::versioningtypes as vers; use crate::xml::Node; @@ -92,6 +119,7 @@ mod tests { src.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(); + println!("{:?}", got); // deserialize let mut rdr = Reader::new(quick_xml::NsReader::from_reader(got.as_bytes())) @@ -141,4 +169,31 @@ mod tests { }) .await; } + + #[tokio::test] + async fn prop_req() { + serialize_deserialize(&dav::PropName::<All>(vec![ + dav::PropertyRequest::Extension(realization::PropertyRequest::Sync( + PropertyRequest::SyncToken(SyncTokenRequest::InitialSync), + )), + ])) + .await; + } + + #[tokio::test] + async fn prop_val() { + serialize_deserialize(&dav::PropValue::<All>(vec![ + dav::Property::Extension(realization::Property::Sync(Property::SyncToken(SyncToken( + "http://example.com/ns/sync/1232".into(), + )))), + dav::Property::Extension(realization::Property::Vers( + vers::Property::SupportedReportSet(vec![vers::SupportedReport( + vers::ReportName::Extension(realization::ReportTypeName::Sync( + ReportTypeName::SyncCollection, + )), + )]), + )), + ])) + .await; + } } diff --git a/aero-dav/src/synctypes.rs b/aero-dav/src/synctypes.rs index a2f40bd..c127962 100644 --- a/aero-dav/src/synctypes.rs +++ b/aero-dav/src/synctypes.rs @@ -4,8 +4,21 @@ use super::versioningtypes as vers; // RFC 6578 // https://datatracker.ietf.org/doc/html/rfc6578 -//@FIXME add SyncTokenRequest to PropertyRequest -//@FIXME add SyncToken to Property +#[derive(Debug, PartialEq, Clone)] +pub enum PropertyRequest { + SyncToken(SyncTokenRequest), +} + +#[derive(Debug, PartialEq, Clone)] +pub enum Property { + SyncToken(SyncToken), +} + +#[derive(Debug, PartialEq, Clone)] +pub enum ReportTypeName { + SyncCollection, +} + //@FIXME add SyncToken to Multistatus /// Name: sync-collection diff --git a/aero-dav/src/types.rs b/aero-dav/src/types.rs index 6039a26..92c63e0 100644 --- a/aero-dav/src/types.rs +++ b/aero-dav/src/types.rs @@ -12,6 +12,7 @@ pub trait Extension: std::fmt::Debug + PartialEq + Clone { type PropertyRequest: xml::Node<Self::PropertyRequest>; type ResourceType: xml::Node<Self::ResourceType>; type ReportType: xml::Node<Self::ReportType>; + type ReportTypeName: xml::Node<Self::ReportTypeName>; } /// 14.1. activelock XML Element diff --git a/aero-dav/src/versioningdecoder.rs b/aero-dav/src/versioningdecoder.rs index 4816cf1..9e58d8c 100644 --- a/aero-dav/src/versioningdecoder.rs +++ b/aero-dav/src/versioningdecoder.rs @@ -3,12 +3,87 @@ use super::types as dav; use super::versioningtypes::*; use super::xml::{IRead, QRead, Reader, DAV_URN}; +// -- extensions --- +impl QRead<PropertyRequest> for PropertyRequest { + async fn qread(xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> { + if xml + .maybe_open(DAV_URN, "supported-report-set") + .await? + .is_some() + { + xml.close().await?; + return Ok(Self::SupportedReportSet); + } + return Err(ParsingError::Recoverable); + } +} + +impl<E: dav::Extension> QRead<Property<E>> for Property<E> { + async fn qread(xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> { + if xml + .maybe_open(DAV_URN, "supported-report-set") + .await? + .is_some() + { + let supported_reports = xml.collect().await?; + xml.close().await?; + return Ok(Property::SupportedReportSet(supported_reports)); + } + Err(ParsingError::Recoverable) + } +} + +impl<E: dav::Extension> QRead<SupportedReport<E>> for SupportedReport<E> { + async fn qread(xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> { + xml.open(DAV_URN, "supported-report").await?; + let r = xml.find().await?; + xml.close().await?; + Ok(SupportedReport(r)) + } +} + +impl<E: dav::Extension> QRead<ReportName<E>> for ReportName<E> { + async fn qread(xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> { + xml.open(DAV_URN, "report").await?; + + let final_result = if xml.maybe_open(DAV_URN, "version-tree").await?.is_some() { + xml.close().await?; + Ok(ReportName::VersionTree) + } else if xml.maybe_open(DAV_URN, "expand-property").await?.is_some() { + xml.close().await?; + Ok(ReportName::ExpandProperty) + } else { + let x = match xml.maybe_find().await? { + Some(v) => v, + None => return Err(ParsingError::MissingChild), + }; + Ok(ReportName::Extension(x)) + //E::ReportTypeName::qread(xml).await.map(ReportName::Extension) + }; + + xml.close().await?; + final_result + } +} + impl<E: dav::Extension> QRead<Report<E>> for Report<E> { async fn qread(xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> { - //@FIXME VersionTree not implemented - //@FIXME ExpandTree not implemented + xml.open(DAV_URN, "report").await?; - E::ReportType::qread(xml).await.map(Report::Extension) + let final_result = if xml.maybe_open(DAV_URN, "version-tree").await?.is_some() { + xml.close().await?; + tracing::warn!("version-tree is not implemented, skipping"); + Ok(Report::VersionTree) + } else if xml.maybe_open(DAV_URN, "expand-property").await?.is_some() { + xml.close().await?; + tracing::warn!("expand-property is not implemented, skipping"); + Ok(Report::ExpandProperty) + } else { + E::ReportType::qread(xml).await.map(Report::Extension) + }; + + xml.close().await?; + final_result } } diff --git a/aero-dav/src/versioningencoder.rs b/aero-dav/src/versioningencoder.rs index bd40f1b..c061f07 100644 --- a/aero-dav/src/versioningencoder.rs +++ b/aero-dav/src/versioningencoder.rs @@ -5,6 +5,67 @@ use super::types::Extension; use super::versioningtypes::*; use super::xml::{IWrite, QWrite, Writer}; +// --- extensions to PROP +impl QWrite for PropertyRequest { + async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> { + match self { + Self::SupportedReportSet => { + let start = xml.create_dav_element("supported-report-set"); + xml.q.write_event_async(Event::Empty(start)).await + } + } + } +} + +impl<E: Extension> QWrite for Property<E> { + async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> { + match self { + Self::SupportedReportSet(set) => { + let start = xml.create_dav_element("supported-report-set"); + let end = start.to_end(); + + xml.q.write_event_async(Event::Start(start.clone())).await?; + for v in set.iter() { + v.qwrite(xml).await?; + } + xml.q.write_event_async(Event::End(end)).await + } + } + } +} + +impl<E: Extension> QWrite for SupportedReport<E> { + async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> { + let start = xml.create_dav_element("supported-report"); + let end = start.to_end(); + xml.q.write_event_async(Event::Start(start.clone())).await?; + self.0.qwrite(xml).await?; + xml.q.write_event_async(Event::End(end)).await + } +} + +impl<E: Extension> QWrite for ReportName<E> { + async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> { + let start = xml.create_dav_element("report"); + let end = start.to_end(); + + xml.q.write_event_async(Event::Start(start.clone())).await?; + match self { + Self::VersionTree => { + let start = xml.create_dav_element("version-tree"); + xml.q.write_event_async(Event::Empty(start)).await?; + } + Self::ExpandProperty => { + let start = xml.create_dav_element("expand-property"); + xml.q.write_event_async(Event::Empty(start)).await?; + } + Self::Extension(ext) => ext.qwrite(xml).await?, + }; + xml.q.write_event_async(Event::End(end)).await + } +} + +// --- root REPORT object --- impl<E: Extension> QWrite for Report<E> { async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> { match self { @@ -15,6 +76,7 @@ impl<E: Extension> QWrite for Report<E> { } } +// --- limit REPORT parameter --- impl QWrite for Limit { async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> { let start = xml.create_dav_element("limit"); diff --git a/aero-dav/src/versioningtypes.rs b/aero-dav/src/versioningtypes.rs index ba64b05..1f8d1cf 100644 --- a/aero-dav/src/versioningtypes.rs +++ b/aero-dav/src/versioningtypes.rs @@ -22,6 +22,26 @@ use super::types as dav; // ANY value: a report element type #[derive(Debug, PartialEq, Clone)] +pub enum PropertyRequest { + SupportedReportSet, +} + +#[derive(Debug, PartialEq, Clone)] +pub enum Property<E: dav::Extension> { + SupportedReportSet(Vec<SupportedReport<E>>), +} + +#[derive(Debug, PartialEq, Clone)] +pub struct SupportedReport<E: dav::Extension>(pub ReportName<E>); + +#[derive(Debug, PartialEq, Clone)] +pub enum ReportName<E: dav::Extension> { + VersionTree, + ExpandProperty, + Extension(E::ReportTypeName), +} + +#[derive(Debug, PartialEq, Clone)] pub enum Report<E: dav::Extension> { VersionTree, // Not yet implemented ExpandProperty, // Not yet implemented |