drop anyprop as it can't be decoded
This commit is contained in:
parent
ce2fa5c3bc
commit
67e5953c24
5 changed files with 117 additions and 54 deletions
|
@ -5,7 +5,7 @@ use tokio::io::AsyncWrite;
|
|||
|
||||
use super::caltypes::*;
|
||||
use super::xml::{QWrite, IWrite, Writer};
|
||||
use super::types::Extension;
|
||||
use super::types::{Extension, Node};
|
||||
|
||||
const ICAL_DATETIME_FMT: &str = "%Y%m%dT%H%M%SZ";
|
||||
|
||||
|
@ -23,7 +23,7 @@ impl<E: Extension> QWrite for MkCalendar<E> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<E: Extension> QWrite for MkCalendarResponse<E> {
|
||||
impl<E: Extension, N: Node<N>> QWrite for MkCalendarResponse<E,N> {
|
||||
async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> {
|
||||
let start = xml.create_cal_element("mkcalendar-response");
|
||||
let end = start.to_end();
|
||||
|
@ -810,19 +810,19 @@ mod tests {
|
|||
#[tokio::test]
|
||||
async fn rfc_calendar_query1_res() {
|
||||
let got = serialize(
|
||||
&dav::Multistatus::<Calendar> {
|
||||
&dav::Multistatus::<Calendar,dav::PropValue<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::AnyProp::Value(dav::PropValue(vec![
|
||||
prop: dav::PropValue(vec![
|
||||
dav::Property::GetEtag("\"fffff-abcd2\"".into()),
|
||||
dav::Property::Extension(Property::CalendarData(CalendarDataPayload {
|
||||
mime: None,
|
||||
payload: "PLACEHOLDER".into()
|
||||
})),
|
||||
])),
|
||||
]),
|
||||
status: dav::Status(http::status::StatusCode::OK),
|
||||
error: None,
|
||||
responsedescription: None,
|
||||
|
@ -836,13 +836,13 @@ mod tests {
|
|||
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![
|
||||
prop: dav::PropValue(vec![
|
||||
dav::Property::GetEtag("\"fffff-abcd3\"".into()),
|
||||
dav::Property::Extension(Property::CalendarData(CalendarDataPayload{
|
||||
mime: None,
|
||||
payload: "PLACEHOLDER".into(),
|
||||
})),
|
||||
])),
|
||||
]),
|
||||
status: dav::Status(http::status::StatusCode::OK),
|
||||
error: None,
|
||||
responsedescription: None,
|
||||
|
|
|
@ -44,7 +44,7 @@ pub struct MkCalendar<E: dav::Extension>(pub dav::Set<E>);
|
|||
///
|
||||
/// <!ELEMENT mkcol-response (propstat+)>
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct MkCalendarResponse<E: dav::Extension>(pub Vec<dav::PropStat<E>>);
|
||||
pub struct MkCalendarResponse<E: dav::Extension, N: dav::Node<N>>(pub Vec<dav::PropStat<E,N>>);
|
||||
|
||||
// --- (REPORT PART) ---
|
||||
|
||||
|
|
|
@ -84,7 +84,7 @@ impl<E: Extension> QRead<PropertyUpdate<E>> for PropertyUpdate<E> {
|
|||
}
|
||||
|
||||
/// Generic response
|
||||
impl<E: Extension> QRead<Multistatus<E>> for Multistatus<E> {
|
||||
impl<E: Extension, N: Node<N>> QRead<Multistatus<E,N>> for Multistatus<E,N> {
|
||||
async fn qread(xml: &mut Reader<impl IRead>) -> Result<Option<Self>, ParsingError> {
|
||||
xml.tag_start(DAV_URN, "multistatus").await?;
|
||||
let mut responses = Vec::new();
|
||||
|
@ -181,16 +181,74 @@ impl<E: Extension> QRead<Error<E>> for Error<E> {
|
|||
|
||||
|
||||
// ---- INNER XML
|
||||
impl<E: Extension> QRead<Response<E>> for Response<E> {
|
||||
impl<E: Extension, N: Node<N>> QRead<Response<E,N>> for Response<E,N> {
|
||||
async fn qread(xml: &mut Reader<impl IRead>) -> Result<Option<Self>, ParsingError> {
|
||||
if xml.maybe_tag_start(DAV_URN, "response").await?.is_none() {
|
||||
return Ok(None)
|
||||
}
|
||||
let (mut status, mut error, mut responsedescription, mut location) = (None, None, None, None);
|
||||
let mut href = Vec::new();
|
||||
let mut propstat = Vec::new();
|
||||
|
||||
loop {
|
||||
if let Some(v) = Status::qread(xml).await? {
|
||||
status = Some(v);
|
||||
} else if let Some(v) = Href::qread(xml).await? {
|
||||
href.push(v);
|
||||
} else if let Some(v) = PropStat::qread(xml).await? {
|
||||
propstat.push(v);
|
||||
} else if let Some(v) = Error::qread(xml).await? {
|
||||
error = Some(v);
|
||||
} else if let Some(v) = ResponseDescription::qread(xml).await? {
|
||||
responsedescription = Some(v);
|
||||
} else if let Some(v) = Location::qread(xml).await? {
|
||||
location = Some(v);
|
||||
} else {
|
||||
match xml.peek() {
|
||||
Event::End(_) => break,
|
||||
_ => { xml.skip().await? },
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
xml.tag_stop(DAV_URN, "response").await?;
|
||||
match (status, &propstat[..], &href[..]) {
|
||||
(Some(status), &[], &[_, ..]) => Ok(Some(Response {
|
||||
status_or_propstat: StatusOrPropstat::Status(href, status),
|
||||
error, responsedescription, location,
|
||||
})),
|
||||
(None, &[_, ..], &[_, ..]) => Ok(Some(Response {
|
||||
status_or_propstat: StatusOrPropstat::PropStat(href.into_iter().next().unwrap(), propstat),
|
||||
error, responsedescription, location,
|
||||
})),
|
||||
(Some(_), &[_, ..], _) => Err(ParsingError::InvalidValue),
|
||||
_ => Err(ParsingError::MissingChild),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Extension, N: Node<N>> QRead<PropStat<E,N>> for PropStat<E,N> {
|
||||
async fn qread(xml: &mut Reader<impl IRead>) -> Result<Option<Self>, ParsingError> {
|
||||
if xml.maybe_tag_start(DAV_URN, "propstat").await?.is_none() {
|
||||
return Ok(None)
|
||||
}
|
||||
unimplemented!();
|
||||
}
|
||||
}
|
||||
|
||||
impl QRead<Status> for Status {
|
||||
async fn qread(xml: &mut Reader<impl IRead>) -> Result<Option<Self>, ParsingError> {
|
||||
if xml.maybe_tag_start(DAV_URN, "status").await?.is_none() {
|
||||
return Ok(None)
|
||||
}
|
||||
let fullcode = xml.tag_string().await?;
|
||||
let txtcode = fullcode.splitn(3, ' ').nth(1).ok_or(ParsingError::InvalidValue)?;
|
||||
let code = http::status::StatusCode::from_bytes(txtcode.as_bytes()).or(Err(ParsingError::InvalidValue))?;
|
||||
xml.tag_stop(DAV_URN, "status").await?;
|
||||
Ok(Some(Status(code)))
|
||||
}
|
||||
}
|
||||
|
||||
impl QRead<ResponseDescription> for ResponseDescription {
|
||||
async fn qread(xml: &mut Reader<impl IRead>) -> Result<Option<Self>, ParsingError> {
|
||||
if xml.maybe_tag_start(DAV_URN, "responsedescription").await?.is_none() {
|
||||
|
@ -202,6 +260,26 @@ impl QRead<ResponseDescription> for ResponseDescription {
|
|||
}
|
||||
}
|
||||
|
||||
impl QRead<Location> for Location {
|
||||
async fn qread(xml: &mut Reader<impl IRead>) -> Result<Option<Self>, ParsingError> {
|
||||
if xml.maybe_tag_start(DAV_URN, "location").await?.is_none() {
|
||||
return Ok(None)
|
||||
}
|
||||
let href = loop {
|
||||
if let Some(v) = Href::qread(xml).await? {
|
||||
break v
|
||||
}
|
||||
|
||||
match xml.peek() {
|
||||
Event::End(_) => return Err(ParsingError::MissingChild),
|
||||
_ => xml.skip().await?,
|
||||
};
|
||||
};
|
||||
xml.tag_stop(DAV_URN, "location").await?;
|
||||
Ok(Some(Location(href)))
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Extension> QRead<PropertyUpdateItem<E>> for PropertyUpdateItem<E> {
|
||||
async fn qread(xml: &mut Reader<impl IRead>) -> Result<Option<Self>, ParsingError> {
|
||||
if let Some(rm) = Remove::qread(xml).await? {
|
||||
|
|
|
@ -53,7 +53,7 @@ impl<E: Extension> QWrite for PropertyUpdate<E> {
|
|||
|
||||
/// PROPFIND RESPONSE, PROPPATCH RESPONSE, COPY RESPONSE, MOVE RESPONSE
|
||||
/// DELETE RESPONSE,
|
||||
impl<E: Extension> QWrite for Multistatus<E> {
|
||||
impl<E: Extension, N: Node<N>> QWrite for Multistatus<E,N> {
|
||||
async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> {
|
||||
let start = xml.create_dav_element("multistatus");
|
||||
let end = start.to_end();
|
||||
|
@ -146,15 +146,6 @@ impl<E: Extension> QWrite for Remove<E> {
|
|||
}
|
||||
|
||||
|
||||
impl<E: Extension> QWrite for AnyProp<E> {
|
||||
async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> {
|
||||
match self {
|
||||
Self::Name(propname) => propname.qwrite(xml).await,
|
||||
Self::Value(propval) => propval.qwrite(xml).await,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Extension> QWrite for PropName<E> {
|
||||
async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> {
|
||||
let start = xml.create_dav_element("prop");
|
||||
|
@ -180,7 +171,7 @@ impl QWrite for Href {
|
|||
}
|
||||
}
|
||||
|
||||
impl<E: Extension> QWrite for Response<E> {
|
||||
impl<E: Extension, N: Node<N>> QWrite for Response<E,N> {
|
||||
async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> {
|
||||
let start = xml.create_dav_element("response");
|
||||
let end = start.to_end();
|
||||
|
@ -200,7 +191,7 @@ impl<E: Extension> QWrite for Response<E> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<E: Extension> QWrite for StatusOrPropstat<E> {
|
||||
impl<E: Extension, N: Node<N>> QWrite for StatusOrPropstat<E,N> {
|
||||
async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> {
|
||||
match self {
|
||||
Self::Status(many_href, status) => {
|
||||
|
@ -258,7 +249,7 @@ impl QWrite for Location {
|
|||
}
|
||||
}
|
||||
|
||||
impl<E: Extension> QWrite for PropStat<E> {
|
||||
impl<E: Extension, N: Node<N>> QWrite for PropStat<E,N> {
|
||||
async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> {
|
||||
let start = xml.create_dav_element("propstat");
|
||||
let end = start.to_end();
|
||||
|
@ -681,7 +672,7 @@ mod tests {
|
|||
#[tokio::test]
|
||||
async fn basic_multistatus() {
|
||||
let got = serialize(
|
||||
&Multistatus::<Core> {
|
||||
&Multistatus::<Core, PropName<Core>> {
|
||||
responses: vec![],
|
||||
responsedescription: Some(ResponseDescription("Hello world".into()))
|
||||
},
|
||||
|
@ -730,18 +721,18 @@ mod tests {
|
|||
#[tokio::test]
|
||||
async fn rfc_propname_res() {
|
||||
let got = serialize(
|
||||
&Multistatus::<Core> {
|
||||
&Multistatus::<Core, PropName<Core>> {
|
||||
responses: vec![
|
||||
Response {
|
||||
status_or_propstat: StatusOrPropstat::PropStat(
|
||||
Href("http://www.example.com/container/".into()),
|
||||
vec![PropStat {
|
||||
prop: AnyProp::Name(PropName(vec![
|
||||
prop: PropName(vec![
|
||||
PropertyRequest::CreationDate,
|
||||
PropertyRequest::DisplayName,
|
||||
PropertyRequest::ResourceType,
|
||||
PropertyRequest::SupportedLock,
|
||||
])),
|
||||
]),
|
||||
status: Status(http::status::StatusCode::OK),
|
||||
error: None,
|
||||
responsedescription: None,
|
||||
|
@ -755,7 +746,7 @@ mod tests {
|
|||
status_or_propstat: StatusOrPropstat::PropStat(
|
||||
Href("http://www.example.com/container/front.html".into()),
|
||||
vec![PropStat {
|
||||
prop: AnyProp::Name(PropName(vec![
|
||||
prop: PropName(vec![
|
||||
PropertyRequest::CreationDate,
|
||||
PropertyRequest::DisplayName,
|
||||
PropertyRequest::GetContentLength,
|
||||
|
@ -764,7 +755,7 @@ mod tests {
|
|||
PropertyRequest::GetLastModified,
|
||||
PropertyRequest::ResourceType,
|
||||
PropertyRequest::SupportedLock,
|
||||
])),
|
||||
]),
|
||||
status: Status(http::status::StatusCode::OK),
|
||||
error: None,
|
||||
responsedescription: None,
|
||||
|
@ -831,13 +822,13 @@ mod tests {
|
|||
async fn rfc_allprop_res() {
|
||||
use chrono::{DateTime,FixedOffset,TimeZone};
|
||||
let got = serialize(
|
||||
&Multistatus::<Core> {
|
||||
&Multistatus::<Core, PropValue<Core>> {
|
||||
responses: vec![
|
||||
Response {
|
||||
status_or_propstat: StatusOrPropstat::PropStat(
|
||||
Href("/container/".into()),
|
||||
vec![PropStat {
|
||||
prop: AnyProp::Value(PropValue(vec![
|
||||
prop: PropValue(vec![
|
||||
Property::CreationDate(FixedOffset::west_opt(8 * 3600)
|
||||
.unwrap()
|
||||
.with_ymd_and_hms(1997, 12, 1, 17, 42, 21)
|
||||
|
@ -854,7 +845,7 @@ mod tests {
|
|||
locktype: LockType::Write,
|
||||
},
|
||||
]),
|
||||
])),
|
||||
]),
|
||||
status: Status(http::status::StatusCode::OK),
|
||||
error: None,
|
||||
responsedescription: None,
|
||||
|
@ -868,7 +859,7 @@ mod tests {
|
|||
status_or_propstat: StatusOrPropstat::PropStat(
|
||||
Href("/container/front.html".into()),
|
||||
vec![PropStat {
|
||||
prop: AnyProp::Value(PropValue(vec![
|
||||
prop: PropValue(vec![
|
||||
Property::CreationDate(FixedOffset::west_opt(8 * 3600)
|
||||
.unwrap()
|
||||
.with_ymd_and_hms(1997, 12, 1, 18, 27, 21)
|
||||
|
@ -892,7 +883,7 @@ mod tests {
|
|||
locktype: LockType::Write,
|
||||
},
|
||||
]),
|
||||
])),
|
||||
]),
|
||||
status: Status(http::status::StatusCode::OK),
|
||||
error: None,
|
||||
responsedescription: None,
|
||||
|
@ -1029,7 +1020,7 @@ mod tests {
|
|||
#[tokio::test]
|
||||
async fn rfc_delete_locked2() {
|
||||
let got = serialize(
|
||||
&Multistatus::<Core> {
|
||||
&Multistatus::<Core, PropValue<Core>> {
|
||||
responses: vec![Response {
|
||||
status_or_propstat: StatusOrPropstat::Status(
|
||||
vec![Href("http://www.example.com/container/resource3".into())],
|
||||
|
|
|
@ -7,12 +7,12 @@ use super::error;
|
|||
|
||||
/// It's how we implement a DAV extension
|
||||
/// (That's the dark magic part...)
|
||||
pub trait ExtensionItem<T> = xml::QRead<T> + xml::QWrite + Debug + PartialEq;
|
||||
pub trait Node<T> = xml::QRead<T> + xml::QWrite + Debug + PartialEq;
|
||||
pub trait Extension {
|
||||
type Error: ExtensionItem<Self::Error>;
|
||||
type Property: ExtensionItem<Self::Property>;
|
||||
type PropertyRequest: ExtensionItem<Self::PropertyRequest>;
|
||||
type ResourceType: ExtensionItem<Self::ResourceType>;
|
||||
type Error: Node<Self::Error>;
|
||||
type Property: Node<Self::Property>;
|
||||
type PropertyRequest: Node<Self::PropertyRequest>;
|
||||
type ResourceType: Node<Self::ResourceType>;
|
||||
}
|
||||
|
||||
/// 14.1. activelock XML Element
|
||||
|
@ -333,8 +333,8 @@ pub enum LockType {
|
|||
///
|
||||
/// <!ELEMENT multistatus (response*, responsedescription?) >
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct Multistatus<E: Extension> {
|
||||
pub responses: Vec<Response<E>>,
|
||||
pub struct Multistatus<E: Extension, N: Node<N>> {
|
||||
pub responses: Vec<Response<E, N>>,
|
||||
pub responsedescription: Option<ResponseDescription>,
|
||||
}
|
||||
|
||||
|
@ -383,12 +383,6 @@ pub enum Owner {
|
|||
/// text or mixed content.
|
||||
///
|
||||
/// <!ELEMENT prop ANY >
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum AnyProp<E: Extension> {
|
||||
Name(PropName<E>),
|
||||
Value(PropValue<E>),
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct PropName<E: Extension>(pub Vec<PropertyRequest<E>>);
|
||||
|
||||
|
@ -471,8 +465,8 @@ pub enum PropFind<E: Extension> {
|
|||
///
|
||||
/// <!ELEMENT propstat (prop, status, error?, responsedescription?) >
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct PropStat<E: Extension> {
|
||||
pub prop: AnyProp<E>,
|
||||
pub struct PropStat<E: Extension, N: Node<N>> {
|
||||
pub prop: N,
|
||||
pub status: Status,
|
||||
pub error: Option<Error<E>>,
|
||||
pub responsedescription: Option<ResponseDescription>,
|
||||
|
@ -520,16 +514,16 @@ pub struct Remove<E: Extension>(pub PropName<E>);
|
|||
/// --- rewritten as ---
|
||||
/// <!ELEMENT response ((href+, status)|(href, propstat+), error?, responsedescription?, location?>
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum StatusOrPropstat<E: Extension> {
|
||||
pub enum StatusOrPropstat<E: Extension, N: Node<N>> {
|
||||
// One status, multiple hrefs...
|
||||
Status(Vec<Href>, Status),
|
||||
// A single href, multiple properties...
|
||||
PropStat(Href, Vec<PropStat<E>>),
|
||||
PropStat(Href, Vec<PropStat<E, N>>),
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct Response<E: Extension> {
|
||||
pub status_or_propstat: StatusOrPropstat<E>,
|
||||
pub struct Response<E: Extension, N: Node<N>> {
|
||||
pub status_or_propstat: StatusOrPropstat<E, N>,
|
||||
pub error: Option<Error<E>>,
|
||||
pub responsedescription: Option<ResponseDescription>,
|
||||
pub location: Option<Location>,
|
||||
|
|
Loading…
Reference in a new issue