Rework webdav types
This commit is contained in:
parent
2e7ffd4f4c
commit
d0c47b93fe
8 changed files with 226 additions and 146 deletions
|
@ -3,7 +3,7 @@ use chrono::NaiveDateTime;
|
|||
|
||||
use super::types as dav;
|
||||
use super::caltypes::*;
|
||||
use super::xml::{QRead, IRead, Reader, Node, DAV_URN, CAL_URN};
|
||||
use super::xml::{QRead, IRead, Reader, DAV_URN, CAL_URN};
|
||||
use super::error::ParsingError;
|
||||
|
||||
// ---- ROOT ELEMENTS ---
|
||||
|
@ -16,7 +16,7 @@ impl<E: dav::Extension> QRead<MkCalendar<E>> for MkCalendar<E> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<E: dav::Extension, N: Node<N>> QRead<MkCalendarResponse<E,N>> for MkCalendarResponse<E,N> {
|
||||
impl<E: dav::Extension> QRead<MkCalendarResponse<E>> for MkCalendarResponse<E> {
|
||||
async fn qread(xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> {
|
||||
xml.open(CAL_URN, "mkcalendar-response").await?;
|
||||
let propstats = xml.collect().await?;
|
||||
|
@ -162,57 +162,57 @@ impl QRead<Violation> for Violation {
|
|||
|
||||
impl QRead<Property> for Property {
|
||||
async fn qread(xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> {
|
||||
if xml.maybe_open(CAL_URN, "calendar-description").await?.is_some() {
|
||||
if xml.maybe_open_start(CAL_URN, "calendar-description").await?.is_some() {
|
||||
let lang = xml.prev_attr("xml:lang");
|
||||
let text = xml.tag_string().await?;
|
||||
xml.close().await?;
|
||||
return Ok(Property::CalendarDescription { lang, text })
|
||||
}
|
||||
|
||||
if xml.maybe_open(CAL_URN, "calendar-timezone").await?.is_some() {
|
||||
if xml.maybe_open_start(CAL_URN, "calendar-timezone").await?.is_some() {
|
||||
let tz = xml.tag_string().await?;
|
||||
xml.close().await?;
|
||||
return Ok(Property::CalendarTimezone(tz))
|
||||
}
|
||||
|
||||
if xml.maybe_open(CAL_URN, "supported-calendar-component-set").await?.is_some() {
|
||||
if xml.maybe_open_start(CAL_URN, "supported-calendar-component-set").await?.is_some() {
|
||||
let comp = xml.collect().await?;
|
||||
xml.close().await?;
|
||||
return Ok(Property::SupportedCalendarComponentSet(comp))
|
||||
}
|
||||
|
||||
if xml.maybe_open(CAL_URN, "supported-calendar-data").await?.is_some() {
|
||||
if xml.maybe_open_start(CAL_URN, "supported-calendar-data").await?.is_some() {
|
||||
let mime = xml.collect().await?;
|
||||
xml.close().await?;
|
||||
return Ok(Property::SupportedCalendarData(mime))
|
||||
}
|
||||
|
||||
if xml.maybe_open(CAL_URN, "max-resource-size").await?.is_some() {
|
||||
if xml.maybe_open_start(CAL_URN, "max-resource-size").await?.is_some() {
|
||||
let sz = xml.tag_string().await?.parse::<u64>()?;
|
||||
xml.close().await?;
|
||||
return Ok(Property::MaxResourceSize(sz))
|
||||
}
|
||||
|
||||
if xml.maybe_open(CAL_URN, "max-date-time").await?.is_some() {
|
||||
if xml.maybe_open_start(CAL_URN, "max-date-time").await?.is_some() {
|
||||
let dtstr = xml.tag_string().await?;
|
||||
let dt = NaiveDateTime::parse_from_str(dtstr.as_str(), ICAL_DATETIME_FMT)?.and_utc();
|
||||
xml.close().await?;
|
||||
return Ok(Property::MaxDateTime(dt))
|
||||
}
|
||||
|
||||
if xml.maybe_open(CAL_URN, "max-instances").await?.is_some() {
|
||||
if xml.maybe_open_start(CAL_URN, "max-instances").await?.is_some() {
|
||||
let sz = xml.tag_string().await?.parse::<u64>()?;
|
||||
xml.close().await?;
|
||||
return Ok(Property::MaxInstances(sz))
|
||||
}
|
||||
|
||||
if xml.maybe_open(CAL_URN, "max-attendees-per-instance").await?.is_some() {
|
||||
if xml.maybe_open_start(CAL_URN, "max-attendees-per-instance").await?.is_some() {
|
||||
let sz = xml.tag_string().await?.parse::<u64>()?;
|
||||
xml.close().await?;
|
||||
return Ok(Property::MaxAttendeesPerInstance(sz))
|
||||
}
|
||||
|
||||
if xml.maybe_open(CAL_URN, "supported-collation-set").await?.is_some() {
|
||||
if xml.maybe_open_start(CAL_URN, "supported-collation-set").await?.is_some() {
|
||||
let cols = xml.collect().await?;
|
||||
xml.close().await?;
|
||||
return Ok(Property::SupportedCollationSet(cols))
|
||||
|
@ -759,6 +759,7 @@ mod tests {
|
|||
use super::*;
|
||||
use chrono::{Utc, TimeZone};
|
||||
use crate::realization::Calendar;
|
||||
use crate::xml::Node;
|
||||
//use quick_reader::NsReader;
|
||||
|
||||
async fn deserialize<T: Node<T>>(src: &str) -> T {
|
||||
|
@ -933,19 +934,19 @@ END:VCALENDAR]]></C:calendar-timezone>
|
|||
|
||||
#[tokio::test]
|
||||
async fn rfc_calendar_query_res() {
|
||||
let expected = dav::Multistatus::<Calendar, dav::PropValue<Calendar>> {
|
||||
let expected = dav::Multistatus::<Calendar> {
|
||||
responses: vec![
|
||||
dav::Response {
|
||||
status_or_propstat: dav::StatusOrPropstat::PropStat(
|
||||
dav::Href("http://cal.example.com/bernard/work/abcd2.ics".into()),
|
||||
vec![
|
||||
dav::PropStat {
|
||||
prop: dav::PropValue(vec![
|
||||
dav::Property::GetEtag("\"fffff-abcd2\"".into()),
|
||||
dav::Property::Extension(Property::CalendarData(CalendarDataPayload {
|
||||
prop: dav::AnyProp(vec![
|
||||
dav::AnyProperty::Value(dav::Property::GetEtag("\"fffff-abcd2\"".into())),
|
||||
dav::AnyProperty::Value(dav::Property::Extension(Property::CalendarData(CalendarDataPayload {
|
||||
mime: None,
|
||||
payload: "BEGIN:VCALENDAR".into(),
|
||||
})),
|
||||
}))),
|
||||
]),
|
||||
status: dav::Status(http::status::StatusCode::OK),
|
||||
error: None,
|
||||
|
@ -962,12 +963,12 @@ END:VCALENDAR]]></C:calendar-timezone>
|
|||
dav::Href("http://cal.example.com/bernard/work/abcd3.ics".into()),
|
||||
vec![
|
||||
dav::PropStat {
|
||||
prop: dav::PropValue(vec![
|
||||
dav::Property::GetEtag("\"fffff-abcd3\"".into()),
|
||||
dav::Property::Extension(Property::CalendarData(CalendarDataPayload {
|
||||
prop: dav::AnyProp(vec![
|
||||
dav::AnyProperty::Value(dav::Property::GetEtag("\"fffff-abcd3\"".into())),
|
||||
dav::AnyProperty::Value(dav::Property::Extension(Property::CalendarData(CalendarDataPayload {
|
||||
mime: None,
|
||||
payload: "BEGIN:VCALENDAR".into(),
|
||||
})),
|
||||
}))),
|
||||
]),
|
||||
status: dav::Status(http::status::StatusCode::OK),
|
||||
error: None,
|
||||
|
@ -1008,7 +1009,7 @@ END:VCALENDAR]]></C:calendar-timezone>
|
|||
</D:multistatus>
|
||||
"#;
|
||||
|
||||
let got = deserialize::<dav::Multistatus<Calendar,dav::PropValue<Calendar>>>(src).await;
|
||||
let got = deserialize::<dav::Multistatus<Calendar>>(src).await;
|
||||
assert_eq!(got, expected)
|
||||
}
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ impl<E: Extension> QWrite for MkCalendar<E> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<E: Extension, N: Node<N>> QWrite for MkCalendarResponse<E,N> {
|
||||
impl<E: Extension> QWrite for MkCalendarResponse<E> {
|
||||
async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> {
|
||||
let start = xml.create_cal_element("mkcalendar-response");
|
||||
let end = start.to_end();
|
||||
|
@ -828,18 +828,18 @@ mod tests {
|
|||
#[tokio::test]
|
||||
async fn rfc_calendar_query1_res() {
|
||||
let got = serialize(
|
||||
&dav::Multistatus::<Calendar,dav::PropValue<Calendar>> {
|
||||
&dav::Multistatus::<Calendar> {
|
||||
responses: vec![
|
||||
dav::Response {
|
||||
status_or_propstat: dav::StatusOrPropstat::PropStat(
|
||||
dav::Href("http://cal.example.com/bernard/work/abcd2.ics".into()),
|
||||
vec![dav::PropStat {
|
||||
prop: dav::PropValue(vec![
|
||||
dav::Property::GetEtag("\"fffff-abcd2\"".into()),
|
||||
dav::Property::Extension(Property::CalendarData(CalendarDataPayload {
|
||||
prop: dav::AnyProp(vec![
|
||||
dav::AnyProperty::Value(dav::Property::GetEtag("\"fffff-abcd2\"".into())),
|
||||
dav::AnyProperty::Value(dav::Property::Extension(Property::CalendarData(CalendarDataPayload {
|
||||
mime: None,
|
||||
payload: "PLACEHOLDER".into()
|
||||
})),
|
||||
}))),
|
||||
]),
|
||||
status: dav::Status(http::status::StatusCode::OK),
|
||||
error: None,
|
||||
|
@ -854,12 +854,12 @@ mod tests {
|
|||
status_or_propstat: dav::StatusOrPropstat::PropStat(
|
||||
dav::Href("http://cal.example.com/bernard/work/abcd3.ics".into()),
|
||||
vec![dav::PropStat {
|
||||
prop: dav::PropValue(vec![
|
||||
dav::Property::GetEtag("\"fffff-abcd3\"".into()),
|
||||
dav::Property::Extension(Property::CalendarData(CalendarDataPayload{
|
||||
prop: dav::AnyProp(vec![
|
||||
dav::AnyProperty::Value(dav::Property::GetEtag("\"fffff-abcd3\"".into())),
|
||||
dav::AnyProperty::Value(dav::Property::Extension(Property::CalendarData(CalendarDataPayload{
|
||||
mime: None,
|
||||
payload: "PLACEHOLDER".into(),
|
||||
})),
|
||||
}))),
|
||||
]),
|
||||
status: dav::Status(http::status::StatusCode::OK),
|
||||
error: None,
|
||||
|
|
|
@ -31,7 +31,7 @@ pub const ICAL_DATETIME_FMT: &str = "%Y%m%dT%H%M%SZ";
|
|||
/// ```xmlschema
|
||||
/// <!ELEMENT mkcalendar (DAV:set)>
|
||||
/// ```
|
||||
#[derive(Debug, PartialEq)]
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub struct MkCalendar<E: dav::Extension>(pub dav::Set<E>);
|
||||
|
||||
|
||||
|
@ -48,8 +48,8 @@ pub struct MkCalendar<E: dav::Extension>(pub dav::Set<E>);
|
|||
/// Definition:
|
||||
///
|
||||
/// <!ELEMENT mkcol-response (propstat+)>
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct MkCalendarResponse<E: dav::Extension, N: xml::Node<N>>(pub Vec<dav::PropStat<E,N>>);
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub struct MkCalendarResponse<E: dav::Extension>(pub Vec<dav::PropStat<E>>);
|
||||
|
||||
// --- (REPORT PART) ---
|
||||
|
||||
|
@ -66,7 +66,7 @@ pub struct MkCalendarResponse<E: dav::Extension, N: xml::Node<N>>(pub Vec<dav::P
|
|||
/// <!ELEMENT calendar-query ((DAV:allprop |
|
||||
/// DAV:propname |
|
||||
/// DAV:prop)?, filter, timezone?)>
|
||||
#[derive(Debug, PartialEq)]
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub struct CalendarQuery<E: dav::Extension> {
|
||||
pub selector: Option<CalendarSelector<E>>,
|
||||
pub filter: Filter,
|
||||
|
@ -87,7 +87,7 @@ pub struct CalendarQuery<E: dav::Extension> {
|
|||
/// <!ELEMENT calendar-multiget ((DAV:allprop |
|
||||
/// DAV:propname |
|
||||
/// DAV:prop)?, DAV:href+)>
|
||||
#[derive(Debug, PartialEq)]
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub struct CalendarMultiget<E: dav::Extension> {
|
||||
pub selector: Option<CalendarSelector<E>>,
|
||||
pub href: Vec<dav::Href>,
|
||||
|
@ -104,7 +104,7 @@ pub struct CalendarMultiget<E: dav::Extension> {
|
|||
///
|
||||
/// Definition:
|
||||
/// <!ELEMENT free-busy-query (time-range)>
|
||||
#[derive(Debug, PartialEq)]
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub struct FreeBusyQuery(pub TimeRange);
|
||||
|
||||
// ----- Hooks -----
|
||||
|
|
|
@ -12,7 +12,7 @@ use super::xml::{Node, QRead, Reader, IRead, DAV_URN};
|
|||
// (2) Rewrite QRead and replace Result<Option<_>, _> with Result<_, _>, not found being a possible
|
||||
// error.
|
||||
// (3) Rewrite vectors with xml.collect<E: QRead>() -> Result<Vec<E>, _>
|
||||
// (4) Something for alternatives would be great but no idea yet
|
||||
// (4) Something for alternatives like xml::choices on some lib would be great but no idea yet
|
||||
|
||||
// ---- ROOT ----
|
||||
|
||||
|
@ -61,7 +61,7 @@ impl<E: Extension> QRead<PropertyUpdate<E>> for PropertyUpdate<E> {
|
|||
}
|
||||
|
||||
/// Generic response
|
||||
impl<E: Extension, N: Node<N>> QRead<Multistatus<E,N>> for Multistatus<E,N> {
|
||||
impl<E: Extension> QRead<Multistatus<E>> for Multistatus<E> {
|
||||
async fn qread(xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> {
|
||||
xml.open(DAV_URN, "multistatus").await?;
|
||||
let mut responses = Vec::new();
|
||||
|
@ -113,6 +113,7 @@ impl QRead<LockInfo> for LockInfo {
|
|||
// LOCK RESPONSE
|
||||
impl<E: Extension> QRead<PropValue<E>> for PropValue<E> {
|
||||
async fn qread(xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> {
|
||||
println!("---- propvalue");
|
||||
xml.open(DAV_URN, "prop").await?;
|
||||
let acc = xml.collect::<Property<E>>().await?;
|
||||
xml.close().await?;
|
||||
|
@ -134,7 +135,7 @@ impl<E: Extension> QRead<Error<E>> for Error<E> {
|
|||
|
||||
|
||||
// ---- INNER XML
|
||||
impl<E: Extension, N: Node<N>> QRead<Response<E,N>> for Response<E,N> {
|
||||
impl<E: Extension> QRead<Response<E>> for Response<E> {
|
||||
async fn qread(xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> {
|
||||
xml.open(DAV_URN, "response").await?;
|
||||
let (mut status, mut error, mut responsedescription, mut location) = (None, None, None, None);
|
||||
|
@ -145,7 +146,7 @@ impl<E: Extension, N: Node<N>> QRead<Response<E,N>> for Response<E,N> {
|
|||
let mut dirty = false;
|
||||
xml.maybe_read::<Status>(&mut status, &mut dirty).await?;
|
||||
xml.maybe_push::<Href>(&mut href, &mut dirty).await?;
|
||||
xml.maybe_push::<PropStat<E,N>>(&mut propstat, &mut dirty).await?;
|
||||
xml.maybe_push::<PropStat<E>>(&mut propstat, &mut dirty).await?;
|
||||
xml.maybe_read::<Error<E>>(&mut error, &mut dirty).await?;
|
||||
xml.maybe_read::<ResponseDescription>(&mut responsedescription, &mut dirty).await?;
|
||||
xml.maybe_read::<Location>(&mut location, &mut dirty).await?;
|
||||
|
@ -174,15 +175,15 @@ impl<E: Extension, N: Node<N>> QRead<Response<E,N>> for Response<E,N> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<E: Extension, N: Node<N>> QRead<PropStat<E,N>> for PropStat<E,N> {
|
||||
impl<E: Extension> QRead<PropStat<E>> for PropStat<E> {
|
||||
async fn qread(xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> {
|
||||
xml.open(DAV_URN, "propstat").await?;
|
||||
|
||||
let (mut m_prop, mut m_status, mut error, mut responsedescription) = (None, None, None, None);
|
||||
let (mut m_any_prop, mut m_status, mut error, mut responsedescription) = (None, None, None, None);
|
||||
|
||||
loop {
|
||||
let mut dirty = false;
|
||||
xml.maybe_read::<N>(&mut m_prop, &mut dirty).await?;
|
||||
xml.maybe_read::<AnyProp<E>>(&mut m_any_prop, &mut dirty).await?;
|
||||
xml.maybe_read::<Status>(&mut m_status, &mut dirty).await?;
|
||||
xml.maybe_read::<Error<E>>(&mut error, &mut dirty).await?;
|
||||
xml.maybe_read::<ResponseDescription>(&mut responsedescription, &mut dirty).await?;
|
||||
|
@ -196,7 +197,7 @@ impl<E: Extension, N: Node<N>> QRead<PropStat<E,N>> for PropStat<E,N> {
|
|||
}
|
||||
|
||||
xml.close().await?;
|
||||
match (m_prop, m_status) {
|
||||
match (m_any_prop, m_status) {
|
||||
(Some(prop), Some(status)) => Ok(PropStat { prop, status, error, responsedescription }),
|
||||
_ => Err(ParsingError::MissingChild),
|
||||
}
|
||||
|
@ -309,6 +310,25 @@ impl<E: Extension> QRead<PropName<E>> for PropName<E> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<E: Extension> QRead<AnyProp<E>> for AnyProp<E> {
|
||||
async fn qread(xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> {
|
||||
xml.open(DAV_URN, "prop").await?;
|
||||
let acc = xml.collect::<AnyProperty<E>>().await?;
|
||||
xml.close().await?;
|
||||
Ok(AnyProp(acc))
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Extension> QRead<AnyProperty<E>> for AnyProperty<E> {
|
||||
async fn qread(xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> {
|
||||
match Property::qread(xml).await {
|
||||
Err(ParsingError::Recoverable) => (),
|
||||
otherwise => return otherwise.map(Self::Value)
|
||||
}
|
||||
PropertyRequest::qread(xml).await.map(Self::Request)
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Extension> QRead<PropertyRequest<E>> for PropertyRequest<E> {
|
||||
async fn qread(xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> {
|
||||
let maybe = if xml.maybe_open(DAV_URN, "creationdate").await?.is_some() {
|
||||
|
@ -348,43 +368,43 @@ impl<E: Extension> QRead<PropertyRequest<E>> for PropertyRequest<E> {
|
|||
impl<E: Extension> QRead<Property<E>> for Property<E> {
|
||||
async fn qread(xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> {
|
||||
// Core WebDAV properties
|
||||
if xml.maybe_open(DAV_URN, "creationdate").await?.is_some() {
|
||||
if xml.maybe_open_start(DAV_URN, "creationdate").await?.is_some() {
|
||||
let datestr = xml.tag_string().await?;
|
||||
xml.close().await?;
|
||||
return Ok(Property::CreationDate(DateTime::parse_from_rfc3339(datestr.as_str())?))
|
||||
} else if xml.maybe_open(DAV_URN, "displayname").await?.is_some() {
|
||||
} else if xml.maybe_open_start(DAV_URN, "displayname").await?.is_some() {
|
||||
let name = xml.tag_string().await?;
|
||||
xml.close().await?;
|
||||
return Ok(Property::DisplayName(name))
|
||||
} else if xml.maybe_open(DAV_URN, "getcontentlanguage").await?.is_some() {
|
||||
} else if xml.maybe_open_start(DAV_URN, "getcontentlanguage").await?.is_some() {
|
||||
let lang = xml.tag_string().await?;
|
||||
xml.close().await?;
|
||||
return Ok(Property::GetContentLanguage(lang))
|
||||
} else if xml.maybe_open(DAV_URN, "getcontentlength").await?.is_some() {
|
||||
} else if xml.maybe_open_start(DAV_URN, "getcontentlength").await?.is_some() {
|
||||
let cl = xml.tag_string().await?.parse::<u64>()?;
|
||||
xml.close().await?;
|
||||
return Ok(Property::GetContentLength(cl))
|
||||
} else if xml.maybe_open(DAV_URN, "getcontenttype").await?.is_some() {
|
||||
} else if xml.maybe_open_start(DAV_URN, "getcontenttype").await?.is_some() {
|
||||
let ct = xml.tag_string().await?;
|
||||
xml.close().await?;
|
||||
return Ok(Property::GetContentType(ct))
|
||||
} else if xml.maybe_open(DAV_URN, "getetag").await?.is_some() {
|
||||
} else if xml.maybe_open_start(DAV_URN, "getetag").await?.is_some() {
|
||||
let etag = xml.tag_string().await?;
|
||||
xml.close().await?;
|
||||
return Ok(Property::GetEtag(etag))
|
||||
} else if xml.maybe_open(DAV_URN, "getlastmodified").await?.is_some() {
|
||||
} else if xml.maybe_open_start(DAV_URN, "getlastmodified").await?.is_some() {
|
||||
let datestr = xml.tag_string().await?;
|
||||
xml.close().await?;
|
||||
return Ok(Property::GetLastModified(DateTime::parse_from_rfc2822(datestr.as_str())?))
|
||||
} else if xml.maybe_open(DAV_URN, "lockdiscovery").await?.is_some() {
|
||||
} else if xml.maybe_open_start(DAV_URN, "lockdiscovery").await?.is_some() {
|
||||
let acc = xml.collect::<ActiveLock>().await?;
|
||||
xml.close().await?;
|
||||
return Ok(Property::LockDiscovery(acc))
|
||||
} else if xml.maybe_open(DAV_URN, "resourcetype").await?.is_some() {
|
||||
} else if xml.maybe_open_start(DAV_URN, "resourcetype").await?.is_some() {
|
||||
let acc = xml.collect::<ResourceType<E>>().await?;
|
||||
xml.close().await?;
|
||||
return Ok(Property::ResourceType(acc))
|
||||
} else if xml.maybe_open(DAV_URN, "supportedlock").await?.is_some() {
|
||||
} else if xml.maybe_open_start(DAV_URN, "supportedlock").await?.is_some() {
|
||||
let acc = xml.collect::<LockEntry>().await?;
|
||||
xml.close().await?;
|
||||
return Ok(Property::SupportedLock(acc))
|
||||
|
@ -758,7 +778,7 @@ mod tests {
|
|||
"#;
|
||||
|
||||
let mut rdr = Reader::new(NsReader::from_reader(src.as_bytes())).await.unwrap();
|
||||
let got = rdr.find::<Multistatus::<Core, PropName<Core>>>().await.unwrap();
|
||||
let got = rdr.find::<Multistatus::<Core>>().await.unwrap();
|
||||
|
||||
assert_eq!(got, Multistatus {
|
||||
responses: vec![
|
||||
|
@ -766,11 +786,11 @@ mod tests {
|
|||
status_or_propstat: StatusOrPropstat::PropStat(
|
||||
Href("http://www.example.com/container/".into()),
|
||||
vec![PropStat {
|
||||
prop: PropName(vec![
|
||||
PropertyRequest::CreationDate,
|
||||
PropertyRequest::DisplayName,
|
||||
PropertyRequest::ResourceType,
|
||||
PropertyRequest::SupportedLock,
|
||||
prop: AnyProp(vec![
|
||||
AnyProperty::Request(PropertyRequest::CreationDate),
|
||||
AnyProperty::Request(PropertyRequest::DisplayName),
|
||||
AnyProperty::Request(PropertyRequest::ResourceType),
|
||||
AnyProperty::Request(PropertyRequest::SupportedLock),
|
||||
]),
|
||||
status: Status(http::status::StatusCode::OK),
|
||||
error: None,
|
||||
|
@ -785,15 +805,15 @@ mod tests {
|
|||
status_or_propstat: StatusOrPropstat::PropStat(
|
||||
Href("http://www.example.com/container/front.html".into()),
|
||||
vec![PropStat {
|
||||
prop: PropName(vec![
|
||||
PropertyRequest::CreationDate,
|
||||
PropertyRequest::DisplayName,
|
||||
PropertyRequest::GetContentLength,
|
||||
PropertyRequest::GetContentType,
|
||||
PropertyRequest::GetEtag,
|
||||
PropertyRequest::GetLastModified,
|
||||
PropertyRequest::ResourceType,
|
||||
PropertyRequest::SupportedLock,
|
||||
prop: AnyProp(vec![
|
||||
AnyProperty::Request(PropertyRequest::CreationDate),
|
||||
AnyProperty::Request(PropertyRequest::DisplayName),
|
||||
AnyProperty::Request(PropertyRequest::GetContentLength),
|
||||
AnyProperty::Request(PropertyRequest::GetContentType),
|
||||
AnyProperty::Request(PropertyRequest::GetEtag),
|
||||
AnyProperty::Request(PropertyRequest::GetLastModified),
|
||||
AnyProperty::Request(PropertyRequest::ResourceType),
|
||||
AnyProperty::Request(PropertyRequest::SupportedLock),
|
||||
]),
|
||||
status: Status(http::status::StatusCode::OK),
|
||||
error: None,
|
||||
|
@ -869,7 +889,7 @@ mod tests {
|
|||
</D:multistatus>"#;
|
||||
|
||||
let mut rdr = Reader::new(NsReader::from_reader(src.as_bytes())).await.unwrap();
|
||||
let got = rdr.find::<Multistatus::<Core, PropValue<Core>>>().await.unwrap();
|
||||
let got = rdr.find::<Multistatus::<Core>>().await.unwrap();
|
||||
|
||||
assert_eq!(got, Multistatus {
|
||||
responses: vec![
|
||||
|
@ -877,11 +897,11 @@ mod tests {
|
|||
status_or_propstat: StatusOrPropstat::PropStat(
|
||||
Href("/container/".into()),
|
||||
vec![PropStat {
|
||||
prop: PropValue(vec![
|
||||
Property::CreationDate(FixedOffset::west_opt(8 * 3600).unwrap().with_ymd_and_hms(1997, 12, 01, 17, 42, 21).unwrap()),
|
||||
Property::DisplayName("Example collection".into()),
|
||||
Property::ResourceType(vec![ResourceType::Collection]),
|
||||
Property::SupportedLock(vec![
|
||||
prop: AnyProp(vec![
|
||||
AnyProperty::Value(Property::CreationDate(FixedOffset::west_opt(8 * 3600).unwrap().with_ymd_and_hms(1997, 12, 01, 17, 42, 21).unwrap())),
|
||||
AnyProperty::Value(Property::DisplayName("Example collection".into())),
|
||||
AnyProperty::Value(Property::ResourceType(vec![ResourceType::Collection])),
|
||||
AnyProperty::Value(Property::SupportedLock(vec![
|
||||
LockEntry {
|
||||
lockscope: LockScope::Exclusive,
|
||||
locktype: LockType::Write,
|
||||
|
@ -890,7 +910,7 @@ mod tests {
|
|||
lockscope: LockScope::Shared,
|
||||
locktype: LockType::Write,
|
||||
},
|
||||
]),
|
||||
])),
|
||||
]),
|
||||
status: Status(http::status::StatusCode::OK),
|
||||
error: None,
|
||||
|
@ -906,15 +926,17 @@ mod tests {
|
|||
status_or_propstat: StatusOrPropstat::PropStat(
|
||||
Href("/container/front.html".into()),
|
||||
vec![PropStat {
|
||||
prop: PropValue(vec![
|
||||
Property::CreationDate(FixedOffset::west_opt(8 * 3600).unwrap().with_ymd_and_hms(1997, 12, 01, 18, 27, 21).unwrap()),
|
||||
Property::DisplayName("Example HTML resource".into()),
|
||||
Property::GetContentLength(4525),
|
||||
Property::GetContentType("text/html".into()),
|
||||
Property::GetEtag(r#""zzyzx""#.into()),
|
||||
Property::GetLastModified(FixedOffset::west_opt(0).unwrap().with_ymd_and_hms(1998, 01, 12, 09, 25, 56).unwrap()),
|
||||
Property::ResourceType(vec![]),
|
||||
Property::SupportedLock(vec![
|
||||
prop: AnyProp(vec![
|
||||
AnyProperty::Value(Property::CreationDate(FixedOffset::west_opt(8 * 3600).unwrap().with_ymd_and_hms(1997, 12, 01, 18, 27, 21).unwrap())),
|
||||
AnyProperty::Value(Property::DisplayName("Example HTML resource".into())),
|
||||
AnyProperty::Value(Property::GetContentLength(4525)),
|
||||
AnyProperty::Value(Property::GetContentType("text/html".into())),
|
||||
AnyProperty::Value(Property::GetEtag(r#""zzyzx""#.into())),
|
||||
AnyProperty::Value(Property::GetLastModified(FixedOffset::west_opt(0).unwrap().with_ymd_and_hms(1998, 01, 12, 09, 25, 56).unwrap())),
|
||||
//@FIXME know bug, can't disambiguate between an empty resource
|
||||
//type value and a request resource type
|
||||
AnyProperty::Request(PropertyRequest::ResourceType),
|
||||
AnyProperty::Value(Property::SupportedLock(vec![
|
||||
LockEntry {
|
||||
lockscope: LockScope::Exclusive,
|
||||
locktype: LockType::Write,
|
||||
|
@ -923,7 +945,7 @@ mod tests {
|
|||
lockscope: LockScope::Shared,
|
||||
locktype: LockType::Write,
|
||||
},
|
||||
]),
|
||||
])),
|
||||
]),
|
||||
status: Status(http::status::StatusCode::OK),
|
||||
error: None,
|
||||
|
|
|
@ -48,7 +48,7 @@ impl<E: Extension> QWrite for PropertyUpdate<E> {
|
|||
|
||||
/// PROPFIND RESPONSE, PROPPATCH RESPONSE, COPY RESPONSE, MOVE RESPONSE
|
||||
/// DELETE RESPONSE,
|
||||
impl<E: Extension, N: Node<N>> QWrite for Multistatus<E,N> {
|
||||
impl<E: Extension> QWrite for Multistatus<E> {
|
||||
async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> {
|
||||
let start = xml.create_dav_element("multistatus");
|
||||
let end = start.to_end();
|
||||
|
@ -154,6 +154,28 @@ impl<E: Extension> QWrite for PropName<E> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<E: Extension> QWrite for AnyProp<E> {
|
||||
async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> {
|
||||
let start = xml.create_dav_element("prop");
|
||||
let end = start.to_end();
|
||||
|
||||
xml.q.write_event_async(Event::Start(start.clone())).await?;
|
||||
for propname in &self.0 {
|
||||
propname.qwrite(xml).await?;
|
||||
}
|
||||
xml.q.write_event_async(Event::End(end)).await
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Extension> QWrite for AnyProperty<E> {
|
||||
async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> {
|
||||
match self {
|
||||
Self::Request(v) => v.qwrite(xml).await,
|
||||
Self::Value(v) => v.qwrite(xml).await,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl QWrite for Href {
|
||||
async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> {
|
||||
|
@ -166,7 +188,7 @@ impl QWrite for Href {
|
|||
}
|
||||
}
|
||||
|
||||
impl<E: Extension, N: Node<N>> QWrite for Response<E,N> {
|
||||
impl<E: Extension> QWrite for Response<E> {
|
||||
async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> {
|
||||
let start = xml.create_dav_element("response");
|
||||
let end = start.to_end();
|
||||
|
@ -186,7 +208,7 @@ impl<E: Extension, N: Node<N>> QWrite for Response<E,N> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<E: Extension, N: Node<N>> QWrite for StatusOrPropstat<E,N> {
|
||||
impl<E: Extension> QWrite for StatusOrPropstat<E> {
|
||||
async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> {
|
||||
match self {
|
||||
Self::Status(many_href, status) => {
|
||||
|
@ -244,7 +266,7 @@ impl QWrite for Location {
|
|||
}
|
||||
}
|
||||
|
||||
impl<E: Extension, N: Node<N>> QWrite for PropStat<E,N> {
|
||||
impl<E: Extension> QWrite for PropStat<E> {
|
||||
async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> {
|
||||
let start = xml.create_dav_element("propstat");
|
||||
let end = start.to_end();
|
||||
|
@ -672,7 +694,7 @@ mod tests {
|
|||
|
||||
#[tokio::test]
|
||||
async fn basic_multistatus() {
|
||||
let orig = Multistatus::<Core, PropName<Core>> {
|
||||
let orig = Multistatus::<Core> {
|
||||
responses: vec![],
|
||||
responsedescription: Some(ResponseDescription("Hello world".into()))
|
||||
};
|
||||
|
@ -683,7 +705,7 @@ mod tests {
|
|||
</D:multistatus>"#;
|
||||
|
||||
assert_eq!(&got, expected, "\n---GOT---\n{got}\n---EXP---\n{expected}\n");
|
||||
assert_eq!(deserialize::<Multistatus::<Core, PropName<Core>>>(got.as_str()).await, orig)
|
||||
assert_eq!(deserialize::<Multistatus::<Core>>(got.as_str()).await, orig)
|
||||
}
|
||||
|
||||
|
||||
|
@ -722,17 +744,17 @@ mod tests {
|
|||
|
||||
#[tokio::test]
|
||||
async fn rfc_propname_res() {
|
||||
let orig = Multistatus::<Core, PropName<Core>> {
|
||||
let orig = Multistatus::<Core> {
|
||||
responses: vec![
|
||||
Response {
|
||||
status_or_propstat: StatusOrPropstat::PropStat(
|
||||
Href("http://www.example.com/container/".into()),
|
||||
vec![PropStat {
|
||||
prop: PropName(vec![
|
||||
PropertyRequest::CreationDate,
|
||||
PropertyRequest::DisplayName,
|
||||
PropertyRequest::ResourceType,
|
||||
PropertyRequest::SupportedLock,
|
||||
prop: AnyProp(vec![
|
||||
AnyProperty::Request(PropertyRequest::CreationDate),
|
||||
AnyProperty::Request(PropertyRequest::DisplayName),
|
||||
AnyProperty::Request(PropertyRequest::ResourceType),
|
||||
AnyProperty::Request(PropertyRequest::SupportedLock),
|
||||
]),
|
||||
status: Status(http::status::StatusCode::OK),
|
||||
error: None,
|
||||
|
@ -747,15 +769,15 @@ mod tests {
|
|||
status_or_propstat: StatusOrPropstat::PropStat(
|
||||
Href("http://www.example.com/container/front.html".into()),
|
||||
vec![PropStat {
|
||||
prop: PropName(vec![
|
||||
PropertyRequest::CreationDate,
|
||||
PropertyRequest::DisplayName,
|
||||
PropertyRequest::GetContentLength,
|
||||
PropertyRequest::GetContentType,
|
||||
PropertyRequest::GetEtag,
|
||||
PropertyRequest::GetLastModified,
|
||||
PropertyRequest::ResourceType,
|
||||
PropertyRequest::SupportedLock,
|
||||
prop: AnyProp(vec![
|
||||
AnyProperty::Request(PropertyRequest::CreationDate),
|
||||
AnyProperty::Request(PropertyRequest::DisplayName),
|
||||
AnyProperty::Request(PropertyRequest::GetContentLength),
|
||||
AnyProperty::Request(PropertyRequest::GetContentType),
|
||||
AnyProperty::Request(PropertyRequest::GetEtag),
|
||||
AnyProperty::Request(PropertyRequest::GetLastModified),
|
||||
AnyProperty::Request(PropertyRequest::ResourceType),
|
||||
AnyProperty::Request(PropertyRequest::SupportedLock),
|
||||
]),
|
||||
status: Status(http::status::StatusCode::OK),
|
||||
error: None,
|
||||
|
@ -805,7 +827,7 @@ mod tests {
|
|||
|
||||
|
||||
assert_eq!(&got, expected, "\n---GOT---\n{got}\n---EXP---\n{expected}\n");
|
||||
assert_eq!(deserialize::<Multistatus::<Core, PropName<Core>>>(got.as_str()).await, orig)
|
||||
assert_eq!(deserialize::<Multistatus::<Core>>(got.as_str()).await, orig)
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
|
@ -825,20 +847,20 @@ mod tests {
|
|||
async fn rfc_allprop_res() {
|
||||
use chrono::{FixedOffset,TimeZone};
|
||||
|
||||
let orig = Multistatus::<Core, PropValue<Core>> {
|
||||
let orig = Multistatus::<Core> {
|
||||
responses: vec![
|
||||
Response {
|
||||
status_or_propstat: StatusOrPropstat::PropStat(
|
||||
Href("/container/".into()),
|
||||
vec![PropStat {
|
||||
prop: PropValue(vec![
|
||||
Property::CreationDate(FixedOffset::west_opt(8 * 3600)
|
||||
prop: AnyProp(vec![
|
||||
AnyProperty::Value(Property::CreationDate(FixedOffset::west_opt(8 * 3600)
|
||||
.unwrap()
|
||||
.with_ymd_and_hms(1997, 12, 1, 17, 42, 21)
|
||||
.unwrap()),
|
||||
Property::DisplayName("Example collection".into()),
|
||||
Property::ResourceType(vec![ResourceType::Collection]),
|
||||
Property::SupportedLock(vec![
|
||||
.unwrap())),
|
||||
AnyProperty::Value(Property::DisplayName("Example collection".into())),
|
||||
AnyProperty::Value(Property::ResourceType(vec![ResourceType::Collection])),
|
||||
AnyProperty::Value(Property::SupportedLock(vec![
|
||||
LockEntry {
|
||||
lockscope: LockScope::Exclusive,
|
||||
locktype: LockType::Write,
|
||||
|
@ -847,7 +869,7 @@ mod tests {
|
|||
lockscope: LockScope::Shared,
|
||||
locktype: LockType::Write,
|
||||
},
|
||||
]),
|
||||
])),
|
||||
]),
|
||||
status: Status(http::status::StatusCode::OK),
|
||||
error: None,
|
||||
|
@ -862,21 +884,23 @@ mod tests {
|
|||
status_or_propstat: StatusOrPropstat::PropStat(
|
||||
Href("/container/front.html".into()),
|
||||
vec![PropStat {
|
||||
prop: PropValue(vec![
|
||||
Property::CreationDate(FixedOffset::west_opt(8 * 3600)
|
||||
prop: AnyProp(vec![
|
||||
AnyProperty::Value(Property::CreationDate(FixedOffset::west_opt(8 * 3600)
|
||||
.unwrap()
|
||||
.with_ymd_and_hms(1997, 12, 1, 18, 27, 21)
|
||||
.unwrap()),
|
||||
Property::DisplayName("Example HTML resource".into()),
|
||||
Property::GetContentLength(4525),
|
||||
Property::GetContentType("text/html".into()),
|
||||
Property::GetEtag(r#""zzyzx""#.into()),
|
||||
Property::GetLastModified(FixedOffset::east_opt(0)
|
||||
.unwrap())),
|
||||
AnyProperty::Value(Property::DisplayName("Example HTML resource".into())),
|
||||
AnyProperty::Value(Property::GetContentLength(4525)),
|
||||
AnyProperty::Value(Property::GetContentType("text/html".into())),
|
||||
AnyProperty::Value(Property::GetEtag(r#""zzyzx""#.into())),
|
||||
AnyProperty::Value(Property::GetLastModified(FixedOffset::east_opt(0)
|
||||
.unwrap()
|
||||
.with_ymd_and_hms(1998, 1, 12, 9, 25, 56)
|
||||
.unwrap()),
|
||||
Property::ResourceType(vec![]),
|
||||
Property::SupportedLock(vec![
|
||||
.unwrap())),
|
||||
//@FIXME know bug, can't disambiguate between an empty resource
|
||||
//type value and a request resource type
|
||||
AnyProperty::Request(PropertyRequest::ResourceType),
|
||||
AnyProperty::Value(Property::SupportedLock(vec![
|
||||
LockEntry {
|
||||
lockscope: LockScope::Exclusive,
|
||||
locktype: LockType::Write,
|
||||
|
@ -885,7 +909,7 @@ mod tests {
|
|||
lockscope: LockScope::Shared,
|
||||
locktype: LockType::Write,
|
||||
},
|
||||
]),
|
||||
])),
|
||||
]),
|
||||
status: Status(http::status::StatusCode::OK),
|
||||
error: None,
|
||||
|
@ -970,7 +994,7 @@ mod tests {
|
|||
</D:multistatus>"#;
|
||||
|
||||
assert_eq!(&got, expected, "\n---GOT---\n{got}\n---EXP---\n{expected}\n");
|
||||
assert_eq!(deserialize::<Multistatus::<Core, PropValue<Core>>>(got.as_str()).await, orig)
|
||||
assert_eq!(deserialize::<Multistatus::<Core>>(got.as_str()).await, orig)
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
|
@ -1025,7 +1049,7 @@ mod tests {
|
|||
|
||||
#[tokio::test]
|
||||
async fn rfc_delete_locked2() {
|
||||
let orig = Multistatus::<Core, PropValue<Core>> {
|
||||
let orig = Multistatus::<Core> {
|
||||
responses: vec![Response {
|
||||
status_or_propstat: StatusOrPropstat::Status(
|
||||
vec![Href("http://www.example.com/container/resource3".into())],
|
||||
|
@ -1051,7 +1075,7 @@ mod tests {
|
|||
</D:multistatus>"#;
|
||||
|
||||
assert_eq!(&got, expected, "\n---GOT---\n{got}\n---EXP---\n{expected}\n");
|
||||
assert_eq!(deserialize::<Multistatus::<Core, PropValue<Core>>>(got.as_str()).await, orig)
|
||||
assert_eq!(deserialize::<Multistatus::<Core>>(got.as_str()).await, orig)
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
|
|
|
@ -331,8 +331,8 @@ pub enum LockType {
|
|||
///
|
||||
/// <!ELEMENT multistatus (response*, responsedescription?) >
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub struct Multistatus<E: Extension, N: xml::Node<N>> {
|
||||
pub responses: Vec<Response<E, N>>,
|
||||
pub struct Multistatus<E: Extension> {
|
||||
pub responses: Vec<Response<E>>,
|
||||
pub responsedescription: Option<ResponseDescription>,
|
||||
}
|
||||
|
||||
|
@ -387,6 +387,9 @@ pub struct PropName<E: Extension>(pub Vec<PropertyRequest<E>>);
|
|||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub struct PropValue<E: Extension>(pub Vec<Property<E>>);
|
||||
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub struct AnyProp<E: Extension>(pub Vec<AnyProperty<E>>);
|
||||
|
||||
/// 14.19. propertyupdate XML Element
|
||||
///
|
||||
/// Name: propertyupdate
|
||||
|
@ -462,14 +465,19 @@ pub enum PropFind<E: Extension> {
|
|||
/// the properties named in 'prop'.
|
||||
///
|
||||
/// <!ELEMENT propstat (prop, status, error?, responsedescription?) >
|
||||
///
|
||||
/// ---
|
||||
///
|
||||
///
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub struct PropStat<E: Extension, N: xml::Node<N>> {
|
||||
pub prop: N,
|
||||
pub struct PropStat<E: Extension> {
|
||||
pub prop: AnyProp<E>,
|
||||
pub status: Status,
|
||||
pub error: Option<Error<E>>,
|
||||
pub responsedescription: Option<ResponseDescription>,
|
||||
}
|
||||
|
||||
|
||||
/// 14.23. remove XML Element
|
||||
///
|
||||
/// Name: remove
|
||||
|
@ -512,16 +520,16 @@ pub struct Remove<E: Extension>(pub PropName<E>);
|
|||
/// --- rewritten as ---
|
||||
/// <!ELEMENT response ((href+, status)|(href, propstat+), error?, responsedescription?, location?>
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub enum StatusOrPropstat<E: Extension, N: xml::Node<N>> {
|
||||
pub enum StatusOrPropstat<E: Extension> {
|
||||
// One status, multiple hrefs...
|
||||
Status(Vec<Href>, Status),
|
||||
// A single href, multiple properties...
|
||||
PropStat(Href, Vec<PropStat<E, N>>),
|
||||
PropStat(Href, Vec<PropStat<E>>),
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub struct Response<E: Extension, N: xml::Node<N>> {
|
||||
pub status_or_propstat: StatusOrPropstat<E, N>,
|
||||
pub struct Response<E: Extension> {
|
||||
pub status_or_propstat: StatusOrPropstat<E>,
|
||||
pub error: Option<Error<E>>,
|
||||
pub responsedescription: Option<ResponseDescription>,
|
||||
pub location: Option<Location>,
|
||||
|
@ -644,6 +652,12 @@ pub enum Timeout {
|
|||
/// the header value could include LWS as defined in [RFC2616], Section
|
||||
/// 4.2. Server implementors SHOULD strip LWS from these values before
|
||||
/// using as WebDAV property values.
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub enum AnyProperty<E: Extension> {
|
||||
Request(PropertyRequest<E>),
|
||||
Value(Property<E>),
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub enum PropertyRequest<E: Extension> {
|
||||
CreationDate,
|
||||
|
|
|
@ -258,6 +258,17 @@ impl<T: IRead> Reader<T> {
|
|||
Ok(evt)
|
||||
}
|
||||
|
||||
pub async fn open_start(&mut self, ns: &[u8], key: &str) -> Result<Event<'static>, ParsingError> {
|
||||
let evt = match self.peek() {
|
||||
Event::Start(_) if self.is_tag(ns, key) => self.next().await?,
|
||||
_ => return Err(ParsingError::Recoverable),
|
||||
};
|
||||
|
||||
//println!("open tag {:?}", evt);
|
||||
self.parents.push(evt.clone());
|
||||
Ok(evt)
|
||||
}
|
||||
|
||||
pub async fn maybe_open(&mut self, ns: &[u8], key: &str) -> Result<Option<Event<'static>>, ParsingError> {
|
||||
match self.open(ns, key).await {
|
||||
Ok(v) => Ok(Some(v)),
|
||||
|
@ -266,6 +277,14 @@ impl<T: IRead> Reader<T> {
|
|||
}
|
||||
}
|
||||
|
||||
pub async fn maybe_open_start(&mut self, ns: &[u8], key: &str) -> Result<Option<Event<'static>>, ParsingError> {
|
||||
match self.open_start(ns, key).await {
|
||||
Ok(v) => Ok(Some(v)),
|
||||
Err(ParsingError::Recoverable) => Ok(None),
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn prev_attr(&self, attr: &str) -> Option<String> {
|
||||
match &self.prev {
|
||||
Event::Start(bs) | Event::Empty(bs) => match bs.try_get_attribute(attr) {
|
||||
|
|
|
@ -375,18 +375,18 @@ trait DavNode: Send {
|
|||
// ----- common
|
||||
|
||||
/// building DAV responses
|
||||
fn multistatus_name(&self, user: &ArcUser, depth: dav::Depth) -> dav::Multistatus<Calendar, dav::PropName<Calendar>> {
|
||||
fn multistatus_name(&self, user: &ArcUser, depth: dav::Depth) -> dav::Multistatus<Calendar> {
|
||||
let mut names = vec![(self.path(user), self.supported_properties(user))];
|
||||
if matches!(depth, dav::Depth::One | dav::Depth::Infinity) {
|
||||
names.extend(self.children(user).iter().map(|c| (c.path(user), c.supported_properties(user))));
|
||||
}
|
||||
|
||||
dav::Multistatus::<Calendar, dav::PropName<Calendar>> {
|
||||
dav::Multistatus::<Calendar> {
|
||||
responses: names.into_iter().map(|(url, names)| dav::Response {
|
||||
status_or_propstat: dav::StatusOrPropstat::PropStat(
|
||||
dav::Href(url),
|
||||
vec![dav::PropStat {
|
||||
prop: names,
|
||||
prop: dav::AnyProp(names.0.into_iter().map(dav::AnyProperty::Request).collect()),
|
||||
status: dav::Status(hyper::StatusCode::OK),
|
||||
error: None,
|
||||
responsedescription: None,
|
||||
|
@ -400,7 +400,7 @@ trait DavNode: Send {
|
|||
}
|
||||
}
|
||||
|
||||
fn multistatus_val(&self, user: &ArcUser, props: &dav::PropName<Calendar>, depth: dav::Depth) -> dav::Multistatus<Calendar, dav::PropValue<Calendar>> {
|
||||
fn multistatus_val(&self, user: &ArcUser, props: &dav::PropName<Calendar>, depth: dav::Depth) -> dav::Multistatus<Calendar> {
|
||||
let mut values = vec![(self.path(user), self.properties(user, props))];
|
||||
if matches!(depth, dav::Depth::One | dav::Depth::Infinity) {
|
||||
values.extend(self
|
||||
|
@ -410,12 +410,12 @@ trait DavNode: Send {
|
|||
);
|
||||
}
|
||||
|
||||
dav::Multistatus::<Calendar, dav::PropValue<Calendar>> {
|
||||
dav::Multistatus::<Calendar> {
|
||||
responses: values.into_iter().map(|(url, propval)| dav::Response {
|
||||
status_or_propstat: dav::StatusOrPropstat::PropStat(
|
||||
dav::Href(url),
|
||||
vec![dav::PropStat {
|
||||
prop: propval,
|
||||
prop: dav::AnyProp(propval.0.into_iter().map(dav::AnyProperty::Value).collect()),
|
||||
status: dav::Status(hyper::StatusCode::OK),
|
||||
error: None,
|
||||
responsedescription: None,
|
||||
|
|
Loading…
Reference in a new issue