diff --git a/src/dav/calencoder.rs b/src/dav/calencoder.rs index d030aa1..114eee9 100644 --- a/src/dav/calencoder.rs +++ b/src/dav/calencoder.rs @@ -813,8 +813,9 @@ mod tests { &dav::Multistatus:: { responses: vec![ dav::Response { - href: dav::Href("http://cal.example.com/bernard/work/abcd2.ics".into()), - status_or_propstat: dav::StatusOrPropstat::PropStat(vec![dav::PropStat { + status_or_propstat: dav::StatusOrPropstat::PropStat( + dav::Href("http://cal.example.com/bernard/work/abcd2.ics".into()), + vec![dav::PropStat { prop: dav::AnyProp::Value(dav::PropValue(vec![ dav::Property::GetEtag("\"fffff-abcd2\"".into()), dav::Property::Extension(Property::CalendarData(CalendarDataPayload { @@ -825,14 +826,16 @@ mod tests { status: dav::Status(http::status::StatusCode::OK), error: None, responsedescription: None, - }]), + }] + ), location: None, error: None, responsedescription: None, }, dav::Response { - href: dav::Href("http://cal.example.com/bernard/work/abcd3.ics".into()), - status_or_propstat: dav::StatusOrPropstat::PropStat(vec![dav::PropStat { + status_or_propstat: dav::StatusOrPropstat::PropStat( + dav::Href("http://cal.example.com/bernard/work/abcd3.ics".into()), + vec![dav::PropStat { prop: dav::AnyProp::Value(dav::PropValue(vec![ dav::Property::GetEtag("\"fffff-abcd3\"".into()), dav::Property::Extension(Property::CalendarData(CalendarDataPayload{ @@ -843,7 +846,8 @@ mod tests { status: dav::Status(http::status::StatusCode::OK), error: None, responsedescription: None, - }]), + }] + ), location: None, error: None, responsedescription: None, diff --git a/src/dav/decoder.rs b/src/dav/decoder.rs index 042a608..66c0839 100644 --- a/src/dav/decoder.rs +++ b/src/dav/decoder.rs @@ -84,7 +84,29 @@ impl QRead> for PropertyUpdate { } /// Generic response -//@TODO Multistatus +impl QRead> for Multistatus { + async fn qread(xml: &mut Reader) -> Result, ParsingError> { + xml.tag_start(DAV_URN, "multistatus").await?; + let mut responses = Vec::new(); + let mut responsedescription = None; + + loop { + if let Some(v) = Response::qread(xml).await? { + responses.push(v); + } else if let Some(v) = ResponseDescription::qread(xml).await? { + responsedescription = Some(v); + } else { + match xml.peek() { + Event::End(_) => break, + _ => xml.skip().await?, + }; + } + } + + xml.tag_stop(DAV_URN, "multistatus").await?; + Ok(Some(Multistatus { responses, responsedescription })) + } +} // LOCK REQUEST impl QRead for LockInfo { @@ -159,6 +181,27 @@ impl QRead> for Error { // ---- INNER XML +impl QRead> for Response { + async fn qread(xml: &mut Reader) -> Result, ParsingError> { + if xml.maybe_tag_start(DAV_URN, "response").await?.is_none() { + return Ok(None) + } + + unimplemented!(); + } +} + +impl QRead for ResponseDescription { + async fn qread(xml: &mut Reader) -> Result, ParsingError> { + if xml.maybe_tag_start(DAV_URN, "responsedescription").await?.is_none() { + return Ok(None) + } + let cnt = xml.tag_string().await?; + xml.tag_stop(DAV_URN, "responsedescription").await?; + Ok(Some(ResponseDescription(cnt))) + } +} + impl QRead> for PropertyUpdateItem { async fn qread(xml: &mut Reader) -> Result, ParsingError> { if let Some(rm) = Remove::qread(xml).await? { diff --git a/src/dav/encoder.rs b/src/dav/encoder.rs index ec937c6..5736217 100644 --- a/src/dav/encoder.rs +++ b/src/dav/encoder.rs @@ -186,7 +186,6 @@ impl QWrite for Response { let end = start.to_end(); xml.q.write_event_async(Event::Start(start.clone())).await?; - self.href.qwrite(xml).await?; self.status_or_propstat.qwrite(xml).await?; if let Some(error) = &self.error { error.qwrite(xml).await?; @@ -204,8 +203,14 @@ impl QWrite for Response { impl QWrite for StatusOrPropstat { async fn qwrite(&self, xml: &mut Writer) -> Result<(), QError> { match self { - Self::Status(status) => status.qwrite(xml).await, - Self::PropStat(propstat_list) => { + Self::Status(many_href, status) => { + for href in many_href.iter() { + href.qwrite(xml).await?; + } + status.qwrite(xml).await + }, + Self::PropStat(href, propstat_list) => { + href.qwrite(xml).await?; for propstat in propstat_list.iter() { propstat.qwrite(xml).await?; } @@ -728,39 +733,43 @@ mod tests { &Multistatus:: { responses: vec![ Response { - href: Href("http://www.example.com/container/".into()), - status_or_propstat: StatusOrPropstat::PropStat(vec![PropStat { - prop: AnyProp::Name(PropName(vec![ - PropertyRequest::CreationDate, - PropertyRequest::DisplayName, - PropertyRequest::ResourceType, - PropertyRequest::SupportedLock, - ])), - status: Status(http::status::StatusCode::OK), - error: None, - responsedescription: None, - }]), + status_or_propstat: StatusOrPropstat::PropStat( + Href("http://www.example.com/container/".into()), + vec![PropStat { + prop: AnyProp::Name(PropName(vec![ + PropertyRequest::CreationDate, + PropertyRequest::DisplayName, + PropertyRequest::ResourceType, + PropertyRequest::SupportedLock, + ])), + status: Status(http::status::StatusCode::OK), + error: None, + responsedescription: None, + }] + ), error: None, responsedescription: None, location: None, }, Response { - href: Href("http://www.example.com/container/front.html".into()), - status_or_propstat: StatusOrPropstat::PropStat(vec![PropStat { - prop: AnyProp::Name(PropName(vec![ - PropertyRequest::CreationDate, - PropertyRequest::DisplayName, - PropertyRequest::GetContentLength, - PropertyRequest::GetContentType, - PropertyRequest::GetEtag, - PropertyRequest::GetLastModified, - PropertyRequest::ResourceType, - PropertyRequest::SupportedLock, - ])), - status: Status(http::status::StatusCode::OK), - error: None, - responsedescription: None, - }]), + status_or_propstat: StatusOrPropstat::PropStat( + Href("http://www.example.com/container/front.html".into()), + vec![PropStat { + prop: AnyProp::Name(PropName(vec![ + PropertyRequest::CreationDate, + PropertyRequest::DisplayName, + PropertyRequest::GetContentLength, + PropertyRequest::GetContentType, + PropertyRequest::GetEtag, + PropertyRequest::GetLastModified, + PropertyRequest::ResourceType, + PropertyRequest::SupportedLock, + ])), + status: Status(http::status::StatusCode::OK), + error: None, + responsedescription: None, + } + ]), error: None, responsedescription: None, location: None, @@ -825,8 +834,9 @@ mod tests { &Multistatus:: { responses: vec![ Response { - href: Href("/container/".into()), - status_or_propstat: StatusOrPropstat::PropStat(vec![PropStat { + status_or_propstat: StatusOrPropstat::PropStat( + Href("/container/".into()), + vec![PropStat { prop: AnyProp::Value(PropValue(vec![ Property::CreationDate(FixedOffset::west_opt(8 * 3600) .unwrap() @@ -848,14 +858,16 @@ mod tests { status: Status(http::status::StatusCode::OK), error: None, responsedescription: None, - }]), + }] + ), error: None, responsedescription: None, location: None, }, Response { - href: Href("/container/front.html".into()), - status_or_propstat: StatusOrPropstat::PropStat(vec![PropStat { + status_or_propstat: StatusOrPropstat::PropStat( + Href("/container/front.html".into()), + vec![PropStat { prop: AnyProp::Value(PropValue(vec![ Property::CreationDate(FixedOffset::west_opt(8 * 3600) .unwrap() @@ -884,7 +896,8 @@ mod tests { status: Status(http::status::StatusCode::OK), error: None, responsedescription: None, - }]), + }] + ), error: None, responsedescription: None, location: None, @@ -1018,8 +1031,10 @@ mod tests { let got = serialize( &Multistatus:: { responses: vec![Response { - href: Href("http://www.example.com/container/resource3".into()), - status_or_propstat: StatusOrPropstat::Status(Status(http::status::StatusCode::from_u16(423).unwrap())), + status_or_propstat: StatusOrPropstat::Status( + vec![Href("http://www.example.com/container/resource3".into())], + Status(http::status::StatusCode::from_u16(423).unwrap()) + ), error: Some(Error(vec![Violation::LockTokenSubmitted(vec![])])), responsedescription: None, location: None, diff --git a/src/dav/types.rs b/src/dav/types.rs index 08c0bc6..b3842de 100644 --- a/src/dav/types.rs +++ b/src/dav/types.rs @@ -516,15 +516,19 @@ pub struct Remove(pub PropName); /// /// +/// +/// --- rewritten as --- +/// #[derive(Debug, PartialEq)] pub enum StatusOrPropstat { - Status(Status), - PropStat(Vec>), + // One status, multiple hrefs... + Status(Vec, Status), + // A single href, multiple properties... + PropStat(Href, Vec>), } #[derive(Debug, PartialEq)] pub struct Response { - pub href: Href, // It's wrong according to the spec, but I don't understand why there is an href* pub status_or_propstat: StatusOrPropstat, pub error: Option>, pub responsedescription: Option,