Refactor encoder+decoder WIP (compile)
This commit is contained in:
parent
b7a990ecdb
commit
8e5d8a8aaa
9 changed files with 689 additions and 447 deletions
|
@ -1,3 +1,4 @@
|
||||||
|
/*
|
||||||
use super::encoder::{QuickWritable, Context};
|
use super::encoder::{QuickWritable, Context};
|
||||||
use super::caltypes::*;
|
use super::caltypes::*;
|
||||||
use super::types::Extension;
|
use super::types::Extension;
|
||||||
|
@ -893,3 +894,4 @@ mod tests {
|
||||||
assert_eq!(&got, expected, "\n---GOT---\n{got}\n---EXP---\n{expected}\n");
|
assert_eq!(&got, expected, "\n---GOT---\n{got}\n---EXP---\n{expected}\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
|
|
||||||
|
/*
|
||||||
use chrono::{DateTime,Utc};
|
use chrono::{DateTime,Utc};
|
||||||
use super::types as Dav;
|
use super::types as dav;
|
||||||
|
|
||||||
//@FIXME ACL (rfc3744) is missing, required
|
//@FIXME ACL (rfc3744) is missing, required
|
||||||
//@FIXME Versioning (rfc3253) is missing, required
|
//@FIXME Versioning (rfc3253) is missing, required
|
||||||
|
@ -11,15 +12,6 @@ use super::types as Dav;
|
||||||
// For reference, non-official extensions documented by SabreDAV:
|
// For reference, non-official extensions documented by SabreDAV:
|
||||||
// https://github.com/apple/ccs-calendarserver/tree/master/doc/Extensions
|
// https://github.com/apple/ccs-calendarserver/tree/master/doc/Extensions
|
||||||
|
|
||||||
pub struct CalExtension {
|
|
||||||
pub root: bool
|
|
||||||
}
|
|
||||||
impl Dav::Extension for CalExtension {
|
|
||||||
type Error = Violation;
|
|
||||||
type Property = Property;
|
|
||||||
type PropertyRequest = PropertyRequest;
|
|
||||||
type ResourceType = ResourceType;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ----- Root elements -----
|
// ----- Root elements -----
|
||||||
|
|
||||||
|
@ -35,7 +27,7 @@ impl Dav::Extension for CalExtension {
|
||||||
/// instruction in Section 12.13.2 of [RFC2518].
|
/// instruction in Section 12.13.2 of [RFC2518].
|
||||||
///
|
///
|
||||||
/// <!ELEMENT mkcalendar (DAV:set)>
|
/// <!ELEMENT mkcalendar (DAV:set)>
|
||||||
pub struct MkCalendar<E: Dav::Extension>(pub Dav::Set<E>);
|
pub struct MkCalendar<E: dav::Extension>(pub dav::Set<E>);
|
||||||
|
|
||||||
|
|
||||||
/// If a response body for a successful request is included, it MUST
|
/// If a response body for a successful request is included, it MUST
|
||||||
|
@ -51,7 +43,7 @@ pub struct MkCalendar<E: Dav::Extension>(pub Dav::Set<E>);
|
||||||
/// Definition:
|
/// Definition:
|
||||||
///
|
///
|
||||||
/// <!ELEMENT mkcol-response (propstat+)>
|
/// <!ELEMENT mkcol-response (propstat+)>
|
||||||
pub struct MkCalendarResponse<T: Dav::Extension>(pub Vec<Dav::PropStat<T>>);
|
pub struct MkCalendarResponse<E: dav::Extension>(pub Vec<dav::PropStat<E>>);
|
||||||
|
|
||||||
// --- (REPORT PART) ---
|
// --- (REPORT PART) ---
|
||||||
|
|
||||||
|
@ -68,8 +60,8 @@ pub struct MkCalendarResponse<T: Dav::Extension>(pub Vec<Dav::PropStat<T>>);
|
||||||
/// <!ELEMENT calendar-query ((DAV:allprop |
|
/// <!ELEMENT calendar-query ((DAV:allprop |
|
||||||
/// DAV:propname |
|
/// DAV:propname |
|
||||||
/// DAV:prop)?, filter, timezone?)>
|
/// DAV:prop)?, filter, timezone?)>
|
||||||
pub struct CalendarQuery<T: Dav::Extension> {
|
pub struct CalendarQuery<E: dav::Extension> {
|
||||||
pub selector: Option<CalendarSelector<T>>,
|
pub selector: Option<CalendarSelector<E>>,
|
||||||
pub filter: Filter,
|
pub filter: Filter,
|
||||||
pub timezone: Option<TimeZone>,
|
pub timezone: Option<TimeZone>,
|
||||||
}
|
}
|
||||||
|
@ -88,9 +80,9 @@ pub struct CalendarQuery<T: Dav::Extension> {
|
||||||
/// <!ELEMENT calendar-multiget ((DAV:allprop |
|
/// <!ELEMENT calendar-multiget ((DAV:allprop |
|
||||||
/// DAV:propname |
|
/// DAV:propname |
|
||||||
/// DAV:prop)?, DAV:href+)>
|
/// DAV:prop)?, DAV:href+)>
|
||||||
pub struct CalendarMultiget<T: Dav::Extension> {
|
pub struct CalendarMultiget<E: dav::Extension> {
|
||||||
pub selector: Option<CalendarSelector<T>>,
|
pub selector: Option<CalendarSelector<E>>,
|
||||||
pub href: Vec<Dav::Href>,
|
pub href: Vec<dav::Href>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Name: free-busy-query
|
/// Name: free-busy-query
|
||||||
|
@ -1056,10 +1048,10 @@ pub struct LimitRecurrenceSet(pub DateTime<Utc>, pub DateTime<Utc>);
|
||||||
pub struct LimitFreebusySet(pub DateTime<Utc>, pub DateTime<Utc>);
|
pub struct LimitFreebusySet(pub DateTime<Utc>, pub DateTime<Utc>);
|
||||||
|
|
||||||
/// Used by CalendarQuery & CalendarMultiget
|
/// Used by CalendarQuery & CalendarMultiget
|
||||||
pub enum CalendarSelector<T: Dav::Extension> {
|
pub enum CalendarSelector<E: dav::Extension> {
|
||||||
AllProp,
|
AllProp,
|
||||||
PropName,
|
PropName,
|
||||||
Prop(Dav::PropName<T>),
|
Prop(dav::PropName<E>),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Name: comp-filter
|
/// Name: comp-filter
|
||||||
|
@ -1402,4 +1394,4 @@ impl Collation {
|
||||||
Self::Unknown(c) => c.as_str(),
|
Self::Unknown(c) => c.as_str(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
|
|
|
@ -8,33 +8,32 @@ use quick_xml::reader::NsReader;
|
||||||
use tokio::io::AsyncBufRead;
|
use tokio::io::AsyncBufRead;
|
||||||
|
|
||||||
use super::types::*;
|
use super::types::*;
|
||||||
|
use super::error::*;
|
||||||
|
|
||||||
#[derive(Debug)]
|
/*
|
||||||
pub enum ParsingError {
|
// --- Traits ----
|
||||||
NamespacePrefixAlreadyUsed,
|
|
||||||
WrongToken,
|
trait Reader = AsyncBufRead+Unpin+'static;
|
||||||
TagNotFound,
|
|
||||||
QuickXml(quick_xml::Error),
|
trait Decodable: Extension {
|
||||||
Eof
|
async fn decode_propreq(xml: &mut PeekRead<impl Reader>) -> Result<Option<Self::PropertyRequest>, ParsingError>;
|
||||||
}
|
}
|
||||||
impl From<AttrError> for ParsingError {
|
impl Decodable for NoExtension {
|
||||||
fn from(value: AttrError) -> Self {
|
async fn decode_propreq(xml: &mut PeekRead<impl Reader>) -> Result<Option<Disabled>, ParsingError> {
|
||||||
Self::QuickXml(value.into())
|
Ok(None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl From<quick_xml::Error> for ParsingError {
|
|
||||||
fn from(value: quick_xml::Error) -> Self {
|
pub trait QReadable<T: Reader>: Sized {
|
||||||
Self::QuickXml(value)
|
async fn read(xml: &mut PeekRead<T>) -> Result<Self, ParsingError>;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// --- Peek read with namespaces
|
||||||
|
|
||||||
const DAV_URN: &[u8] = b"DAV:";
|
const DAV_URN: &[u8] = b"DAV:";
|
||||||
const CALDAV_URN: &[u8] = b"urn:ietf:params:xml:ns:caldav";
|
const CALDAV_URN: &[u8] = b"urn:ietf:params:xml:ns:caldav";
|
||||||
const CARDDAV_URN: &[u8] = b"urn:ietf:params:xml:ns:carddav";
|
const CARDDAV_URN: &[u8] = b"urn:ietf:params:xml:ns:carddav";
|
||||||
//const XML_URN: &[u8] = b"xml";
|
//const XML_URN: &[u8] = b"xml";
|
||||||
|
|
||||||
trait Reader = AsyncBufRead+Unpin+'static;
|
|
||||||
|
|
||||||
pub struct PeekRead<T: Reader> {
|
pub struct PeekRead<T: Reader> {
|
||||||
evt: Event<'static>,
|
evt: Event<'static>,
|
||||||
rdr: NsReader<T>,
|
rdr: NsReader<T>,
|
||||||
|
@ -117,11 +116,9 @@ impl<T: Reader> PeekRead<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait QReadable<T: Reader>: Sized {
|
// ----- Decode ----
|
||||||
async fn read(xml: &mut PeekRead<T>) -> Result<Self, ParsingError>;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<E: Extension, T: Reader> QReadable<T> for PropFind<E> {
|
impl<E: Decodable, T: Reader> QReadable<T> for PropFind<E> {
|
||||||
async fn read(xml: &mut PeekRead<T>) -> Result<PropFind<E>, ParsingError> {
|
async fn read(xml: &mut PeekRead<T>) -> Result<PropFind<E>, ParsingError> {
|
||||||
// Find propfind
|
// Find propfind
|
||||||
xml.tag_start(DAV_URN, "propfind").await?;
|
xml.tag_start(DAV_URN, "propfind").await?;
|
||||||
|
@ -161,13 +158,13 @@ impl<E: Extension, T: Reader> QReadable<T> for PropFind<E> {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl<E: Extension, T: Reader> QReadable<T> for Include<E> {
|
impl<E: Decodable, T: Reader> QReadable<T> for Include<E> {
|
||||||
async fn read(xml: &mut PeekRead<T>) -> Result<Include<E>, ParsingError> {
|
async fn read(xml: &mut PeekRead<T>) -> Result<Include<E>, ParsingError> {
|
||||||
xml.tag_start(DAV_URN, "include").await?;
|
xml.tag_start(DAV_URN, "include").await?;
|
||||||
let mut acc: Vec<PropertyRequest<E>> = Vec::new();
|
let mut acc: Vec<PropertyRequest<E>> = Vec::new();
|
||||||
loop {
|
loop {
|
||||||
match xml.peek() {
|
match xml.peek() {
|
||||||
Event::Start(_) => acc.push(PropertyRequest::read(xml).await?),
|
Event::Start(_) | Event::Empty(_) => acc.push(PropertyRequest::read(xml).await?),
|
||||||
Event::End(_) if xml.is_tag(DAV_URN, "include") => break,
|
Event::End(_) if xml.is_tag(DAV_URN, "include") => break,
|
||||||
_ => { xml.skip().await?; },
|
_ => { xml.skip().await?; },
|
||||||
}
|
}
|
||||||
|
@ -177,13 +174,13 @@ impl<E: Extension, T: Reader> QReadable<T> for Include<E> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E: Extension, T: Reader> QReadable<T> for PropName<E> {
|
impl<E: Decodable, T: Reader> QReadable<T> for PropName<E> {
|
||||||
async fn read(xml: &mut PeekRead<T>) -> Result<PropName<E>, ParsingError> {
|
async fn read(xml: &mut PeekRead<T>) -> Result<PropName<E>, ParsingError> {
|
||||||
xml.tag_start(DAV_URN, "prop").await?;
|
xml.tag_start(DAV_URN, "prop").await?;
|
||||||
let mut acc: Vec<PropertyRequest<E>> = Vec::new();
|
let mut acc: Vec<PropertyRequest<E>> = Vec::new();
|
||||||
loop {
|
loop {
|
||||||
match xml.peek() {
|
match xml.peek() {
|
||||||
Event::Start(_) => acc.push(PropertyRequest::read(xml).await?),
|
Event::Start(_) | Event::Empty(_) => acc.push(PropertyRequest::read(xml).await?),
|
||||||
Event::End(_) if xml.is_tag(DAV_URN, "prop") => break,
|
Event::End(_) if xml.is_tag(DAV_URN, "prop") => break,
|
||||||
_ => { xml.skip().await?; },
|
_ => { xml.skip().await?; },
|
||||||
}
|
}
|
||||||
|
@ -193,12 +190,52 @@ impl<E: Extension, T: Reader> QReadable<T> for PropName<E> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E: Extension, T: Reader> QReadable<T> for PropertyRequest<E> {
|
impl<E: Decodable, T: Reader> QReadable<T> for PropertyRequest<E> {
|
||||||
async fn read(xml: &mut PeekRead<T>) -> Result<PropertyRequest<E>, ParsingError> {
|
async fn read(xml: &mut PeekRead<T>) -> Result<PropertyRequest<E>, ParsingError> {
|
||||||
/*match xml.peek() {
|
loop {
|
||||||
|
let (need_close, bs) = match xml.peek() {
|
||||||
|
Event::Start(b) => (true, b),
|
||||||
|
Event::Empty(b) => (false, b),
|
||||||
|
_ => {
|
||||||
|
xml.skip().await?;
|
||||||
|
continue
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
}*/
|
let mut maybe_res = None;
|
||||||
unimplemented!();
|
|
||||||
|
// Option 1: a pure DAV property
|
||||||
|
let (ns, loc) = xml.rdr.resolve_element(bs.name());
|
||||||
|
if matches!(ns, Bound(Namespace(ns)) if ns == DAV_URN) {
|
||||||
|
maybe_res = match loc.into_inner() {
|
||||||
|
b"creationdate" => Some(PropertyRequest::CreationDate),
|
||||||
|
b"displayname" => Some(PropertyRequest::DisplayName),
|
||||||
|
b"getcontentlanguage" => Some(PropertyRequest::GetContentLanguage),
|
||||||
|
b"getcontentlength" => Some(PropertyRequest::GetContentLength),
|
||||||
|
b"getetag" => Some(PropertyRequest::GetEtag),
|
||||||
|
b"getlastmodified" => Some(PropertyRequest::GetLastModified),
|
||||||
|
b"lockdiscovery" => Some(PropertyRequest::LockDiscovery),
|
||||||
|
b"resourcetype" => Some(PropertyRequest::ResourceType),
|
||||||
|
b"supportedlock" => Some(PropertyRequest::SupportedLock),
|
||||||
|
_ => None,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Option 2: an extension property
|
||||||
|
if maybe_res.is_none() {
|
||||||
|
maybe_res = E::decode_propreq(xml).await?.map(PropertyRequest::Extension);
|
||||||
|
}
|
||||||
|
|
||||||
|
// In any cases, we must close the opened tag
|
||||||
|
if need_close {
|
||||||
|
xml.skip().await?;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return if something is found - otherwise loop
|
||||||
|
if let Some(res) = maybe_res {
|
||||||
|
return Ok(res)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -207,7 +244,7 @@ mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn basic_propfind() {
|
async fn basic_propfind_propname() {
|
||||||
let src = r#"<?xml version="1.0" encoding="utf-8" ?>
|
let src = r#"<?xml version="1.0" encoding="utf-8" ?>
|
||||||
<rando/>
|
<rando/>
|
||||||
<garbage><old/></garbage>
|
<garbage><old/></garbage>
|
||||||
|
@ -220,4 +257,37 @@ mod tests {
|
||||||
let got = PropFind::<NoExtension>::read(&mut rdr).await.unwrap();
|
let got = PropFind::<NoExtension>::read(&mut rdr).await.unwrap();
|
||||||
assert!(matches!(got, PropFind::PropName));
|
assert!(matches!(got, PropFind::PropName));
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
#[tokio::test]
|
||||||
|
async fn basic_propfind_prop() {
|
||||||
|
let src = r#"<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
<rando/>
|
||||||
|
<garbage><old/></garbage>
|
||||||
|
<D:propfind xmlns:D="DAV:">
|
||||||
|
<D:prop>
|
||||||
|
<displayname/>
|
||||||
|
<getcontentlength/>
|
||||||
|
<getcontenttype/>
|
||||||
|
<getetag/>
|
||||||
|
<getlastmodified/>
|
||||||
|
<resourcetype/>
|
||||||
|
<supportedlock/>
|
||||||
|
</D:prop>
|
||||||
|
</D:propfind>
|
||||||
|
"#;
|
||||||
|
|
||||||
|
let mut rdr = PeekRead::new(NsReader::from_reader(src.as_bytes())).await.unwrap();
|
||||||
|
let got = PropFind::<NoExtension>::read(&mut rdr).await.unwrap();
|
||||||
|
assert_eq!(got, PropFind::Prop(PropName(vec![
|
||||||
|
PropertyRequest::DisplayName,
|
||||||
|
PropertyRequest::GetContentLength,
|
||||||
|
PropertyRequest::GetContentType,
|
||||||
|
PropertyRequest::GetEtag,
|
||||||
|
PropertyRequest::GetLastModified,
|
||||||
|
PropertyRequest::ResourceType,
|
||||||
|
PropertyRequest::SupportedLock,
|
||||||
|
])));
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
|
@ -2,390 +2,339 @@ use std::io::Cursor;
|
||||||
|
|
||||||
use quick_xml::Error as QError;
|
use quick_xml::Error as QError;
|
||||||
use quick_xml::events::{Event, BytesEnd, BytesStart, BytesText};
|
use quick_xml::events::{Event, BytesEnd, BytesStart, BytesText};
|
||||||
use quick_xml::writer::{ElementWriter, Writer};
|
use quick_xml::writer::ElementWriter;
|
||||||
use quick_xml::name::PrefixDeclaration;
|
use quick_xml::name::PrefixDeclaration;
|
||||||
use tokio::io::AsyncWrite;
|
use tokio::io::AsyncWrite;
|
||||||
use super::types::*;
|
use super::types::*;
|
||||||
|
use super::xml::{Writer,QWrite,IWrite};
|
||||||
|
|
||||||
|
|
||||||
//-------------- TRAITS ----------------------
|
|
||||||
|
|
||||||
/// Basic encode trait to make a type encodable
|
|
||||||
pub trait QuickWritable<C: Context> {
|
|
||||||
async fn write(&self, xml: &mut Writer<impl AsyncWrite+Unpin>, ctx: C) -> Result<(), QError>;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Encoding context
|
|
||||||
pub trait Context: Extension {
|
|
||||||
fn child(&self) -> Self;
|
|
||||||
fn create_dav_element(&self, name: &str) -> BytesStart;
|
|
||||||
async fn hook_error(&self, err: &Self::Error, xml: &mut Writer<impl AsyncWrite+Unpin>) -> Result<(), QError>;
|
|
||||||
async fn hook_property(&self, prop: &Self::Property, xml: &mut Writer<impl AsyncWrite+Unpin>) -> Result<(), QError>;
|
|
||||||
async fn hook_propertyrequest(&self, prop: &Self::PropertyRequest, xml: &mut Writer<impl AsyncWrite+Unpin>) -> Result<(), QError>;
|
|
||||||
async fn hook_resourcetype(&self, prop: &Self::ResourceType, xml: &mut Writer<impl AsyncWrite+Unpin>) -> Result<(), QError>;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// -------------- NoExtension Encoding Context
|
|
||||||
impl Context for NoExtension {
|
|
||||||
fn child(&self) -> Self {
|
|
||||||
Self { root: false }
|
|
||||||
}
|
|
||||||
fn create_dav_element(&self, name: &str) -> BytesStart {
|
|
||||||
let mut start = BytesStart::new(format!("D:{}", name));
|
|
||||||
if self.root {
|
|
||||||
start.push_attribute(("xmlns:D", "DAV:"));
|
|
||||||
}
|
|
||||||
start
|
|
||||||
}
|
|
||||||
async fn hook_error(&self, _err: &Disabled, _xml: &mut Writer<impl AsyncWrite+Unpin>) -> Result<(), QError> {
|
|
||||||
unreachable!();
|
|
||||||
}
|
|
||||||
async fn hook_property(&self, _prop: &Disabled, _xml: &mut Writer<impl AsyncWrite+Unpin>) -> Result<(), QError> {
|
|
||||||
unreachable!();
|
|
||||||
}
|
|
||||||
async fn hook_propertyrequest(&self, _prop: &Disabled, _xml: &mut Writer<impl AsyncWrite+Unpin>) -> Result<(), QError> {
|
|
||||||
unreachable!();
|
|
||||||
}
|
|
||||||
async fn hook_resourcetype(&self, _restype: &Disabled, _xml: &mut Writer<impl AsyncWrite+Unpin>) -> Result<(), QError> {
|
|
||||||
unreachable!();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//--------------------- ENCODING --------------------
|
|
||||||
|
|
||||||
// --- XML ROOTS
|
// --- XML ROOTS
|
||||||
|
|
||||||
/// PROPFIND REQUEST
|
/// PROPFIND REQUEST
|
||||||
impl<C: Context> QuickWritable<C> for PropFind<C> {
|
impl<E: Extension> QWrite for PropFind<E> {
|
||||||
async fn write(&self, xml: &mut Writer<impl AsyncWrite+Unpin>, ctx: C) -> Result<(), QError> {
|
async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> {
|
||||||
let start = ctx.create_dav_element("propfind");
|
let start = xml.create_dav_element("propfind");
|
||||||
let end = start.to_end();
|
let end = start.to_end();
|
||||||
let ctx = ctx.child();
|
|
||||||
|
|
||||||
xml.write_event_async(Event::Start(start.clone())).await?;
|
xml.q.write_event_async(Event::Start(start.clone())).await?;
|
||||||
match self {
|
match self {
|
||||||
Self::PropName => xml.write_event_async(Event::Empty(ctx.create_dav_element("propname"))).await?,
|
Self::PropName => {
|
||||||
|
let empty_propname = xml.create_dav_element("propname");
|
||||||
|
xml.q.write_event_async(Event::Empty(empty_propname)).await?
|
||||||
|
},
|
||||||
Self::AllProp(maybe_include) => {
|
Self::AllProp(maybe_include) => {
|
||||||
xml.write_event_async(Event::Empty(ctx.create_dav_element("allprop"))).await?;
|
let empty_allprop = xml.create_dav_element("allprop");
|
||||||
|
xml.q.write_event_async(Event::Empty(empty_allprop)).await?;
|
||||||
if let Some(include) = maybe_include {
|
if let Some(include) = maybe_include {
|
||||||
include.write(xml, ctx.child()).await?;
|
include.qwrite(xml).await?;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Self::Prop(propname) => propname.write(xml, ctx.child()).await?,
|
Self::Prop(propname) => propname.qwrite(xml).await?,
|
||||||
}
|
}
|
||||||
xml.write_event_async(Event::End(end)).await
|
xml.q.write_event_async(Event::End(end)).await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// PROPPATCH REQUEST
|
/// PROPPATCH REQUEST
|
||||||
impl<C: Context> QuickWritable<C> for PropertyUpdate<C> {
|
impl<E: Extension> QWrite for PropertyUpdate<E> {
|
||||||
async fn write(&self, xml: &mut Writer<impl AsyncWrite+Unpin>, ctx: C) -> Result<(), QError> {
|
async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> {
|
||||||
let start = ctx.create_dav_element("propertyupdate");
|
let start = xml.create_dav_element("propertyupdate");
|
||||||
let end = start.to_end();
|
let end = start.to_end();
|
||||||
|
|
||||||
xml.write_event_async(Event::Start(start.clone())).await?;
|
xml.q.write_event_async(Event::Start(start.clone())).await?;
|
||||||
for update in self.0.iter() {
|
for update in self.0.iter() {
|
||||||
update.write(xml, ctx.child()).await?;
|
update.qwrite(xml).await?;
|
||||||
}
|
}
|
||||||
xml.write_event_async(Event::End(end)).await
|
xml.q.write_event_async(Event::End(end)).await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// PROPFIND RESPONSE, PROPPATCH RESPONSE, COPY RESPONSE, MOVE RESPONSE
|
/// PROPFIND RESPONSE, PROPPATCH RESPONSE, COPY RESPONSE, MOVE RESPONSE
|
||||||
/// DELETE RESPONSE,
|
/// DELETE RESPONSE,
|
||||||
impl<C: Context> QuickWritable<C> for Multistatus<C> {
|
impl<E: Extension> QWrite for Multistatus<E> {
|
||||||
async fn write(&self, xml: &mut Writer<impl AsyncWrite+Unpin>, ctx: C) -> Result<(), QError> {
|
async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> {
|
||||||
let start = ctx.create_dav_element("multistatus");
|
let start = xml.create_dav_element("multistatus");
|
||||||
let end = start.to_end();
|
let end = start.to_end();
|
||||||
|
|
||||||
xml.write_event_async(Event::Start(start.clone())).await?;
|
xml.q.write_event_async(Event::Start(start.clone())).await?;
|
||||||
for response in self.responses.iter() {
|
for response in self.responses.iter() {
|
||||||
response.write(xml, ctx.child()).await?;
|
response.qwrite(xml).await?;
|
||||||
}
|
}
|
||||||
if let Some(description) = &self.responsedescription {
|
if let Some(description) = &self.responsedescription {
|
||||||
description.write(xml, ctx.child()).await?;
|
description.qwrite(xml).await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
xml.write_event_async(Event::End(end)).await?;
|
xml.q.write_event_async(Event::End(end)).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// LOCK REQUEST
|
/// LOCK REQUEST
|
||||||
impl<C: Context> QuickWritable<C> for LockInfo {
|
impl QWrite for LockInfo {
|
||||||
async fn write(&self, xml: &mut Writer<impl AsyncWrite+Unpin>, ctx: C) -> Result<(), QError> {
|
async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> {
|
||||||
let start = ctx.create_dav_element("lockinfo");
|
let start = xml.create_dav_element("lockinfo");
|
||||||
let end = start.to_end();
|
let end = start.to_end();
|
||||||
|
|
||||||
xml.write_event_async(Event::Start(start.clone())).await?;
|
xml.q.write_event_async(Event::Start(start.clone())).await?;
|
||||||
self.lockscope.write(xml, ctx.child()).await?;
|
self.lockscope.qwrite(xml).await?;
|
||||||
self.locktype.write(xml, ctx.child()).await?;
|
self.locktype.qwrite(xml).await?;
|
||||||
if let Some(owner) = &self.owner {
|
if let Some(owner) = &self.owner {
|
||||||
owner.write(xml, ctx.child()).await?;
|
owner.qwrite(xml).await?;
|
||||||
}
|
}
|
||||||
xml.write_event_async(Event::End(end)).await
|
xml.q.write_event_async(Event::End(end)).await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// SOME LOCK RESPONSES
|
/// SOME LOCK RESPONSES
|
||||||
impl<C: Context> QuickWritable<C> for PropValue<C> {
|
impl<E: Extension> QWrite for PropValue<E> {
|
||||||
async fn write(&self, xml: &mut Writer<impl AsyncWrite+Unpin>, ctx: C) -> Result<(), QError> {
|
async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> {
|
||||||
let start = ctx.create_dav_element("prop");
|
let start = xml.create_dav_element("prop");
|
||||||
let end = start.to_end();
|
let end = start.to_end();
|
||||||
|
|
||||||
xml.write_event_async(Event::Start(start.clone())).await?;
|
xml.q.write_event_async(Event::Start(start.clone())).await?;
|
||||||
for propval in &self.0 {
|
for propval in &self.0 {
|
||||||
propval.write(xml, ctx.child()).await?;
|
propval.qwrite(xml).await?;
|
||||||
}
|
}
|
||||||
xml.write_event_async(Event::End(end)).await
|
xml.q.write_event_async(Event::End(end)).await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- XML inner elements
|
// --- XML inner elements
|
||||||
impl<C: Context> QuickWritable<C> for PropertyUpdateItem<C> {
|
impl<E: Extension> QWrite for PropertyUpdateItem<E> {
|
||||||
async fn write(&self, xml: &mut Writer<impl AsyncWrite+Unpin>, ctx: C) -> Result<(), QError> {
|
async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> {
|
||||||
match self {
|
match self {
|
||||||
Self::Set(set) => set.write(xml, ctx).await,
|
Self::Set(set) => set.qwrite(xml).await,
|
||||||
Self::Remove(rm) => rm.write(xml, ctx).await,
|
Self::Remove(rm) => rm.qwrite(xml).await,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C: Context> QuickWritable<C> for Set<C> {
|
impl<E: Extension> QWrite for Set<E> {
|
||||||
async fn write(&self, xml: &mut Writer<impl AsyncWrite+Unpin>, ctx: C) -> Result<(), QError> {
|
async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> {
|
||||||
let start = ctx.create_dav_element("set");
|
let start = xml.create_dav_element("set");
|
||||||
let end = start.to_end();
|
let end = start.to_end();
|
||||||
xml.write_event_async(Event::Start(start.clone())).await?;
|
xml.q.write_event_async(Event::Start(start.clone())).await?;
|
||||||
self.0.write(xml, ctx.child()).await?;
|
self.0.qwrite(xml).await?;
|
||||||
xml.write_event_async(Event::End(end)).await
|
xml.q.write_event_async(Event::End(end)).await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C: Context> QuickWritable<C> for Remove<C> {
|
impl<E: Extension> QWrite for Remove<E> {
|
||||||
async fn write(&self, xml: &mut Writer<impl AsyncWrite+Unpin>, ctx: C) -> Result<(), QError> {
|
async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> {
|
||||||
let start = ctx.create_dav_element("remove");
|
let start = xml.create_dav_element("remove");
|
||||||
let end = start.to_end();
|
let end = start.to_end();
|
||||||
xml.write_event_async(Event::Start(start.clone())).await?;
|
xml.q.write_event_async(Event::Start(start.clone())).await?;
|
||||||
self.0.write(xml, ctx.child()).await?;
|
self.0.qwrite(xml).await?;
|
||||||
xml.write_event_async(Event::End(end)).await
|
xml.q.write_event_async(Event::End(end)).await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl<C: Context> QuickWritable<C> for AnyProp<C> {
|
impl<E: Extension> QWrite for AnyProp<E> {
|
||||||
async fn write(&self, xml: &mut Writer<impl AsyncWrite+Unpin>, ctx: C) -> Result<(), QError> {
|
async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> {
|
||||||
match self {
|
match self {
|
||||||
Self::Name(propname) => propname.write(xml, ctx).await,
|
Self::Name(propname) => propname.qwrite(xml).await,
|
||||||
Self::Value(propval) => propval.write(xml, ctx).await,
|
Self::Value(propval) => propval.qwrite(xml).await,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C: Context> QuickWritable<C> for PropName<C> {
|
impl<E: Extension> QWrite for PropName<E> {
|
||||||
async fn write(&self, xml: &mut Writer<impl AsyncWrite+Unpin>, ctx: C) -> Result<(), QError> {
|
async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> {
|
||||||
let start = ctx.create_dav_element("prop");
|
let start = xml.create_dav_element("prop");
|
||||||
let end = start.to_end();
|
let end = start.to_end();
|
||||||
|
|
||||||
xml.write_event_async(Event::Start(start.clone())).await?;
|
xml.q.write_event_async(Event::Start(start.clone())).await?;
|
||||||
for propname in &self.0 {
|
for propname in &self.0 {
|
||||||
propname.write(xml, ctx.child()).await?;
|
propname.qwrite(xml).await?;
|
||||||
}
|
}
|
||||||
xml.write_event_async(Event::End(end)).await
|
xml.q.write_event_async(Event::End(end)).await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl<C: Context> QuickWritable<C> for Href {
|
impl QWrite for Href {
|
||||||
async fn write(&self, xml: &mut Writer<impl AsyncWrite+Unpin>, ctx: C) -> Result<(), QError> {
|
async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> {
|
||||||
let start = ctx.create_dav_element("href");
|
let start = xml.create_dav_element("href");
|
||||||
let end = start.to_end();
|
let end = start.to_end();
|
||||||
|
|
||||||
xml.write_event_async(Event::Start(start.clone())).await?;
|
xml.q.write_event_async(Event::Start(start.clone())).await?;
|
||||||
xml.write_event_async(Event::Text(BytesText::new(&self.0))).await?;
|
xml.q.write_event_async(Event::Text(BytesText::new(&self.0))).await?;
|
||||||
xml.write_event_async(Event::End(end)).await?;
|
xml.q.write_event_async(Event::End(end)).await
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C: Context> QuickWritable<C> for Response<C> {
|
impl<E: Extension> QWrite for Response<E> {
|
||||||
async fn write(&self, xml: &mut Writer<impl AsyncWrite+Unpin>, ctx: C) -> Result<(), QError> {
|
async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> {
|
||||||
let start = ctx.create_dav_element("response");
|
let start = xml.create_dav_element("response");
|
||||||
let end = start.to_end();
|
let end = start.to_end();
|
||||||
|
|
||||||
xml.write_event_async(Event::Start(start.clone())).await?;
|
xml.q.write_event_async(Event::Start(start.clone())).await?;
|
||||||
self.href.write(xml, ctx.child()).await?;
|
self.href.qwrite(xml).await?;
|
||||||
self.status_or_propstat.write(xml, ctx.child()).await?;
|
self.status_or_propstat.qwrite(xml).await?;
|
||||||
if let Some(error) = &self.error {
|
if let Some(error) = &self.error {
|
||||||
error.write(xml, ctx.child()).await?;
|
error.qwrite(xml).await?;
|
||||||
}
|
}
|
||||||
if let Some(responsedescription) = &self.responsedescription {
|
if let Some(responsedescription) = &self.responsedescription {
|
||||||
responsedescription.write(xml, ctx.child()).await?;
|
responsedescription.qwrite(xml).await?;
|
||||||
}
|
}
|
||||||
if let Some(location) = &self.location {
|
if let Some(location) = &self.location {
|
||||||
location.write(xml, ctx.child()).await?;
|
location.qwrite(xml).await?;
|
||||||
}
|
}
|
||||||
xml.write_event_async(Event::End(end)).await?;
|
xml.q.write_event_async(Event::End(end)).await
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C: Context> QuickWritable<C> for StatusOrPropstat<C> {
|
impl<E: Extension> QWrite for StatusOrPropstat<E> {
|
||||||
async fn write(&self, xml: &mut Writer<impl AsyncWrite+Unpin>, ctx: C) -> Result<(), QError> {
|
async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> {
|
||||||
match self {
|
match self {
|
||||||
Self::Status(status) => status.write(xml, ctx.child()).await,
|
Self::Status(status) => status.qwrite(xml).await,
|
||||||
Self::PropStat(propstat_list) => {
|
Self::PropStat(propstat_list) => {
|
||||||
for propstat in propstat_list.iter() {
|
for propstat in propstat_list.iter() {
|
||||||
propstat.write(xml, ctx.child()).await?;
|
propstat.qwrite(xml).await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C: Context> QuickWritable<C> for Status {
|
impl QWrite for Status {
|
||||||
async fn write(&self, xml: &mut Writer<impl AsyncWrite+Unpin>, ctx: C) -> Result<(), QError> {
|
async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> {
|
||||||
let start = ctx.create_dav_element("status");
|
let start = xml.create_dav_element("status");
|
||||||
let end = start.to_end();
|
let end = start.to_end();
|
||||||
|
|
||||||
xml.write_event_async(Event::Start(start.clone())).await?;
|
xml.q.write_event_async(Event::Start(start.clone())).await?;
|
||||||
|
|
||||||
let txt = format!("HTTP/1.1 {} {}", self.0.as_str(), self.0.canonical_reason().unwrap_or("No reason"));
|
let txt = format!("HTTP/1.1 {} {}", self.0.as_str(), self.0.canonical_reason().unwrap_or("No reason"));
|
||||||
xml.write_event_async(Event::Text(BytesText::new(&txt))).await?;
|
xml.q.write_event_async(Event::Text(BytesText::new(&txt))).await?;
|
||||||
|
|
||||||
xml.write_event_async(Event::End(end)).await?;
|
xml.q.write_event_async(Event::End(end)).await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C: Context> QuickWritable<C> for ResponseDescription {
|
impl QWrite for ResponseDescription {
|
||||||
async fn write(&self, xml: &mut Writer<impl AsyncWrite+Unpin>, ctx: C) -> Result<(), QError> {
|
async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> {
|
||||||
let start = ctx.create_dav_element("responsedescription");
|
let start = xml.create_dav_element("responsedescription");
|
||||||
let end = start.to_end();
|
let end = start.to_end();
|
||||||
|
|
||||||
xml.write_event_async(Event::Start(start.clone())).await?;
|
xml.q.write_event_async(Event::Start(start.clone())).await?;
|
||||||
xml.write_event_async(Event::Text(BytesText::new(&self.0))).await?;
|
xml.q.write_event_async(Event::Text(BytesText::new(&self.0))).await?;
|
||||||
xml.write_event_async(Event::End(end)).await?;
|
xml.q.write_event_async(Event::End(end)).await
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C: Context> QuickWritable<C> for Location {
|
impl QWrite for Location {
|
||||||
async fn write(&self, xml: &mut Writer<impl AsyncWrite+Unpin>, ctx: C) -> Result<(), QError> {
|
async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> {
|
||||||
let start = ctx.create_dav_element("location");
|
let start = xml.create_dav_element("location");
|
||||||
let end = start.to_end();
|
let end = start.to_end();
|
||||||
|
|
||||||
xml.write_event_async(Event::Start(start.clone())).await?;
|
xml.q.write_event_async(Event::Start(start.clone())).await?;
|
||||||
self.0.write(xml, ctx.child()).await?;
|
self.0.qwrite(xml).await?;
|
||||||
xml.write_event_async(Event::End(end)).await?;
|
xml.q.write_event_async(Event::End(end)).await
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C: Context> QuickWritable<C> for PropStat<C> {
|
impl<E: Extension> QWrite for PropStat<E> {
|
||||||
async fn write(&self, xml: &mut Writer<impl AsyncWrite+Unpin>, ctx: C) -> Result<(), QError> {
|
async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> {
|
||||||
let start = ctx.create_dav_element("propstat");
|
let start = xml.create_dav_element("propstat");
|
||||||
let end = start.to_end();
|
let end = start.to_end();
|
||||||
|
|
||||||
xml.write_event_async(Event::Start(start.clone())).await?;
|
xml.q.write_event_async(Event::Start(start.clone())).await?;
|
||||||
self.prop.write(xml, ctx.child()).await?;
|
self.prop.qwrite(xml).await?;
|
||||||
self.status.write(xml, ctx.child()).await?;
|
self.status.qwrite(xml).await?;
|
||||||
if let Some(error) = &self.error {
|
if let Some(error) = &self.error {
|
||||||
error.write(xml, ctx.child()).await?;
|
error.qwrite(xml).await?;
|
||||||
}
|
}
|
||||||
if let Some(description) = &self.responsedescription {
|
if let Some(description) = &self.responsedescription {
|
||||||
description.write(xml, ctx.child()).await?;
|
description.qwrite(xml).await?;
|
||||||
}
|
}
|
||||||
xml.write_event_async(Event::End(end)).await?;
|
xml.q.write_event_async(Event::End(end)).await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C: Context> QuickWritable<C> for Property<C> {
|
impl<E: Extension> QWrite for Property<E> {
|
||||||
async fn write(&self, xml: &mut Writer<impl AsyncWrite+Unpin>, ctx: C) -> Result<(), QError> {
|
async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> {
|
||||||
use Property::*;
|
use Property::*;
|
||||||
match self {
|
match self {
|
||||||
CreationDate(date) => {
|
CreationDate(date) => {
|
||||||
// <D:creationdate>1997-12-01T17:42:21-08:00</D:creationdate>
|
// <D:creationdate>1997-12-01T17:42:21-08:00</D:creationdate>
|
||||||
let start = ctx.create_dav_element("creationdate");
|
let start = xml.create_dav_element("creationdate");
|
||||||
let end = start.to_end();
|
let end = start.to_end();
|
||||||
|
|
||||||
xml.write_event_async(Event::Start(start.clone())).await?;
|
xml.q.write_event_async(Event::Start(start.clone())).await?;
|
||||||
xml.write_event_async(Event::Text(BytesText::new(&date.to_rfc3339()))).await?;
|
xml.q.write_event_async(Event::Text(BytesText::new(&date.to_rfc3339()))).await?;
|
||||||
xml.write_event_async(Event::End(end)).await?;
|
xml.q.write_event_async(Event::End(end)).await?;
|
||||||
},
|
},
|
||||||
DisplayName(name) => {
|
DisplayName(name) => {
|
||||||
// <D:displayname>Example collection</D:displayname>
|
// <D:displayname>Example collection</D:displayname>
|
||||||
let start = ctx.create_dav_element("displayname");
|
let start = xml.create_dav_element("displayname");
|
||||||
let end = start.to_end();
|
let end = start.to_end();
|
||||||
|
|
||||||
xml.write_event_async(Event::Start(start.clone())).await?;
|
xml.q.write_event_async(Event::Start(start.clone())).await?;
|
||||||
xml.write_event_async(Event::Text(BytesText::new(name))).await?;
|
xml.q.write_event_async(Event::Text(BytesText::new(name))).await?;
|
||||||
xml.write_event_async(Event::End(end)).await?;
|
xml.q.write_event_async(Event::End(end)).await?;
|
||||||
},
|
},
|
||||||
GetContentLanguage(lang) => {
|
GetContentLanguage(lang) => {
|
||||||
let start = ctx.create_dav_element("getcontentlanguage");
|
let start = xml.create_dav_element("getcontentlanguage");
|
||||||
let end = start.to_end();
|
let end = start.to_end();
|
||||||
|
|
||||||
xml.write_event_async(Event::Start(start.clone())).await?;
|
xml.q.write_event_async(Event::Start(start.clone())).await?;
|
||||||
xml.write_event_async(Event::Text(BytesText::new(lang))).await?;
|
xml.q.write_event_async(Event::Text(BytesText::new(lang))).await?;
|
||||||
xml.write_event_async(Event::End(end)).await?;
|
xml.q.write_event_async(Event::End(end)).await?;
|
||||||
},
|
},
|
||||||
GetContentLength(len) => {
|
GetContentLength(len) => {
|
||||||
// <D:getcontentlength>4525</D:getcontentlength>
|
// <D:getcontentlength>4525</D:getcontentlength>
|
||||||
let start = ctx.create_dav_element("getcontentlength");
|
let start = xml.create_dav_element("getcontentlength");
|
||||||
let end = start.to_end();
|
let end = start.to_end();
|
||||||
|
|
||||||
xml.write_event_async(Event::Start(start.clone())).await?;
|
xml.q.write_event_async(Event::Start(start.clone())).await?;
|
||||||
xml.write_event_async(Event::Text(BytesText::new(&len.to_string()))).await?;
|
xml.q.write_event_async(Event::Text(BytesText::new(&len.to_string()))).await?;
|
||||||
xml.write_event_async(Event::End(end)).await?;
|
xml.q.write_event_async(Event::End(end)).await?;
|
||||||
},
|
},
|
||||||
GetContentType(ct) => {
|
GetContentType(ct) => {
|
||||||
// <D:getcontenttype>text/html</D:getcontenttype>
|
// <D:getcontenttype>text/html</D:getcontenttype>
|
||||||
let start = ctx.create_dav_element("getcontenttype");
|
let start = xml.create_dav_element("getcontenttype");
|
||||||
let end = start.to_end();
|
let end = start.to_end();
|
||||||
|
|
||||||
xml.write_event_async(Event::Start(start.clone())).await?;
|
xml.q.write_event_async(Event::Start(start.clone())).await?;
|
||||||
xml.write_event_async(Event::Text(BytesText::new(&ct))).await?;
|
xml.q.write_event_async(Event::Text(BytesText::new(&ct))).await?;
|
||||||
xml.write_event_async(Event::End(end)).await?;
|
xml.q.write_event_async(Event::End(end)).await?;
|
||||||
},
|
},
|
||||||
GetEtag(et) => {
|
GetEtag(et) => {
|
||||||
// <D:getetag>"zzyzx"</D:getetag>
|
// <D:getetag>"zzyzx"</D:getetag>
|
||||||
let start = ctx.create_dav_element("getetag");
|
let start = xml.create_dav_element("getetag");
|
||||||
let end = start.to_end();
|
let end = start.to_end();
|
||||||
|
|
||||||
xml.write_event_async(Event::Start(start.clone())).await?;
|
xml.q.write_event_async(Event::Start(start.clone())).await?;
|
||||||
xml.write_event_async(Event::Text(BytesText::new(et))).await?;
|
xml.q.write_event_async(Event::Text(BytesText::new(et))).await?;
|
||||||
xml.write_event_async(Event::End(end)).await?;
|
xml.q.write_event_async(Event::End(end)).await?;
|
||||||
},
|
},
|
||||||
GetLastModified(date) => {
|
GetLastModified(date) => {
|
||||||
// <D:getlastmodified>Mon, 12 Jan 1998 09:25:56 GMT</D:getlastmodified>
|
// <D:getlastmodified>Mon, 12 Jan 1998 09:25:56 GMT</D:getlastmodified>
|
||||||
let start = ctx.create_dav_element("getlastmodified");
|
let start = xml.create_dav_element("getlastmodified");
|
||||||
let end = start.to_end();
|
let end = start.to_end();
|
||||||
|
|
||||||
xml.write_event_async(Event::Start(start.clone())).await?;
|
xml.q.write_event_async(Event::Start(start.clone())).await?;
|
||||||
xml.write_event_async(Event::Text(BytesText::new(&date.to_rfc2822()))).await?;
|
xml.q.write_event_async(Event::Text(BytesText::new(&date.to_rfc2822()))).await?;
|
||||||
xml.write_event_async(Event::End(end)).await?;
|
xml.q.write_event_async(Event::End(end)).await?;
|
||||||
},
|
},
|
||||||
LockDiscovery(many_locks) => {
|
LockDiscovery(many_locks) => {
|
||||||
// <D:lockdiscovery><D:activelock> ... </D:activelock></D:lockdiscovery>
|
// <D:lockdiscovery><D:activelock> ... </D:activelock></D:lockdiscovery>
|
||||||
let start = ctx.create_dav_element("lockdiscovery");
|
let start = xml.create_dav_element("lockdiscovery");
|
||||||
let end = start.to_end();
|
let end = start.to_end();
|
||||||
|
|
||||||
xml.write_event_async(Event::Start(start.clone())).await?;
|
xml.q.write_event_async(Event::Start(start.clone())).await?;
|
||||||
for lock in many_locks.iter() {
|
for lock in many_locks.iter() {
|
||||||
lock.write(xml, ctx.child()).await?;
|
lock.qwrite(xml).await?;
|
||||||
}
|
}
|
||||||
xml.write_event_async(Event::End(end)).await?;
|
xml.q.write_event_async(Event::End(end)).await?;
|
||||||
},
|
},
|
||||||
ResourceType(many_types) => {
|
ResourceType(many_types) => {
|
||||||
// <D:resourcetype><D:collection/></D:resourcetype>
|
// <D:resourcetype><D:collection/></D:resourcetype>
|
||||||
|
@ -397,16 +346,16 @@ impl<C: Context> QuickWritable<C> for Property<C> {
|
||||||
// <f:search-results xmlns:f="http://www.example.com/ns"/>
|
// <f:search-results xmlns:f="http://www.example.com/ns"/>
|
||||||
// </x:resourcetype>
|
// </x:resourcetype>
|
||||||
|
|
||||||
let start = ctx.create_dav_element("resourcetype");
|
let start = xml.create_dav_element("resourcetype");
|
||||||
if many_types.is_empty() {
|
if many_types.is_empty() {
|
||||||
xml.write_event_async(Event::Empty(start)).await?;
|
xml.q.write_event_async(Event::Empty(start)).await?;
|
||||||
} else {
|
} else {
|
||||||
let end = start.to_end();
|
let end = start.to_end();
|
||||||
xml.write_event_async(Event::Start(start.clone())).await?;
|
xml.q.write_event_async(Event::Start(start.clone())).await?;
|
||||||
for restype in many_types.iter() {
|
for restype in many_types.iter() {
|
||||||
restype.write(xml, ctx.child()).await?;
|
restype.qwrite(xml).await?;
|
||||||
}
|
}
|
||||||
xml.write_event_async(Event::End(end)).await?;
|
xml.q.write_event_async(Event::End(end)).await?;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
SupportedLock(many_entries) => {
|
SupportedLock(many_entries) => {
|
||||||
|
@ -414,52 +363,56 @@ impl<C: Context> QuickWritable<C> for Property<C> {
|
||||||
|
|
||||||
// <D:supportedlock> <D:lockentry> ... </D:lockentry> </D:supportedlock>
|
// <D:supportedlock> <D:lockentry> ... </D:lockentry> </D:supportedlock>
|
||||||
|
|
||||||
let start = ctx.create_dav_element("supportedlock");
|
let start = xml.create_dav_element("supportedlock");
|
||||||
if many_entries.is_empty() {
|
if many_entries.is_empty() {
|
||||||
xml.write_event_async(Event::Empty(start)).await?;
|
xml.q.write_event_async(Event::Empty(start)).await?;
|
||||||
} else {
|
} else {
|
||||||
let end = start.to_end();
|
let end = start.to_end();
|
||||||
xml.write_event_async(Event::Start(start.clone())).await?;
|
xml.q.write_event_async(Event::Start(start.clone())).await?;
|
||||||
for entry in many_entries.iter() {
|
for entry in many_entries.iter() {
|
||||||
entry.write(xml, ctx.child()).await?;
|
entry.qwrite(xml).await?;
|
||||||
}
|
}
|
||||||
xml.write_event_async(Event::End(end)).await?;
|
xml.q.write_event_async(Event::End(end)).await?;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Extension(inner) => {
|
Extension(inner) => inner.qwrite(xml).await?,
|
||||||
ctx.hook_property(inner, xml).await?;
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C: Context> QuickWritable<C> for ResourceType<C> {
|
impl<E: Extension> QWrite for ResourceType<E> {
|
||||||
async fn write(&self, xml: &mut Writer<impl AsyncWrite+Unpin>, ctx: C) -> Result<(), QError> {
|
async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> {
|
||||||
match self {
|
match self {
|
||||||
Self::Collection => xml.write_event_async(Event::Empty(ctx.create_dav_element("collection"))).await,
|
Self::Collection => {
|
||||||
Self::Extension(inner) => ctx.hook_resourcetype(inner, xml).await,
|
let empty_collection = xml.create_dav_element("collection");
|
||||||
|
xml.q.write_event_async(Event::Empty(empty_collection)).await
|
||||||
|
},
|
||||||
|
Self::Extension(inner) => inner.qwrite(xml).await,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C: Context> QuickWritable<C> for Include<C> {
|
impl<E: Extension> QWrite for Include<E> {
|
||||||
async fn write(&self, xml: &mut Writer<impl AsyncWrite+Unpin>, ctx: C) -> Result<(), QError> {
|
async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> {
|
||||||
let start = ctx.create_dav_element("include");
|
let start = xml.create_dav_element("include");
|
||||||
let end = start.to_end();
|
let end = start.to_end();
|
||||||
|
|
||||||
xml.write_event_async(Event::Start(start.clone())).await?;
|
xml.q.write_event_async(Event::Start(start.clone())).await?;
|
||||||
for prop in self.0.iter() {
|
for prop in self.0.iter() {
|
||||||
prop.write(xml, ctx.child()).await?;
|
prop.qwrite(xml).await?;
|
||||||
}
|
}
|
||||||
xml.write_event_async(Event::End(end)).await
|
xml.q.write_event_async(Event::End(end)).await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C: Context> QuickWritable<C> for PropertyRequest<C> {
|
impl<E: Extension> QWrite for PropertyRequest<E> {
|
||||||
async fn write(&self, xml: &mut Writer<impl AsyncWrite+Unpin>, ctx: C) -> Result<(), QError> {
|
async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> {
|
||||||
use PropertyRequest::*;
|
use PropertyRequest::*;
|
||||||
let mut atom = async |c| xml.write_event_async(Event::Empty(ctx.create_dav_element(c))).await;
|
let mut atom = async |c| {
|
||||||
|
let empty_tag = xml.create_dav_element(c);
|
||||||
|
xml.q.write_event_async(Event::Empty(empty_tag)).await
|
||||||
|
};
|
||||||
|
|
||||||
match self {
|
match self {
|
||||||
CreationDate => atom("creationdate").await,
|
CreationDate => atom("creationdate").await,
|
||||||
|
@ -472,13 +425,13 @@ impl<C: Context> QuickWritable<C> for PropertyRequest<C> {
|
||||||
LockDiscovery => atom("lockdiscovery").await,
|
LockDiscovery => atom("lockdiscovery").await,
|
||||||
ResourceType => atom("resourcetype").await,
|
ResourceType => atom("resourcetype").await,
|
||||||
SupportedLock => atom("supportedlock").await,
|
SupportedLock => atom("supportedlock").await,
|
||||||
Extension(inner) => ctx.hook_propertyrequest(inner, xml).await,
|
Extension(inner) => inner.qwrite(xml).await,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C: Context> QuickWritable<C> for ActiveLock {
|
impl QWrite for ActiveLock {
|
||||||
async fn write(&self, xml: &mut Writer<impl AsyncWrite+Unpin>, ctx: C) -> Result<(), QError> {
|
async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> {
|
||||||
// <D:activelock>
|
// <D:activelock>
|
||||||
// <D:locktype><D:write/></D:locktype>
|
// <D:locktype><D:write/></D:locktype>
|
||||||
// <D:lockscope><D:exclusive/></D:lockscope>
|
// <D:lockscope><D:exclusive/></D:lockscope>
|
||||||
|
@ -494,192 +447,193 @@ impl<C: Context> QuickWritable<C> for ActiveLock {
|
||||||
// <D:href>http://example.com/workspace/webdav/proposal.doc</D:href>
|
// <D:href>http://example.com/workspace/webdav/proposal.doc</D:href>
|
||||||
// </D:lockroot>
|
// </D:lockroot>
|
||||||
// </D:activelock>
|
// </D:activelock>
|
||||||
let start = ctx.create_dav_element("activelock");
|
let start = xml.create_dav_element("activelock");
|
||||||
let end = start.to_end();
|
let end = start.to_end();
|
||||||
|
|
||||||
xml.write_event_async(Event::Start(start.clone())).await?;
|
xml.q.write_event_async(Event::Start(start.clone())).await?;
|
||||||
self.locktype.write(xml, ctx.child()).await?;
|
self.locktype.qwrite(xml).await?;
|
||||||
self.lockscope.write(xml, ctx.child()).await?;
|
self.lockscope.qwrite(xml).await?;
|
||||||
self.depth.write(xml, ctx.child()).await?;
|
self.depth.qwrite(xml).await?;
|
||||||
if let Some(owner) = &self.owner {
|
if let Some(owner) = &self.owner {
|
||||||
owner.write(xml, ctx.child()).await?;
|
owner.qwrite(xml).await?;
|
||||||
}
|
}
|
||||||
if let Some(timeout) = &self.timeout {
|
if let Some(timeout) = &self.timeout {
|
||||||
timeout.write(xml, ctx.child()).await?;
|
timeout.qwrite(xml).await?;
|
||||||
}
|
}
|
||||||
if let Some(locktoken) = &self.locktoken {
|
if let Some(locktoken) = &self.locktoken {
|
||||||
locktoken.write(xml, ctx.child()).await?;
|
locktoken.qwrite(xml).await?;
|
||||||
}
|
}
|
||||||
self.lockroot.write(xml, ctx.child()).await?;
|
self.lockroot.qwrite(xml).await?;
|
||||||
xml.write_event_async(Event::End(end)).await?;
|
xml.q.write_event_async(Event::End(end)).await
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C: Context> QuickWritable<C> for LockType {
|
impl QWrite for LockType {
|
||||||
async fn write(&self, xml: &mut Writer<impl AsyncWrite+Unpin>, ctx: C) -> Result<(), QError> {
|
async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> {
|
||||||
let start = ctx.create_dav_element("locktype");
|
let start = xml.create_dav_element("locktype");
|
||||||
let end = start.to_end();
|
let end = start.to_end();
|
||||||
let ctx = ctx.child();
|
|
||||||
|
|
||||||
xml.write_event_async(Event::Start(start.clone())).await?;
|
xml.q.write_event_async(Event::Start(start.clone())).await?;
|
||||||
match self {
|
match self {
|
||||||
Self::Write => xml.write_event_async(Event::Empty(ctx.create_dav_element("write"))).await?,
|
Self::Write => {
|
||||||
|
let empty_write = xml.create_dav_element("write");
|
||||||
|
xml.q.write_event_async(Event::Empty(empty_write)).await?
|
||||||
|
},
|
||||||
};
|
};
|
||||||
xml.write_event_async(Event::End(end)).await
|
xml.q.write_event_async(Event::End(end)).await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C: Context> QuickWritable<C> for LockScope {
|
impl QWrite for LockScope {
|
||||||
async fn write(&self, xml: &mut Writer<impl AsyncWrite+Unpin>, ctx: C) -> Result<(), QError> {
|
async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> {
|
||||||
let start = ctx.create_dav_element("lockscope");
|
let start = xml.create_dav_element("lockscope");
|
||||||
let end = start.to_end();
|
let end = start.to_end();
|
||||||
let ctx = ctx.child();
|
|
||||||
|
|
||||||
xml.write_event_async(Event::Start(start.clone())).await?;
|
xml.q.write_event_async(Event::Start(start.clone())).await?;
|
||||||
match self {
|
match self {
|
||||||
Self::Exclusive => xml.write_event_async(Event::Empty(ctx.create_dav_element("exclusive"))).await?,
|
Self::Exclusive => {
|
||||||
Self::Shared => xml.write_event_async(Event::Empty(ctx.create_dav_element("shared"))).await?,
|
let empty_tag = xml.create_dav_element("exclusive");
|
||||||
|
xml.q.write_event_async(Event::Empty(empty_tag)).await?
|
||||||
|
},
|
||||||
|
Self::Shared => {
|
||||||
|
let empty_tag = xml.create_dav_element("shared");
|
||||||
|
xml.q.write_event_async(Event::Empty(empty_tag)).await?
|
||||||
|
},
|
||||||
};
|
};
|
||||||
xml.write_event_async(Event::End(end)).await
|
xml.q.write_event_async(Event::End(end)).await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C: Context> QuickWritable<C> for Owner {
|
impl QWrite for Owner {
|
||||||
async fn write(&self, xml: &mut Writer<impl AsyncWrite+Unpin>, ctx: C) -> Result<(), QError> {
|
async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> {
|
||||||
let start = ctx.create_dav_element("owner");
|
let start = xml.create_dav_element("owner");
|
||||||
let end = start.to_end();
|
let end = start.to_end();
|
||||||
|
|
||||||
xml.write_event_async(Event::Start(start.clone())).await?;
|
xml.q.write_event_async(Event::Start(start.clone())).await?;
|
||||||
match self {
|
match self {
|
||||||
Self::Txt(txt) => xml.write_event_async(Event::Text(BytesText::new(&txt))).await?,
|
Self::Txt(txt) => xml.q.write_event_async(Event::Text(BytesText::new(&txt))).await?,
|
||||||
Self::Href(href) => href.write(xml, ctx.child()).await?,
|
Self::Href(href) => href.qwrite(xml).await?,
|
||||||
}
|
}
|
||||||
xml.write_event_async(Event::End(end)).await
|
xml.q.write_event_async(Event::End(end)).await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C: Context> QuickWritable<C> for Depth {
|
impl QWrite for Depth {
|
||||||
async fn write(&self, xml: &mut Writer<impl AsyncWrite+Unpin>, ctx: C) -> Result<(), QError> {
|
async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> {
|
||||||
let start = ctx.create_dav_element("depth");
|
let start = xml.create_dav_element("depth");
|
||||||
let end = start.to_end();
|
let end = start.to_end();
|
||||||
|
|
||||||
xml.write_event_async(Event::Start(start.clone())).await?;
|
xml.q.write_event_async(Event::Start(start.clone())).await?;
|
||||||
match self {
|
match self {
|
||||||
Self::Zero => xml.write_event_async(Event::Text(BytesText::new("0"))).await?,
|
Self::Zero => xml.q.write_event_async(Event::Text(BytesText::new("0"))).await?,
|
||||||
Self::One => xml.write_event_async(Event::Text(BytesText::new("1"))).await?,
|
Self::One => xml.q.write_event_async(Event::Text(BytesText::new("1"))).await?,
|
||||||
Self::Infinity => xml.write_event_async(Event::Text(BytesText::new("infinity"))).await?,
|
Self::Infinity => xml.q.write_event_async(Event::Text(BytesText::new("infinity"))).await?,
|
||||||
};
|
};
|
||||||
xml.write_event_async(Event::End(end)).await
|
xml.q.write_event_async(Event::End(end)).await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C: Context> QuickWritable<C> for Timeout {
|
impl QWrite for Timeout {
|
||||||
async fn write(&self, xml: &mut Writer<impl AsyncWrite+Unpin>, ctx: C) -> Result<(), QError> {
|
async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> {
|
||||||
let start = ctx.create_dav_element("timeout");
|
let start = xml.create_dav_element("timeout");
|
||||||
let end = start.to_end();
|
let end = start.to_end();
|
||||||
|
|
||||||
xml.write_event_async(Event::Start(start.clone())).await?;
|
xml.q.write_event_async(Event::Start(start.clone())).await?;
|
||||||
match self {
|
match self {
|
||||||
Self::Seconds(count) => {
|
Self::Seconds(count) => {
|
||||||
let txt = format!("Second-{}", count);
|
let txt = format!("Second-{}", count);
|
||||||
xml.write_event_async(Event::Text(BytesText::new(&txt))).await?
|
xml.q.write_event_async(Event::Text(BytesText::new(&txt))).await?
|
||||||
},
|
},
|
||||||
Self::Infinite => xml.write_event_async(Event::Text(BytesText::new("Infinite"))).await?
|
Self::Infinite => xml.q.write_event_async(Event::Text(BytesText::new("Infinite"))).await?
|
||||||
};
|
};
|
||||||
xml.write_event_async(Event::End(end)).await
|
xml.q.write_event_async(Event::End(end)).await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C: Context> QuickWritable<C> for LockToken {
|
impl QWrite for LockToken {
|
||||||
async fn write(&self, xml: &mut Writer<impl AsyncWrite+Unpin>, ctx: C) -> Result<(), QError> {
|
async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> {
|
||||||
let start = ctx.create_dav_element("locktoken");
|
let start = xml.create_dav_element("locktoken");
|
||||||
let end = start.to_end();
|
let end = start.to_end();
|
||||||
|
|
||||||
xml.write_event_async(Event::Start(start.clone())).await?;
|
xml.q.write_event_async(Event::Start(start.clone())).await?;
|
||||||
self.0.write(xml, ctx.child()).await?;
|
self.0.qwrite(xml).await?;
|
||||||
xml.write_event_async(Event::End(end)).await
|
xml.q.write_event_async(Event::End(end)).await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C: Context> QuickWritable<C> for LockRoot {
|
impl QWrite for LockRoot {
|
||||||
async fn write(&self, xml: &mut Writer<impl AsyncWrite+Unpin>, ctx: C) -> Result<(), QError> {
|
async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> {
|
||||||
let start = ctx.create_dav_element("lockroot");
|
let start = xml.create_dav_element("lockroot");
|
||||||
let end = start.to_end();
|
let end = start.to_end();
|
||||||
|
|
||||||
xml.write_event_async(Event::Start(start.clone())).await?;
|
xml.q.write_event_async(Event::Start(start.clone())).await?;
|
||||||
self.0.write(xml, ctx.child()).await?;
|
self.0.qwrite(xml).await?;
|
||||||
xml.write_event_async(Event::End(end)).await
|
xml.q.write_event_async(Event::End(end)).await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C: Context> QuickWritable<C> for LockEntry {
|
impl QWrite for LockEntry {
|
||||||
async fn write(&self, xml: &mut Writer<impl AsyncWrite+Unpin>, ctx: C) -> Result<(), QError> {
|
async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> {
|
||||||
let start = ctx.create_dav_element("lockentry");
|
let start = xml.create_dav_element("lockentry");
|
||||||
let end = start.to_end();
|
let end = start.to_end();
|
||||||
|
|
||||||
xml.write_event_async(Event::Start(start.clone())).await?;
|
xml.q.write_event_async(Event::Start(start.clone())).await?;
|
||||||
self.lockscope.write(xml, ctx.child()).await?;
|
self.lockscope.qwrite(xml).await?;
|
||||||
self.locktype.write(xml, ctx.child()).await?;
|
self.locktype.qwrite(xml).await?;
|
||||||
xml.write_event_async(Event::End(end)).await
|
xml.q.write_event_async(Event::End(end)).await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C: Context> QuickWritable<C> for Error<C> {
|
impl<E: Extension> QWrite for Error<E> {
|
||||||
async fn write(&self, xml: &mut Writer<impl AsyncWrite+Unpin>, ctx: C) -> Result<(), QError> {
|
async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> {
|
||||||
let start = ctx.create_dav_element("error");
|
let start = xml.create_dav_element("error");
|
||||||
let end = start.to_end();
|
let end = start.to_end();
|
||||||
|
|
||||||
xml.write_event_async(Event::Start(start.clone())).await?;
|
xml.q.write_event_async(Event::Start(start.clone())).await?;
|
||||||
for violation in &self.0 {
|
for violation in &self.0 {
|
||||||
violation.write(xml, ctx.child()).await?;
|
violation.qwrite(xml).await?;
|
||||||
}
|
}
|
||||||
xml.write_event_async(Event::End(end)).await?;
|
xml.q.write_event_async(Event::End(end)).await
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C: Context> QuickWritable<C> for Violation<C> {
|
impl<E: Extension> QWrite for Violation<E> {
|
||||||
async fn write(&self, xml: &mut Writer<impl AsyncWrite+Unpin>, ctx: C) -> Result<(), QError> {
|
async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> {
|
||||||
match self {
|
let mut atom = async |c| {
|
||||||
Violation::LockTokenMatchesRequestUri => xml.write_event_async(Event::Empty(ctx.create_dav_element("lock-token-matches-request-uri"))).await?,
|
let empty_tag = xml.create_dav_element(c);
|
||||||
Violation::LockTokenSubmitted(hrefs) if hrefs.is_empty() => {
|
xml.q.write_event_async(Event::Empty(empty_tag)).await
|
||||||
xml.write_event_async(Event::Empty(ctx.create_dav_element("lock-token-submitted"))).await?
|
|
||||||
},
|
|
||||||
Violation::LockTokenSubmitted(hrefs) => {
|
|
||||||
let start = ctx.create_dav_element("lock-token-submitted");
|
|
||||||
let end = start.to_end();
|
|
||||||
|
|
||||||
xml.write_event_async(Event::Start(start.clone())).await?;
|
|
||||||
for href in hrefs {
|
|
||||||
href.write(xml, ctx.child()).await?;
|
|
||||||
}
|
|
||||||
xml.write_event_async(Event::End(end)).await?;
|
|
||||||
},
|
|
||||||
Violation::NoConflictingLock(hrefs) if hrefs.is_empty() => {
|
|
||||||
xml.write_event_async(Event::Empty(ctx.create_dav_element("no-conflicting-lock"))).await?
|
|
||||||
},
|
|
||||||
Violation::NoConflictingLock(hrefs) => {
|
|
||||||
let start = ctx.create_dav_element("no-conflicting-lock");
|
|
||||||
let end = start.to_end();
|
|
||||||
|
|
||||||
xml.write_event_async(Event::Start(start.clone())).await?;
|
|
||||||
for href in hrefs {
|
|
||||||
href.write(xml, ctx.child()).await?;
|
|
||||||
}
|
|
||||||
xml.write_event_async(Event::End(end)).await?;
|
|
||||||
},
|
|
||||||
Violation::NoExternalEntities => xml.write_event_async(Event::Empty(ctx.create_dav_element("no-external-entities"))).await?,
|
|
||||||
Violation::PreservedLiveProperties => xml.write_event_async(Event::Empty(ctx.create_dav_element("preserved-live-properties"))).await?,
|
|
||||||
Violation::PropfindFiniteDepth => xml.write_event_async(Event::Empty(ctx.create_dav_element("propfind-finite-depth"))).await?,
|
|
||||||
Violation::CannotModifyProtectedProperty => xml.write_event_async(Event::Empty(ctx.create_dav_element("cannot-modify-protected-property"))).await?,
|
|
||||||
Violation::Extension(inner) => {
|
|
||||||
ctx.hook_error(inner, xml).await?;
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
Ok(())
|
|
||||||
|
match self {
|
||||||
|
Violation::LockTokenMatchesRequestUri => atom("lock-token-matches-request-uri").await,
|
||||||
|
Violation::LockTokenSubmitted(hrefs) if hrefs.is_empty() => atom("lock-token-submitted").await,
|
||||||
|
Violation::LockTokenSubmitted(hrefs) => {
|
||||||
|
let start = xml.create_dav_element("lock-token-submitted");
|
||||||
|
let end = start.to_end();
|
||||||
|
|
||||||
|
xml.q.write_event_async(Event::Start(start.clone())).await?;
|
||||||
|
for href in hrefs {
|
||||||
|
href.qwrite(xml).await?;
|
||||||
|
}
|
||||||
|
xml.q.write_event_async(Event::End(end)).await
|
||||||
|
},
|
||||||
|
Violation::NoConflictingLock(hrefs) if hrefs.is_empty() => atom("no-conflicting-lock").await,
|
||||||
|
Violation::NoConflictingLock(hrefs) => {
|
||||||
|
let start = xml.create_dav_element("no-conflicting-lock");
|
||||||
|
let end = start.to_end();
|
||||||
|
|
||||||
|
xml.q.write_event_async(Event::Start(start.clone())).await?;
|
||||||
|
for href in hrefs {
|
||||||
|
href.qwrite(xml).await?;
|
||||||
|
}
|
||||||
|
xml.q.write_event_async(Event::End(end)).await
|
||||||
|
},
|
||||||
|
Violation::NoExternalEntities => atom("no-external-entities").await,
|
||||||
|
Violation::PreservedLiveProperties => atom("preserved-live-properties").await,
|
||||||
|
Violation::PropfindFiniteDepth => atom("propfind-finite-depth").await,
|
||||||
|
Violation::CannotModifyProtectedProperty => atom("cannot-modify-protected-property").await,
|
||||||
|
Violation::Extension(inner) => inner.qwrite(xml).await,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
20
src/dav/error.rs
Normal file
20
src/dav/error.rs
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
use quick_xml::events::attributes::AttrError;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum ParsingError {
|
||||||
|
NamespacePrefixAlreadyUsed,
|
||||||
|
WrongToken,
|
||||||
|
TagNotFound,
|
||||||
|
QuickXml(quick_xml::Error),
|
||||||
|
Eof
|
||||||
|
}
|
||||||
|
impl From<AttrError> for ParsingError {
|
||||||
|
fn from(value: AttrError) -> Self {
|
||||||
|
Self::QuickXml(value.into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl From<quick_xml::Error> for ParsingError {
|
||||||
|
fn from(value: quick_xml::Error) -> Self {
|
||||||
|
Self::QuickXml(value)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,3 +1,5 @@
|
||||||
|
mod error;
|
||||||
|
mod xml;
|
||||||
mod types;
|
mod types;
|
||||||
mod caltypes;
|
mod caltypes;
|
||||||
mod acltypes;
|
mod acltypes;
|
||||||
|
@ -5,6 +7,7 @@ mod versioningtypes;
|
||||||
mod encoder;
|
mod encoder;
|
||||||
mod calencoder;
|
mod calencoder;
|
||||||
mod decoder;
|
mod decoder;
|
||||||
|
mod realization;
|
||||||
|
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
|
|
||||||
|
|
41
src/dav/realization.rs
Normal file
41
src/dav/realization.rs
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
use super::types as dav;
|
||||||
|
use super::caltypes as cal;
|
||||||
|
use super::xml;
|
||||||
|
use super::error;
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
|
pub struct Disabled(());
|
||||||
|
impl xml::QRead<Disabled> for Disabled {
|
||||||
|
async fn qread(&self, xml: &mut xml::Reader<impl xml::IRead>) -> Result<Option<Self>, error::ParsingError> {
|
||||||
|
unreachable!();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl xml::QWrite for Disabled {
|
||||||
|
async fn qwrite(&self, xml: &mut xml::Writer<impl xml::IWrite>) -> Result<(), quick_xml::Error> {
|
||||||
|
unreachable!();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The base WebDAV
|
||||||
|
///
|
||||||
|
/// Any extension is kooh is disabled through an object we can't build
|
||||||
|
/// due to a private inner element.
|
||||||
|
pub struct Core {}
|
||||||
|
impl dav::Extension for Core {
|
||||||
|
type Error = Disabled;
|
||||||
|
type Property = Disabled;
|
||||||
|
type PropertyRequest = Disabled;
|
||||||
|
type ResourceType = Disabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
// WebDAV with the base Calendar implementation (RFC4791)
|
||||||
|
pub struct CalendarMin {}
|
||||||
|
impl dav::Extension for CalendarMin
|
||||||
|
{
|
||||||
|
type Error = cal::Violation;
|
||||||
|
type Property = cal::Property;
|
||||||
|
type PropertyRequest = cal::PropertyRequest;
|
||||||
|
type ResourceType = cal::ResourceType;
|
||||||
|
}
|
||||||
|
*/
|
138
src/dav/types.rs
138
src/dav/types.rs
|
@ -1,28 +1,20 @@
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
|
use std::fmt::Debug;
|
||||||
|
|
||||||
use chrono::{DateTime,FixedOffset};
|
use chrono::{DateTime,FixedOffset};
|
||||||
|
use super::xml;
|
||||||
|
use super::error;
|
||||||
|
|
||||||
/// Extension utilities
|
/// It's how we implement a DAV extension
|
||||||
pub struct Disabled(());
|
/// (That's the dark magic part...)
|
||||||
|
pub trait ExtensionItem<T> = xml::QRead<T> + xml::QWrite + Debug + PartialEq;
|
||||||
pub trait Extension {
|
pub trait Extension {
|
||||||
type Error;
|
type Error: ExtensionItem<Self::Error>;
|
||||||
type Property;
|
type Property: ExtensionItem<Self::Property>;
|
||||||
type PropertyRequest;
|
type PropertyRequest: ExtensionItem<Self::PropertyRequest>;
|
||||||
type ResourceType;
|
type ResourceType: ExtensionItem<Self::ResourceType>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// No extension
|
|
||||||
pub struct NoExtension {
|
|
||||||
pub root: bool
|
|
||||||
}
|
|
||||||
impl Extension for NoExtension {
|
|
||||||
type Error = Disabled;
|
|
||||||
type Property = Disabled;
|
|
||||||
type PropertyRequest = Disabled;
|
|
||||||
type ResourceType = Disabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// 14.1. activelock XML Element
|
/// 14.1. activelock XML Element
|
||||||
///
|
///
|
||||||
/// Name: activelock
|
/// Name: activelock
|
||||||
|
@ -30,6 +22,7 @@ impl Extension for NoExtension {
|
||||||
/// Purpose: Describes a lock on a resource.
|
/// Purpose: Describes a lock on a resource.
|
||||||
/// <!ELEMENT activelock (lockscope, locktype, depth, owner?, timeout?,
|
/// <!ELEMENT activelock (lockscope, locktype, depth, owner?, timeout?,
|
||||||
/// locktoken?, lockroot)>
|
/// locktoken?, lockroot)>
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
pub struct ActiveLock {
|
pub struct ActiveLock {
|
||||||
pub lockscope: LockScope,
|
pub lockscope: LockScope,
|
||||||
pub locktype: LockType,
|
pub locktype: LockType,
|
||||||
|
@ -50,6 +43,7 @@ pub struct ActiveLock {
|
||||||
/// elements.
|
/// elements.
|
||||||
///
|
///
|
||||||
/// <!ELEMENT collection EMPTY >
|
/// <!ELEMENT collection EMPTY >
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
pub struct Collection{}
|
pub struct Collection{}
|
||||||
|
|
||||||
/// 14.4 depth XML Element
|
/// 14.4 depth XML Element
|
||||||
|
@ -62,6 +56,7 @@ pub struct Collection{}
|
||||||
/// Value: "0" | "1" | "infinity"
|
/// Value: "0" | "1" | "infinity"
|
||||||
///
|
///
|
||||||
/// <!ELEMENT depth (#PCDATA) >
|
/// <!ELEMENT depth (#PCDATA) >
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
pub enum Depth {
|
pub enum Depth {
|
||||||
Zero,
|
Zero,
|
||||||
One,
|
One,
|
||||||
|
@ -84,8 +79,10 @@ pub enum Depth {
|
||||||
/// postcondition code. Unrecognized elements MUST be ignored.
|
/// postcondition code. Unrecognized elements MUST be ignored.
|
||||||
///
|
///
|
||||||
/// <!ELEMENT error ANY >
|
/// <!ELEMENT error ANY >
|
||||||
pub struct Error<T: Extension>(pub Vec<Violation<T>>);
|
#[derive(Debug, PartialEq)]
|
||||||
pub enum Violation<T: Extension> {
|
pub struct Error<E: Extension>(pub Vec<Violation<E>>);
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
|
pub enum Violation<E: Extension> {
|
||||||
/// Name: lock-token-matches-request-uri
|
/// Name: lock-token-matches-request-uri
|
||||||
///
|
///
|
||||||
/// Use with: 409 Conflict
|
/// Use with: 409 Conflict
|
||||||
|
@ -169,7 +166,7 @@ pub enum Violation<T: Extension> {
|
||||||
CannotModifyProtectedProperty,
|
CannotModifyProtectedProperty,
|
||||||
|
|
||||||
/// Specific errors
|
/// Specific errors
|
||||||
Extension(T::Error),
|
Extension(E::Error),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 14.6. exclusive XML Element
|
/// 14.6. exclusive XML Element
|
||||||
|
@ -179,6 +176,7 @@ pub enum Violation<T: Extension> {
|
||||||
/// Purpose: Specifies an exclusive lock.
|
/// Purpose: Specifies an exclusive lock.
|
||||||
///
|
///
|
||||||
/// <!ELEMENT exclusive EMPTY >
|
/// <!ELEMENT exclusive EMPTY >
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
pub struct Exclusive {}
|
pub struct Exclusive {}
|
||||||
|
|
||||||
/// 14.7. href XML Element
|
/// 14.7. href XML Element
|
||||||
|
@ -194,6 +192,7 @@ pub struct Exclusive {}
|
||||||
/// Value: Simple-ref
|
/// Value: Simple-ref
|
||||||
///
|
///
|
||||||
/// <!ELEMENT href (#PCDATA)>
|
/// <!ELEMENT href (#PCDATA)>
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
pub struct Href(pub String);
|
pub struct Href(pub String);
|
||||||
|
|
||||||
|
|
||||||
|
@ -209,7 +208,8 @@ pub struct Href(pub String);
|
||||||
/// standards. This element MUST NOT contain text or mixed content.
|
/// standards. This element MUST NOT contain text or mixed content.
|
||||||
///
|
///
|
||||||
/// <!ELEMENT include ANY >
|
/// <!ELEMENT include ANY >
|
||||||
pub struct Include<T: Extension>(pub Vec<PropertyRequest<T>>);
|
#[derive(Debug, PartialEq)]
|
||||||
|
pub struct Include<E: Extension>(pub Vec<PropertyRequest<E>>);
|
||||||
|
|
||||||
/// 14.9. location XML Element
|
/// 14.9. location XML Element
|
||||||
///
|
///
|
||||||
|
@ -225,6 +225,7 @@ pub struct Include<T: Extension>(pub Vec<PropertyRequest<T>>);
|
||||||
/// that would be used in a Location header.
|
/// that would be used in a Location header.
|
||||||
///
|
///
|
||||||
/// <!ELEMENT location (href)>
|
/// <!ELEMENT location (href)>
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
pub struct Location(pub Href);
|
pub struct Location(pub Href);
|
||||||
|
|
||||||
/// 14.10. lockentry XML Element
|
/// 14.10. lockentry XML Element
|
||||||
|
@ -235,6 +236,7 @@ pub struct Location(pub Href);
|
||||||
/// resource.
|
/// resource.
|
||||||
///
|
///
|
||||||
/// <!ELEMENT lockentry (lockscope, locktype) >
|
/// <!ELEMENT lockentry (lockscope, locktype) >
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
pub struct LockEntry {
|
pub struct LockEntry {
|
||||||
pub lockscope: LockScope,
|
pub lockscope: LockScope,
|
||||||
pub locktype: LockType,
|
pub locktype: LockType,
|
||||||
|
@ -248,6 +250,7 @@ pub struct LockEntry {
|
||||||
/// specify the type of lock the client wishes to have created.
|
/// specify the type of lock the client wishes to have created.
|
||||||
///
|
///
|
||||||
/// <!ELEMENT lockinfo (lockscope, locktype, owner?) >
|
/// <!ELEMENT lockinfo (lockscope, locktype, owner?) >
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
pub struct LockInfo {
|
pub struct LockInfo {
|
||||||
pub lockscope: LockScope,
|
pub lockscope: LockScope,
|
||||||
pub locktype: LockType,
|
pub locktype: LockType,
|
||||||
|
@ -266,6 +269,7 @@ pub struct LockInfo {
|
||||||
/// values and the response to LOCK requests.
|
/// values and the response to LOCK requests.
|
||||||
///
|
///
|
||||||
/// <!ELEMENT lockroot (href) >
|
/// <!ELEMENT lockroot (href) >
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
pub struct LockRoot(pub Href);
|
pub struct LockRoot(pub Href);
|
||||||
|
|
||||||
/// 14.13. lockscope XML Element
|
/// 14.13. lockscope XML Element
|
||||||
|
@ -275,6 +279,7 @@ pub struct LockRoot(pub Href);
|
||||||
/// Purpose: Specifies whether a lock is an exclusive lock, or a shared
|
/// Purpose: Specifies whether a lock is an exclusive lock, or a shared
|
||||||
/// lock.
|
/// lock.
|
||||||
/// <!ELEMENT lockscope (exclusive | shared) >
|
/// <!ELEMENT lockscope (exclusive | shared) >
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
pub enum LockScope {
|
pub enum LockScope {
|
||||||
Exclusive,
|
Exclusive,
|
||||||
Shared
|
Shared
|
||||||
|
@ -290,6 +295,7 @@ pub enum LockScope {
|
||||||
/// refers to the lock.
|
/// refers to the lock.
|
||||||
///
|
///
|
||||||
/// <!ELEMENT locktoken (href) >
|
/// <!ELEMENT locktoken (href) >
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
pub struct LockToken(pub Href);
|
pub struct LockToken(pub Href);
|
||||||
|
|
||||||
/// 14.15. locktype XML Element
|
/// 14.15. locktype XML Element
|
||||||
|
@ -300,6 +306,7 @@ pub struct LockToken(pub Href);
|
||||||
/// specification only defines one lock type, the write lock.
|
/// specification only defines one lock type, the write lock.
|
||||||
///
|
///
|
||||||
/// <!ELEMENT locktype (write) >
|
/// <!ELEMENT locktype (write) >
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
pub enum LockType {
|
pub enum LockType {
|
||||||
/// 14.30. write XML Element
|
/// 14.30. write XML Element
|
||||||
///
|
///
|
||||||
|
@ -325,8 +332,9 @@ pub enum LockType {
|
||||||
/// response descriptions contained within the responses.
|
/// response descriptions contained within the responses.
|
||||||
///
|
///
|
||||||
/// <!ELEMENT multistatus (response*, responsedescription?) >
|
/// <!ELEMENT multistatus (response*, responsedescription?) >
|
||||||
pub struct Multistatus<T: Extension> {
|
#[derive(Debug, PartialEq)]
|
||||||
pub responses: Vec<Response<T>>,
|
pub struct Multistatus<E: Extension> {
|
||||||
|
pub responses: Vec<Response<E>>,
|
||||||
pub responsedescription: Option<ResponseDescription>,
|
pub responsedescription: Option<ResponseDescription>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -354,6 +362,7 @@ pub struct Multistatus<T: Extension> {
|
||||||
///
|
///
|
||||||
/// <!ELEMENT owner ANY >
|
/// <!ELEMENT owner ANY >
|
||||||
//@FIXME might need support for an extension
|
//@FIXME might need support for an extension
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
pub enum Owner {
|
pub enum Owner {
|
||||||
Txt(String),
|
Txt(String),
|
||||||
Href(Href),
|
Href(Href),
|
||||||
|
@ -373,12 +382,17 @@ pub enum Owner {
|
||||||
/// text or mixed content.
|
/// text or mixed content.
|
||||||
///
|
///
|
||||||
/// <!ELEMENT prop ANY >
|
/// <!ELEMENT prop ANY >
|
||||||
pub enum AnyProp<T: Extension> {
|
#[derive(Debug, PartialEq)]
|
||||||
Name(PropName<T>),
|
pub enum AnyProp<E: Extension> {
|
||||||
Value(PropValue<T>),
|
Name(PropName<E>),
|
||||||
|
Value(PropValue<E>),
|
||||||
}
|
}
|
||||||
pub struct PropName<T: Extension>(pub Vec<PropertyRequest<T>>);
|
|
||||||
pub struct PropValue<T: Extension>(pub Vec<Property<T>>);
|
#[derive(Debug, PartialEq)]
|
||||||
|
pub struct PropName<E: Extension>(pub Vec<PropertyRequest<E>>);
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
|
pub struct PropValue<E: Extension>(pub Vec<Property<E>>);
|
||||||
|
|
||||||
/// 14.19. propertyupdate XML Element
|
/// 14.19. propertyupdate XML Element
|
||||||
///
|
///
|
||||||
|
@ -390,10 +404,13 @@ pub struct PropValue<T: Extension>(pub Vec<Property<T>>);
|
||||||
/// required to modify the properties on the resource.
|
/// required to modify the properties on the resource.
|
||||||
///
|
///
|
||||||
/// <!ELEMENT propertyupdate (remove | set)+ >
|
/// <!ELEMENT propertyupdate (remove | set)+ >
|
||||||
pub struct PropertyUpdate<T: Extension>(pub Vec<PropertyUpdateItem<T>>);
|
#[derive(Debug, PartialEq)]
|
||||||
pub enum PropertyUpdateItem<T: Extension> {
|
pub struct PropertyUpdate<E: Extension>(pub Vec<PropertyUpdateItem<E>>);
|
||||||
Remove(Remove<T>),
|
|
||||||
Set(Set<T>),
|
#[derive(Debug, PartialEq)]
|
||||||
|
pub enum PropertyUpdateItem<E: Extension> {
|
||||||
|
Remove(Remove<E>),
|
||||||
|
Set(Set<E>),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 14.2 allprop XML Element
|
/// 14.2 allprop XML Element
|
||||||
|
@ -430,10 +447,11 @@ pub enum PropertyUpdateItem<T: Extension> {
|
||||||
/// values.
|
/// values.
|
||||||
///
|
///
|
||||||
/// <!ELEMENT propfind ( propname | (allprop, include?) | prop ) >
|
/// <!ELEMENT propfind ( propname | (allprop, include?) | prop ) >
|
||||||
pub enum PropFind<T: Extension> {
|
#[derive(Debug, PartialEq)]
|
||||||
|
pub enum PropFind<E: Extension> {
|
||||||
PropName,
|
PropName,
|
||||||
AllProp(Option<Include<T>>),
|
AllProp(Option<Include<E>>),
|
||||||
Prop(PropName<T>),
|
Prop(PropName<E>),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 14.22 propstat XML Element
|
/// 14.22 propstat XML Element
|
||||||
|
@ -451,10 +469,11 @@ pub enum PropFind<T: Extension> {
|
||||||
/// the properties named in 'prop'.
|
/// the properties named in 'prop'.
|
||||||
///
|
///
|
||||||
/// <!ELEMENT propstat (prop, status, error?, responsedescription?) >
|
/// <!ELEMENT propstat (prop, status, error?, responsedescription?) >
|
||||||
pub struct PropStat<T: Extension> {
|
#[derive(Debug, PartialEq)]
|
||||||
pub prop: AnyProp<T>,
|
pub struct PropStat<E: Extension> {
|
||||||
|
pub prop: AnyProp<E>,
|
||||||
pub status: Status,
|
pub status: Status,
|
||||||
pub error: Option<Error<T>>,
|
pub error: Option<Error<E>>,
|
||||||
pub responsedescription: Option<ResponseDescription>,
|
pub responsedescription: Option<ResponseDescription>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -471,7 +490,8 @@ pub struct PropStat<T: Extension> {
|
||||||
/// the names of properties to be removed are required.
|
/// the names of properties to be removed are required.
|
||||||
///
|
///
|
||||||
/// <!ELEMENT remove (prop) >
|
/// <!ELEMENT remove (prop) >
|
||||||
pub struct Remove<T: Extension>(pub PropName<T>);
|
#[derive(Debug, PartialEq)]
|
||||||
|
pub struct Remove<E: Extension>(pub PropName<E>);
|
||||||
|
|
||||||
/// 14.24. response XML Element
|
/// 14.24. response XML Element
|
||||||
///
|
///
|
||||||
|
@ -495,14 +515,17 @@ pub struct Remove<T: Extension>(pub PropName<T>);
|
||||||
///
|
///
|
||||||
/// <!ELEMENT response (href, ((href*, status)|(propstat+)),
|
/// <!ELEMENT response (href, ((href*, status)|(propstat+)),
|
||||||
/// error?, responsedescription? , location?) >
|
/// error?, responsedescription? , location?) >
|
||||||
pub enum StatusOrPropstat<T: Extension> {
|
#[derive(Debug, PartialEq)]
|
||||||
|
pub enum StatusOrPropstat<E: Extension> {
|
||||||
Status(Status),
|
Status(Status),
|
||||||
PropStat(Vec<PropStat<T>>),
|
PropStat(Vec<PropStat<E>>),
|
||||||
}
|
}
|
||||||
pub struct Response<T: Extension> {
|
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
|
pub struct Response<E: Extension> {
|
||||||
pub href: Href, // It's wrong according to the spec, but I don't understand why there is an href*
|
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<T>,
|
pub status_or_propstat: StatusOrPropstat<E>,
|
||||||
pub error: Option<Error<T>>,
|
pub error: Option<Error<E>>,
|
||||||
pub responsedescription: Option<ResponseDescription>,
|
pub responsedescription: Option<ResponseDescription>,
|
||||||
pub location: Option<Location>,
|
pub location: Option<Location>,
|
||||||
}
|
}
|
||||||
|
@ -518,6 +541,7 @@ pub struct Response<T: Extension> {
|
||||||
/// user.
|
/// user.
|
||||||
///
|
///
|
||||||
/// <!ELEMENT responsedescription (#PCDATA) >
|
/// <!ELEMENT responsedescription (#PCDATA) >
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
pub struct ResponseDescription(pub String);
|
pub struct ResponseDescription(pub String);
|
||||||
|
|
||||||
/// 14.26. set XML Element
|
/// 14.26. set XML Element
|
||||||
|
@ -536,7 +560,8 @@ pub struct ResponseDescription(pub String);
|
||||||
/// property, and MUST be subsequently retrievable using PROPFIND.
|
/// property, and MUST be subsequently retrievable using PROPFIND.
|
||||||
///
|
///
|
||||||
/// <!ELEMENT set (prop) >
|
/// <!ELEMENT set (prop) >
|
||||||
pub struct Set<T: Extension>(pub PropValue<T>);
|
#[derive(Debug, PartialEq)]
|
||||||
|
pub struct Set<E: Extension>(pub PropValue<E>);
|
||||||
|
|
||||||
/// 14.27. shared XML Element
|
/// 14.27. shared XML Element
|
||||||
///
|
///
|
||||||
|
@ -546,6 +571,7 @@ pub struct Set<T: Extension>(pub PropValue<T>);
|
||||||
///
|
///
|
||||||
///
|
///
|
||||||
/// <!ELEMENT shared EMPTY >
|
/// <!ELEMENT shared EMPTY >
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
pub struct Shared {}
|
pub struct Shared {}
|
||||||
|
|
||||||
|
|
||||||
|
@ -559,6 +585,7 @@ pub struct Shared {}
|
||||||
///
|
///
|
||||||
/// <!ELEMENT status (#PCDATA) >
|
/// <!ELEMENT status (#PCDATA) >
|
||||||
//@FIXME: Better typing is possible with an enum for example
|
//@FIXME: Better typing is possible with an enum for example
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
pub struct Status(pub http::status::StatusCode);
|
pub struct Status(pub http::status::StatusCode);
|
||||||
|
|
||||||
/// 14.29. timeout XML Element
|
/// 14.29. timeout XML Element
|
||||||
|
@ -586,6 +613,7 @@ pub struct Status(pub http::status::StatusCode);
|
||||||
/// elapse between granting of the lock at the server, and the automatic
|
/// elapse between granting of the lock at the server, and the automatic
|
||||||
/// removal of the lock. The timeout value for TimeType "Second" MUST
|
/// removal of the lock. The timeout value for TimeType "Second" MUST
|
||||||
/// NOT be greater than 2^32-1.
|
/// NOT be greater than 2^32-1.
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
pub enum Timeout {
|
pub enum Timeout {
|
||||||
Seconds(u32),
|
Seconds(u32),
|
||||||
Infinite,
|
Infinite,
|
||||||
|
@ -619,7 +647,8 @@ pub enum Timeout {
|
||||||
/// the header value could include LWS as defined in [RFC2616], Section
|
/// the header value could include LWS as defined in [RFC2616], Section
|
||||||
/// 4.2. Server implementors SHOULD strip LWS from these values before
|
/// 4.2. Server implementors SHOULD strip LWS from these values before
|
||||||
/// using as WebDAV property values.
|
/// using as WebDAV property values.
|
||||||
pub enum PropertyRequest<T: Extension> {
|
#[derive(Debug, PartialEq)]
|
||||||
|
pub enum PropertyRequest<E: Extension> {
|
||||||
CreationDate,
|
CreationDate,
|
||||||
DisplayName,
|
DisplayName,
|
||||||
GetContentLanguage,
|
GetContentLanguage,
|
||||||
|
@ -630,9 +659,11 @@ pub enum PropertyRequest<T: Extension> {
|
||||||
LockDiscovery,
|
LockDiscovery,
|
||||||
ResourceType,
|
ResourceType,
|
||||||
SupportedLock,
|
SupportedLock,
|
||||||
Extension(T::PropertyRequest),
|
Extension(E::PropertyRequest),
|
||||||
}
|
}
|
||||||
pub enum Property<T: Extension> {
|
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
|
pub enum Property<E: Extension> {
|
||||||
/// 15.1. creationdate Property
|
/// 15.1. creationdate Property
|
||||||
///
|
///
|
||||||
/// Name: creationdate
|
/// Name: creationdate
|
||||||
|
@ -883,7 +914,7 @@ pub enum Property<T: Extension> {
|
||||||
/// <x:collection/>
|
/// <x:collection/>
|
||||||
/// <f:search-results xmlns:f="http://www.example.com/ns"/>
|
/// <f:search-results xmlns:f="http://www.example.com/ns"/>
|
||||||
/// </x:resourcetype>
|
/// </x:resourcetype>
|
||||||
ResourceType(Vec<ResourceType<T>>),
|
ResourceType(Vec<ResourceType<E>>),
|
||||||
|
|
||||||
/// 15.10. supportedlock Property
|
/// 15.10. supportedlock Property
|
||||||
///
|
///
|
||||||
|
@ -911,10 +942,11 @@ pub enum Property<T: Extension> {
|
||||||
SupportedLock(Vec<LockEntry>),
|
SupportedLock(Vec<LockEntry>),
|
||||||
|
|
||||||
/// Any extension
|
/// Any extension
|
||||||
Extension(T::Property),
|
Extension(E::Property),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum ResourceType<T: Extension> {
|
#[derive(Debug, PartialEq)]
|
||||||
|
pub enum ResourceType<E: Extension> {
|
||||||
Collection,
|
Collection,
|
||||||
Extension(T::ResourceType),
|
Extension(E::ResourceType),
|
||||||
}
|
}
|
||||||
|
|
128
src/dav/xml.rs
Normal file
128
src/dav/xml.rs
Normal file
|
@ -0,0 +1,128 @@
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use tokio::io::{AsyncWrite, AsyncBufRead};
|
||||||
|
use quick_xml::events::{Event, BytesEnd, BytesStart, BytesText};
|
||||||
|
use quick_xml::name::{Namespace, QName, PrefixDeclaration, ResolveResult, ResolveResult::*};
|
||||||
|
use quick_xml::reader::NsReader;
|
||||||
|
|
||||||
|
use super::error::ParsingError;
|
||||||
|
|
||||||
|
// Async traits
|
||||||
|
pub trait IWrite = AsyncWrite + Unpin;
|
||||||
|
pub trait IRead = AsyncBufRead + Unpin + 'static;
|
||||||
|
|
||||||
|
// Serialization/Deserialization traits
|
||||||
|
pub trait QWrite {
|
||||||
|
async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), quick_xml::Error>;
|
||||||
|
}
|
||||||
|
pub trait QRead<T> {
|
||||||
|
async fn qread(&self, xml: &mut Reader<impl IRead>) -> Result<Option<T>, ParsingError>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Transform a Rust object into an XML stream of characters
|
||||||
|
pub struct Writer<T: IWrite> {
|
||||||
|
pub q: quick_xml::writer::Writer<T>,
|
||||||
|
root: bool,
|
||||||
|
}
|
||||||
|
impl<T: IWrite> Writer<T> {
|
||||||
|
pub fn create_dav_element(&mut self, name: &str) -> BytesStart<'static> {
|
||||||
|
self.create_ns_element("D", name)
|
||||||
|
}
|
||||||
|
pub fn create_cal_element(&mut self, name: &str) -> BytesStart<'static> {
|
||||||
|
self.create_ns_element("C", name)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_ns_element(&mut self, ns: &str, name: &str) -> BytesStart<'static> {
|
||||||
|
let mut start = BytesStart::new(format!("{}:{}", ns, name));
|
||||||
|
//@FIXME not what we want
|
||||||
|
if self.root {
|
||||||
|
start.push_attribute(("xmlns:D", "DAV:"));
|
||||||
|
start.push_attribute(("xmlns:C", "urn:ietf:params:xml:ns:caldav"));
|
||||||
|
self.root = false;
|
||||||
|
}
|
||||||
|
start
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Transform an XML stream of characters into a Rust object
|
||||||
|
pub struct Reader<T: IRead> {
|
||||||
|
evt: Event<'static>,
|
||||||
|
rdr: NsReader<T>,
|
||||||
|
buf: Vec<u8>,
|
||||||
|
}
|
||||||
|
impl<T: IRead> Reader<T> {
|
||||||
|
async fn new(mut rdr: NsReader<T>) -> Result<Self, ParsingError> {
|
||||||
|
let mut buf: Vec<u8> = vec![];
|
||||||
|
let evt = rdr.read_event_into_async(&mut buf).await?.into_owned();
|
||||||
|
buf.clear();
|
||||||
|
Ok(Self { evt, rdr, buf })
|
||||||
|
}
|
||||||
|
|
||||||
|
fn peek(&self) -> &Event<'static> {
|
||||||
|
&self.evt
|
||||||
|
}
|
||||||
|
|
||||||
|
/// skip tag. Can't skip end, can't skip eof.
|
||||||
|
async fn skip(&mut self) -> Result<Event<'static>, ParsingError> {
|
||||||
|
match &self.evt {
|
||||||
|
Event::Start(b) => {
|
||||||
|
let _span = self.rdr.read_to_end_into_async(b.to_end().name(), &mut self.buf).await?;
|
||||||
|
self.next().await
|
||||||
|
},
|
||||||
|
Event::End(_) => Err(ParsingError::WrongToken),
|
||||||
|
Event::Eof => Err(ParsingError::Eof),
|
||||||
|
_ => self.next().await,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// read one more tag
|
||||||
|
async fn next(&mut self) -> Result<Event<'static>, ParsingError> {
|
||||||
|
let evt = self.rdr.read_event_into_async(&mut self.buf).await?.into_owned();
|
||||||
|
self.buf.clear();
|
||||||
|
let old_evt = std::mem::replace(&mut self.evt, evt);
|
||||||
|
Ok(old_evt)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// check if this is the desired tag
|
||||||
|
fn is_tag(&self, ns: &[u8], key: &str) -> bool {
|
||||||
|
let qname = match self.peek() {
|
||||||
|
Event::Start(bs) | Event::Empty(bs) => bs.name(),
|
||||||
|
Event::End(be) => be.name(),
|
||||||
|
_ => return false,
|
||||||
|
};
|
||||||
|
|
||||||
|
let (extr_ns, local) = self.rdr.resolve_element(qname);
|
||||||
|
|
||||||
|
if local.into_inner() != key.as_bytes() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
match extr_ns {
|
||||||
|
ResolveResult::Bound(v) => v.into_inner() == ns,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// find start tag
|
||||||
|
async fn tag_start(&mut self, ns: &[u8], key: &str) -> Result<Event<'static>, ParsingError> {
|
||||||
|
loop {
|
||||||
|
match self.peek() {
|
||||||
|
Event::Start(b) if self.is_tag(ns, key) => break,
|
||||||
|
_ => { self.skip().await?; },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.next().await
|
||||||
|
}
|
||||||
|
|
||||||
|
// find stop tag
|
||||||
|
async fn tag_stop(&mut self, ns: &[u8], key: &str) -> Result<Event<'static>, ParsingError> {
|
||||||
|
loop {
|
||||||
|
match self.peek() {
|
||||||
|
Event::End(b) if self.is_tag(ns, key) => break,
|
||||||
|
_ => { self.skip().await?; },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.next().await
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue