diff options
-rw-r--r-- | src/dav/encoder.rs | 105 | ||||
-rw-r--r-- | src/dav/types.rs | 18 |
2 files changed, 81 insertions, 42 deletions
diff --git a/src/dav/encoder.rs b/src/dav/encoder.rs index 9e907dc..4a9bcf4 100644 --- a/src/dav/encoder.rs +++ b/src/dav/encoder.rs @@ -72,21 +72,20 @@ impl<C: Context> QuickWritable<C> for PropFind<C> { include.write(xml, ctx.child()).await?; } }, - Self::Prop(many_propreq) => { - let start = ctx.create_dav_element("prop"); - let end = start.to_end(); - - xml.write_event_async(Event::Start(start.clone())).await?; - for propreq in many_propreq.iter() { - propreq.write(xml, ctx.child()).await?; - } - xml.write_event_async(Event::End(end)).await?; - }, + Self::Prop(propname) => propname.write(xml, ctx.child()).await?, } xml.write_event_async(Event::End(end)).await } } +/// PROPPATCH REQUEST +impl<C: Context> QuickWritable<C> for PropertyUpdate<C> { + async fn write(&self, xml: &mut Writer<impl AsyncWrite+Unpin>, ctx: C) -> Result<(), QError> { + unimplemented!(); + } +} + + /// PROPFIND RESPONSE, PROPPATCH RESPONSE, COPY RESPONSE, MOVE RESPONSE /// DELETE RESPONSE, impl<C: Context> QuickWritable<C> for Multistatus<C> { @@ -124,31 +123,43 @@ impl<C: Context> QuickWritable<C> for LockInfo { } /// SOME LOCK RESPONSES -impl<C: Context> QuickWritable<C> for Prop<C> { +impl<C: Context> QuickWritable<C> for PropValue<C> { async fn write(&self, xml: &mut Writer<impl AsyncWrite+Unpin>, ctx: C) -> Result<(), QError> { let start = ctx.create_dav_element("prop"); let end = start.to_end(); xml.write_event_async(Event::Start(start.clone())).await?; + for propval in &self.0 { + propval.write(xml, ctx.child()).await?; + } + xml.write_event_async(Event::End(end)).await + } +} + +// --- XML inner elements +impl<C: Context> QuickWritable<C> for AnyProp<C> { + async fn write(&self, xml: &mut Writer<impl AsyncWrite+Unpin>, ctx: C) -> Result<(), QError> { match self { - Self::Name(many_names) => { - for propname in many_names { - propname.write(xml, ctx.child()).await?; - } - }, - Self::Value(many_values) => { - for propval in many_values { - propval.write(xml, ctx.child()).await?; - } - } - }; - xml.write_event_async(Event::End(end)).await?; + Self::Name(propname) => propname.write(xml, ctx).await, + Self::Value(propval) => propval.write(xml, ctx).await, + } + } +} - Ok(()) +impl<C: Context> QuickWritable<C> for PropName<C> { + async fn write(&self, xml: &mut Writer<impl AsyncWrite+Unpin>, ctx: C) -> Result<(), QError> { + let start = ctx.create_dav_element("prop"); + let end = start.to_end(); + + xml.write_event_async(Event::Start(start.clone())).await?; + for propname in &self.0 { + propname.write(xml, ctx.child()).await?; + } + xml.write_event_async(Event::End(end)).await } } -// --- XML inner elements + impl<C: Context> QuickWritable<C> for Href { async fn write(&self, xml: &mut Writer<impl AsyncWrite+Unpin>, ctx: C) -> Result<(), QError> { let start = ctx.create_dav_element("href"); @@ -411,7 +422,7 @@ impl<C: Context> QuickWritable<C> for Include<C> { impl<C: Context> QuickWritable<C> for PropertyRequest<C> { async fn write(&self, xml: &mut Writer<impl AsyncWrite+Unpin>, ctx: C) -> Result<(), QError> { use PropertyRequest::*; - let mut atom = (async |c| xml.write_event_async(Event::Empty(ctx.create_dav_element(c))).await); + let mut atom = async |c| xml.write_event_async(Event::Empty(ctx.create_dav_element(c))).await; match self { CreationDate => atom("creationdate").await, @@ -724,12 +735,12 @@ mod tests { Response { href: Href("http://www.example.com/container/".into()), status_or_propstat: StatusOrPropstat::PropStat(vec![PropStat { - prop: Prop::Name(vec![ + prop: AnyProp::Name(PropName(vec![ PropertyRequest::CreationDate, PropertyRequest::DisplayName, PropertyRequest::ResourceType, PropertyRequest::SupportedLock, - ]), + ])), status: Status(http::status::StatusCode::OK), error: None, responsedescription: None, @@ -741,7 +752,7 @@ mod tests { Response { href: Href("http://www.example.com/container/front.html".into()), status_or_propstat: StatusOrPropstat::PropStat(vec![PropStat { - prop: Prop::Name(vec![ + prop: AnyProp::Name(PropName(vec![ PropertyRequest::CreationDate, PropertyRequest::DisplayName, PropertyRequest::GetContentLength, @@ -750,7 +761,7 @@ mod tests { PropertyRequest::GetLastModified, PropertyRequest::ResourceType, PropertyRequest::SupportedLock, - ]), + ])), status: Status(http::status::StatusCode::OK), error: None, responsedescription: None, @@ -823,7 +834,7 @@ mod tests { Response { href: Href("/container/".into()), status_or_propstat: StatusOrPropstat::PropStat(vec![PropStat { - prop: Prop::Value(vec![ + prop: AnyProp::Value(PropValue(vec![ Property::CreationDate(FixedOffset::west_opt(8 * 3600) .unwrap() .with_ymd_and_hms(1997, 12, 1, 17, 42, 21) @@ -840,7 +851,7 @@ mod tests { locktype: LockType::Write, }, ]), - ]), + ])), status: Status(http::status::StatusCode::OK), error: None, responsedescription: None, @@ -852,7 +863,7 @@ mod tests { Response { href: Href("/container/front.html".into()), status_or_propstat: StatusOrPropstat::PropStat(vec![PropStat { - prop: Prop::Value(vec![ + prop: AnyProp::Value(PropValue(vec![ Property::CreationDate(FixedOffset::west_opt(8 * 3600) .unwrap() .with_ymd_and_hms(1997, 12, 1, 18, 27, 21) @@ -876,7 +887,7 @@ mod tests { locktype: LockType::Write, }, ]), - ]), + ])), status: Status(http::status::StatusCode::OK), error: None, responsedescription: None, @@ -981,4 +992,30 @@ mod tests { assert_eq!(&got, expected, "\n---GOT---\n{got}\n---EXP---\n{expected}\n"); } + + #[tokio::test] + async fn rfc_propertyupdate() { + let got = serialize( + NoExtension { root: true }, + &PropertyUpdate(vec![ + PropertyUpdateItem::Set(Set(PropValue(vec![ ]))), + PropertyUpdateItem::Remove(Remove(PropName(vec![]))), + ]), + ).await; + + let expected = r#"<D:propertyupdate xmlns:D="DAV:"> + <D:set> + <D:prop> + <D:getcontentlanguage>fr-FR</D:getcontentlanguage> + </D:prop> + </D:set> + <D:remove> + <D:prop> + <D:displayname/> + </D:prop> + </D:remove> +</D:propertyupdate>"#; + + assert_eq!(&got, expected, "\n---GOT---\n{got}\n---EXP---\n{expected}\n"); + } } diff --git a/src/dav/types.rs b/src/dav/types.rs index 55e9e86..4487de7 100644 --- a/src/dav/types.rs +++ b/src/dav/types.rs @@ -372,10 +372,12 @@ pub struct Owner { /// text or mixed content. /// /// <!ELEMENT prop ANY > -pub enum Prop<T: Extension> { - Name(Vec<PropertyRequest<T>>), - Value(Vec<Property<T>>), +pub enum AnyProp<T: Extension> { + Name(PropName<T>), + Value(PropValue<T>), } +pub struct PropName<T: Extension>(pub Vec<PropertyRequest<T>>); +pub struct PropValue<T: Extension>(pub Vec<Property<T>>); /// 14.19. propertyupdate XML Element /// @@ -387,7 +389,7 @@ pub enum Prop<T: Extension> { /// required to modify the properties on the resource. /// /// <!ELEMENT propertyupdate (remove | set)+ > -pub struct PropertyUpdate<T: Extension>(Vec<PropertyUpdateItem<T>>); +pub struct PropertyUpdate<T: Extension>(pub Vec<PropertyUpdateItem<T>>); pub enum PropertyUpdateItem<T: Extension> { Remove(Remove<T>), Set(Set<T>), @@ -430,7 +432,7 @@ pub enum PropertyUpdateItem<T: Extension> { pub enum PropFind<T: Extension> { PropName, AllProp(Option<Include<T>>), - Prop(Vec<PropertyRequest<T>>), + Prop(PropName<T>), } @@ -451,7 +453,7 @@ pub enum PropFind<T: Extension> { /// /// <!ELEMENT propstat (prop, status, error?, responsedescription?) > pub struct PropStat<T: Extension> { - pub prop: Prop<T>, + pub prop: AnyProp<T>, pub status: Status, pub error: Option<Error<T>>, pub responsedescription: Option<ResponseDescription>, @@ -470,7 +472,7 @@ pub struct PropStat<T: Extension> { /// the names of properties to be removed are required. /// /// <!ELEMENT remove (prop) > -pub struct Remove<T: Extension>(pub Prop<T>); +pub struct Remove<T: Extension>(pub PropName<T>); /// 14.24. response XML Element /// @@ -535,7 +537,7 @@ pub struct ResponseDescription(pub String); /// property, and MUST be subsequently retrievable using PROPFIND. /// /// <!ELEMENT set (prop) > -pub struct Set<T: Extension>(pub Prop<T>); +pub struct Set<T: Extension>(pub PropValue<T>); /// 14.27. shared XML Element /// |