At least it compiles
This commit is contained in:
parent
9146537aaf
commit
1e3737a590
6 changed files with 369 additions and 47 deletions
100
src/dav/calencoder.rs
Normal file
100
src/dav/calencoder.rs
Normal file
|
@ -0,0 +1,100 @@
|
||||||
|
use super::encoder::{QuickWritable, Context};
|
||||||
|
use super::caltypes::*;
|
||||||
|
use super::types::Extension;
|
||||||
|
|
||||||
|
use quick_xml::Error as QError;
|
||||||
|
use quick_xml::events::{Event, BytesEnd, BytesStart, BytesText};
|
||||||
|
use quick_xml::writer::{ElementWriter, Writer};
|
||||||
|
use quick_xml::name::PrefixDeclaration;
|
||||||
|
use tokio::io::AsyncWrite;
|
||||||
|
|
||||||
|
/*pub trait CalWriter<E: Extension>: DavWriter<E> {
|
||||||
|
fn create_cal_element(&mut self, name: &str) -> ElementWriter<impl AsyncWrite + Unpin>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, W: AsyncWrite+Unpin> DavWriter<CalExtension> for Writer<'a, W, CalExtension> {
|
||||||
|
fn create_dav_element(&mut self, name: &str) -> ElementWriter<impl AsyncWrite + Unpin> {
|
||||||
|
self.create_ns_element(name, Namespace::Dav)
|
||||||
|
}
|
||||||
|
fn child(w: &'a mut QWriter<W>) -> impl DavWriter<CalExtension> {
|
||||||
|
Self::child(w)
|
||||||
|
}
|
||||||
|
async fn error(&mut self, err: &Violation) -> Result<(), QError> {
|
||||||
|
err.write(self).await
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, W: AsyncWrite+Unpin> CalWriter<CalExtension> for Writer<'a, W, CalExtension> {
|
||||||
|
fn create_cal_element(&mut self, name: &str) -> ElementWriter<impl AsyncWrite + Unpin> {
|
||||||
|
self.create_ns_element(name, Namespace::CalDav)
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
|
||||||
|
pub struct CalCtx {
|
||||||
|
root: bool
|
||||||
|
}
|
||||||
|
impl Context<CalExtension> for CalCtx {
|
||||||
|
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.push_attribute(("xmlns:C", "urn:ietf:params:xml:ns:caldav"));
|
||||||
|
}
|
||||||
|
start
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn hook_error(&self, err: &Violation, xml: &mut Writer<impl AsyncWrite+Unpin>) -> Result<(), QError> {
|
||||||
|
err.write(xml, self.child()).await
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl QuickWritable<CalExtension, CalCtx> for Violation {
|
||||||
|
async fn write(&self, xml: &mut Writer<impl AsyncWrite+Unpin>, _ctx: CalCtx) -> Result<(), QError> {
|
||||||
|
match self {
|
||||||
|
Self::SupportedFilter => xml
|
||||||
|
.create_element("supported-filter")
|
||||||
|
.write_empty_async().await?,
|
||||||
|
};
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
<D:error>
|
||||||
|
<C:supported-filter>
|
||||||
|
<C:prop-filter name="X-ABC-GUID"/>
|
||||||
|
</C:supported-filter>
|
||||||
|
</D:error>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
use crate::dav::types::{Error, Violation as DavViolation};
|
||||||
|
use tokio::io::AsyncWriteExt;
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_violation() {
|
||||||
|
let mut buffer = Vec::new();
|
||||||
|
let mut tokio_buffer = tokio::io::BufWriter::new(&mut buffer);
|
||||||
|
let mut writer = Writer::new_with_indent(&mut tokio_buffer, b' ', 4);
|
||||||
|
|
||||||
|
let res: Error<CalExtension> = Error(vec![
|
||||||
|
DavViolation::Extension(Violation::SupportedFilter),
|
||||||
|
]);
|
||||||
|
|
||||||
|
res.write(&mut writer, CalCtx{ root: true }).await.expect("xml serialization");
|
||||||
|
tokio_buffer.flush().await.expect("tokio buffer flush");
|
||||||
|
|
||||||
|
let expected = r#"<D:error xmlns:D="DAV:" xmlns:C="urn:ietf:params:xml:ns:caldav">
|
||||||
|
<C:supported-filter/>
|
||||||
|
</D:error>"#;
|
||||||
|
let got = std::str::from_utf8(buffer.as_slice()).unwrap();
|
||||||
|
|
||||||
|
assert_eq!(got, expected);
|
||||||
|
}
|
||||||
|
}
|
41
src/dav/caltypes.rs
Normal file
41
src/dav/caltypes.rs
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
use super::types::*;
|
||||||
|
|
||||||
|
pub enum Namespace {
|
||||||
|
Dav,
|
||||||
|
CalDav,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct CalExtension {}
|
||||||
|
impl Extension for CalExtension {
|
||||||
|
type Error = Violation;
|
||||||
|
type Namespace = Namespace;
|
||||||
|
|
||||||
|
fn namespaces() -> &'static [(&'static str, &'static str)] {
|
||||||
|
return &[ ("D", "DAV:"), ("C", "urn:ietf:params:xml:ns:caldav") ][..]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn short_ns(ns: Self::Namespace) -> &'static str {
|
||||||
|
match ns {
|
||||||
|
Namespace::Dav => "D",
|
||||||
|
Namespace::CalDav => "C",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum Violation {
|
||||||
|
/// (CALDAV:supported-filter): The CALDAV:comp-filter (see
|
||||||
|
/// Section 9.7.1), CALDAV:prop-filter (see Section 9.7.2), and
|
||||||
|
/// CALDAV:param-filter (see Section 9.7.3) XML elements used in the
|
||||||
|
/// CALDAV:filter XML element (see Section 9.7) in the REPORT request
|
||||||
|
/// only make reference to components, properties, and parameters for
|
||||||
|
/// which queries are supported by the server, i.e., if the CALDAV:
|
||||||
|
/// filter element attempts to reference an unsupported component,
|
||||||
|
/// property, or parameter, this precondition is violated. Servers
|
||||||
|
/// SHOULD report the CALDAV:comp-filter, CALDAV:prop-filter, or
|
||||||
|
/// CALDAV:param-filter for which it does not provide support.
|
||||||
|
///
|
||||||
|
/// <!ELEMENT supported-filter (comp-filter*,
|
||||||
|
/// prop-filter*,
|
||||||
|
/// param-filter*)>
|
||||||
|
SupportedFilter,
|
||||||
|
}
|
|
@ -1,61 +1,205 @@
|
||||||
use std::io::Cursor;
|
use std::io::Cursor;
|
||||||
|
|
||||||
use futures::stream::{StreamExt, TryStreamExt};
|
use quick_xml::Error as QError;
|
||||||
use quick_xml::Error;
|
|
||||||
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, Writer};
|
||||||
use quick_xml::name::PrefixDeclaration;
|
use quick_xml::name::PrefixDeclaration;
|
||||||
use tokio::io::AsyncWrite;
|
use tokio::io::AsyncWrite;
|
||||||
use super::types::*;
|
use super::types::*;
|
||||||
|
|
||||||
//@FIXME a cleaner way to manager namespace would be great
|
|
||||||
//but at the same time, the quick-xml library is not cooperating.
|
|
||||||
//So instead of writing many cursed workarounds - I tried, I am just hardcoding the namespaces...
|
|
||||||
|
|
||||||
pub trait Encode {
|
//-------------- TRAITS ----------------------
|
||||||
async fn write(&self, xml: &mut Writer<impl AsyncWrite + Unpin>) -> Result<(), Error>;
|
/*pub trait DavWriter<E: Extension> {
|
||||||
|
fn create_dav_element(&mut self, name: &str) -> ElementWriter<impl AsyncWrite + Unpin>;
|
||||||
|
fn child(w: &mut QWriter<impl AsyncWrite + Unpin>) -> impl DavWriter<E>;
|
||||||
|
async fn error(&mut self, err: &E::Error) -> Result<(), QError>;
|
||||||
|
}*/
|
||||||
|
|
||||||
|
/// Basic encode trait to make a type encodable
|
||||||
|
pub trait QuickWritable<E: Extension, C: Context<E>> {
|
||||||
|
async fn write(&self, xml: &mut Writer<impl AsyncWrite+Unpin>, ctx: C) -> Result<(), QError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Encode for Href {
|
pub trait Context<E: Extension> {
|
||||||
async fn write(&self, xml: &mut Writer<impl AsyncWrite + Unpin>) -> Result<(), Error> {
|
fn child(&self) -> Self;
|
||||||
xml.create_element("D:href")
|
fn create_dav_element(&self, name: &str) -> BytesStart;
|
||||||
|
async fn hook_error(&self, err: &E::Error, xml: &mut Writer<impl AsyncWrite+Unpin>) -> Result<(), QError>;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct NoExtCtx {
|
||||||
|
root: bool
|
||||||
|
}
|
||||||
|
impl Context<NoExtension> for NoExtCtx {
|
||||||
|
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!();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------- ENCODING --------------------
|
||||||
|
|
||||||
|
// --- XML ROOTS
|
||||||
|
impl<E: Extension, C: Context<E>> QuickWritable<E,C> for Multistatus<E> {
|
||||||
|
async fn write(&self, xml: &mut Writer<impl AsyncWrite+Unpin>, ctx: C) -> Result<(), QError> {
|
||||||
|
let start = ctx.create_dav_element("multistatus");
|
||||||
|
let end = start.to_end();
|
||||||
|
|
||||||
|
xml.write_event_async(Event::Start(start.clone())).await?;
|
||||||
|
for response in self.responses.iter() {
|
||||||
|
response.write(xml, ctx.child()).await?;
|
||||||
|
}
|
||||||
|
if let Some(description) = &self.responsedescription {
|
||||||
|
description.write(xml, ctx.child()).await?;
|
||||||
|
}
|
||||||
|
|
||||||
|
xml.write_event_async(Event::End(end)).await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// --- XML inner elements
|
||||||
|
impl<E: Extension, C: Context<E>> QuickWritable<E,C> for Href {
|
||||||
|
async fn write(&self, xml: &mut Writer<impl AsyncWrite+Unpin>, _ctx: C) -> Result<(), QError> {
|
||||||
|
xml.create_element("href")
|
||||||
.write_text_content_async(BytesText::new(&self.0))
|
.write_text_content_async(BytesText::new(&self.0))
|
||||||
.await?;
|
.await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Encode for Multistatus<T> {
|
impl<E: Extension, C: Context<E>> QuickWritable<E,C> for Response<E> {
|
||||||
async fn write(&self, xml: &mut Writer<impl AsyncWrite + Unpin>) -> Result<(), Error> {
|
async fn write(&self, xml: &mut Writer<impl AsyncWrite+Unpin>, ctx: C) -> Result<(), QError> {
|
||||||
xml.create_element("D:multistatus")
|
xml.create_element("response")
|
||||||
.with_attribute(("xmlns:D", "DAV:"))
|
.write_inner_content_async::<_, _, QError>(|inner_xml| async move {
|
||||||
.write_inner_content_async::<_, _, quick_xml::Error>(|inner_xml| async move {
|
self.href.write(inner_xml, ctx.child()).await?;
|
||||||
for response in self.responses.iter() {
|
self.status_or_propstat.write(inner_xml, ctx.child()).await?;
|
||||||
response.write(inner_xml).await?;
|
if let Some(error) = &self.error {
|
||||||
|
error.write(inner_xml, ctx.child()).await?;
|
||||||
}
|
}
|
||||||
|
if let Some(responsedescription) = &self.responsedescription {
|
||||||
if let Some(description) = &self.responsedescription {
|
responsedescription.write(inner_xml, ctx.child()).await?;
|
||||||
description.write(inner_xml).await?;
|
}
|
||||||
|
if let Some(location) = &self.location {
|
||||||
|
location.write(inner_xml, ctx.child()).await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(inner_xml)
|
Ok(inner_xml)
|
||||||
})
|
})
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<E: Extension, C: Context<E>> QuickWritable<E,C> for StatusOrPropstat<E> {
|
||||||
|
async fn write(&self, xml: &mut Writer<impl AsyncWrite+Unpin>, ctx: C) -> Result<(), QError> {
|
||||||
|
match self {
|
||||||
|
Self::Status(status) => status.write(xml, ctx.child()).await,
|
||||||
|
Self::PropStat(propstat_list) => {
|
||||||
|
for propstat in propstat_list.iter() {
|
||||||
|
propstat.write(xml, ctx.child()).await?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<E: Extension, C: Context<E>> QuickWritable<E,C> for Status {
|
||||||
|
async fn write(&self, xml: &mut Writer<impl AsyncWrite+Unpin>, ctx: C) -> Result<(), QError> {
|
||||||
|
xml.create_element("status")
|
||||||
|
.write_text_content_async(
|
||||||
|
BytesText::new(&format!("HTTP/1.1 {} {}", self.0.as_str(), self.0.canonical_reason().unwrap_or("No reason")))
|
||||||
|
)
|
||||||
.await?;
|
.await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Encode for Response<T> {
|
impl<E: Extension, C: Context<E>> QuickWritable<E,C> for ResponseDescription {
|
||||||
async fn write(&self, xml: &mut Writer<impl AsyncWrite + Unpin>) -> Result<(), Error> {
|
async fn write(&self, xml: &mut Writer<impl AsyncWrite+Unpin>, ctx: C) -> Result<(), QError> {
|
||||||
|
let start = ctx.create_dav_element("responsedescription");
|
||||||
|
let end = start.to_end();
|
||||||
|
|
||||||
|
xml.write_event_async(Event::Start(start.clone())).await?;
|
||||||
|
xml.write_event_async(Event::Text(BytesText::new(&self.0))).await?;
|
||||||
|
xml.write_event_async(Event::End(end)).await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<E: Extension, C: Context<E>> QuickWritable<E,C> for Location {
|
||||||
|
async fn write(&self, xml: &mut Writer<impl AsyncWrite+Unpin>, ctx: C) -> Result<(), QError> {
|
||||||
unimplemented!();
|
unimplemented!();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Encode for ResponseDescription {
|
impl<E: Extension, C: Context<E>> QuickWritable<E,C> for PropStat<E> {
|
||||||
async fn write(&self, xml: &mut Writer<impl AsyncWrite + Unpin>) -> Result<(), Error> {
|
async fn write(&self, xml: &mut Writer<impl AsyncWrite+Unpin>, ctx: C) -> Result<(), QError> {
|
||||||
xml.create_element("D:responsedescription")
|
unimplemented!();
|
||||||
.write_text_content_async(BytesText::new(&self.0))
|
}
|
||||||
.await?;
|
}
|
||||||
|
|
||||||
|
impl<E: Extension, C: Context<E>> QuickWritable<E,C> for Error<E> {
|
||||||
|
async fn write(&self, xml: &mut Writer<impl AsyncWrite+Unpin>, ctx: C) -> Result<(), QError> {
|
||||||
|
xml.create_element("error")
|
||||||
|
.write_inner_content_async::<_, _, QError>(|inner_xml| async move {
|
||||||
|
for violation in &self.0 {
|
||||||
|
violation.write(inner_xml, ctx.child()).await?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(inner_xml)
|
||||||
|
})
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<E: Extension, C: Context<E>> QuickWritable<E,C> for Violation<E> {
|
||||||
|
async fn write(&self, xml: &mut Writer<impl AsyncWrite+Unpin>, ctx: C) -> Result<(), QError> {
|
||||||
|
match self {
|
||||||
|
Violation::LockTokenMatchesRequestUri => xml.create_element("lock-token-matches-request-uri").write_empty_async().await?,
|
||||||
|
Violation::LockTokenSubmitted(hrefs) => xml
|
||||||
|
.create_element("lock-token-submitted")
|
||||||
|
.write_inner_content_async::<_, _, QError>(|inner_xml| async move {
|
||||||
|
for href in hrefs {
|
||||||
|
href.write(inner_xml, ctx.child()).await?;
|
||||||
|
}
|
||||||
|
Ok(inner_xml)
|
||||||
|
}
|
||||||
|
).await?,
|
||||||
|
Violation::NoConflictingLock(hrefs) => xml
|
||||||
|
.create_element("no-conflicting-lock")
|
||||||
|
.write_inner_content_async::<_, _, QError>(|inner_xml| async move {
|
||||||
|
for href in hrefs {
|
||||||
|
href.write(inner_xml, ctx.child()).await?;
|
||||||
|
}
|
||||||
|
Ok(inner_xml)
|
||||||
|
}
|
||||||
|
).await?,
|
||||||
|
Violation::NoExternalEntities => xml.create_element("no-external-entities").write_empty_async().await?,
|
||||||
|
Violation::PreservedLiveProperties => xml.create_element("preserved-live-properties").write_empty_async().await?,
|
||||||
|
Violation::PropfindFiniteDepth => xml.create_element("propfind-finite-depth").write_empty_async().await?,
|
||||||
|
Violation::CannotModifyProtectedProperty => xml.create_element("cannot-modify-protected-property").write_empty_async().await?,
|
||||||
|
Violation::Extension(inner) => {
|
||||||
|
ctx.hook_error(inner, xml).await?;
|
||||||
|
xml
|
||||||
|
},
|
||||||
|
};
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -74,7 +218,8 @@ mod tests {
|
||||||
let mut tokio_buffer = tokio::io::BufWriter::new(&mut buffer);
|
let mut tokio_buffer = tokio::io::BufWriter::new(&mut buffer);
|
||||||
let mut writer = Writer::new_with_indent(&mut tokio_buffer, b' ', 4);
|
let mut writer = Writer::new_with_indent(&mut tokio_buffer, b' ', 4);
|
||||||
|
|
||||||
Href("/SOGo/dav/so/".into()).write(&mut writer).await.expect("xml serialization");
|
let ctx = NoExtCtx{ root: true };
|
||||||
|
Href("/SOGo/dav/so/".into()).write(&mut writer, ctx).await.expect("xml serialization");
|
||||||
tokio_buffer.flush().await.expect("tokio buffer flush");
|
tokio_buffer.flush().await.expect("tokio buffer flush");
|
||||||
|
|
||||||
assert_eq!(buffer.as_slice(), &b"<D:href>/SOGo/dav/so/</D:href>"[..]);
|
assert_eq!(buffer.as_slice(), &b"<D:href>/SOGo/dav/so/</D:href>"[..]);
|
||||||
|
@ -87,8 +232,9 @@ mod tests {
|
||||||
let mut tokio_buffer = tokio::io::BufWriter::new(&mut buffer);
|
let mut tokio_buffer = tokio::io::BufWriter::new(&mut buffer);
|
||||||
let mut writer = Writer::new_with_indent(&mut tokio_buffer, b' ', 4);
|
let mut writer = Writer::new_with_indent(&mut tokio_buffer, b' ', 4);
|
||||||
|
|
||||||
let xml: Multistatus<u64> = Multistatus { responses: vec![], responsedescription: Some(ResponseDescription("Hello world".into())) };
|
let ctx = NoExtCtx{ root: true };
|
||||||
xml.write(&mut writer).await.expect("xml serialization");
|
let xml: Multistatus<NoExtension> = Multistatus { responses: vec![], responsedescription: Some(ResponseDescription("Hello world".into())) };
|
||||||
|
xml.write(&mut writer, ctx).await.expect("xml serialization");
|
||||||
tokio_buffer.flush().await.expect("tokio buffer flush");
|
tokio_buffer.flush().await.expect("tokio buffer flush");
|
||||||
|
|
||||||
let expected = r#"<D:multistatus xmlns:D="DAV:">
|
let expected = r#"<D:multistatus xmlns:D="DAV:">
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
mod types;
|
mod types;
|
||||||
|
mod caltypes;
|
||||||
mod encoder;
|
mod encoder;
|
||||||
|
mod calencoder;
|
||||||
|
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,34 @@
|
||||||
|
|
||||||
use chrono::{DateTime,FixedOffset};
|
use chrono::{DateTime,FixedOffset};
|
||||||
|
|
||||||
|
/// Extension utilities
|
||||||
|
pub struct Disabled(());
|
||||||
|
pub trait Extension {
|
||||||
|
type Error;
|
||||||
|
type Namespace;
|
||||||
|
|
||||||
|
fn namespaces() -> &'static [(&'static str, &'static str)];
|
||||||
|
fn short_ns(ns: Self::Namespace) -> &'static str;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// No extension
|
||||||
|
pub struct NoExtension {}
|
||||||
|
pub enum Namespace {
|
||||||
|
Dav
|
||||||
|
}
|
||||||
|
impl Extension for NoExtension {
|
||||||
|
type Error = Disabled;
|
||||||
|
type Namespace = Namespace;
|
||||||
|
|
||||||
|
fn namespaces() -> &'static [(&'static str, &'static str)] {
|
||||||
|
return &[ ("D", "DAV:") ][..]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn short_ns(ns: Self::Namespace) -> &'static str {
|
||||||
|
"D"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// 14.1. activelock XML Element
|
/// 14.1. activelock XML Element
|
||||||
///
|
///
|
||||||
/// Name: activelock
|
/// Name: activelock
|
||||||
|
@ -10,11 +38,11 @@ use chrono::{DateTime,FixedOffset};
|
||||||
/// <!ELEMENT activelock (lockscope, locktype, depth, owner?, timeout?,
|
/// <!ELEMENT activelock (lockscope, locktype, depth, owner?, timeout?,
|
||||||
/// locktoken?, lockroot)>
|
/// locktoken?, lockroot)>
|
||||||
pub struct ActiveLock {
|
pub struct ActiveLock {
|
||||||
lockscope: u64,
|
lockscope: LockScope,
|
||||||
locktype: u64,
|
locktype: LockType,
|
||||||
depth: Depth,
|
depth: Depth,
|
||||||
owner: Option<u64>,
|
owner: Option<Owner>,
|
||||||
timeout: Option<u64>,
|
timeout: Option<Timeout>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 14.2 allprop XML Element
|
/// 14.2 allprop XML Element
|
||||||
|
@ -72,7 +100,8 @@ pub enum Depth {
|
||||||
/// postcondition code. Unrecognized elements MUST be ignored.
|
/// postcondition code. Unrecognized elements MUST be ignored.
|
||||||
///
|
///
|
||||||
/// <!ELEMENT error ANY >
|
/// <!ELEMENT error ANY >
|
||||||
pub enum Error<T> {
|
pub struct Error<T: Extension>(pub Vec<Violation<T>>);
|
||||||
|
pub enum Violation<T: Extension> {
|
||||||
/// Name: lock-token-matches-request-uri
|
/// Name: lock-token-matches-request-uri
|
||||||
///
|
///
|
||||||
/// Use with: 409 Conflict
|
/// Use with: 409 Conflict
|
||||||
|
@ -156,7 +185,7 @@ pub enum Error<T> {
|
||||||
CannotModifyProtectedProperty,
|
CannotModifyProtectedProperty,
|
||||||
|
|
||||||
/// Specific errors
|
/// Specific errors
|
||||||
Extensions(T),
|
Extension(T::Error),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 14.6. exclusive XML Element
|
/// 14.6. exclusive XML Element
|
||||||
|
@ -312,7 +341,7 @@ 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> {
|
pub struct Multistatus<T: Extension> {
|
||||||
pub responses: Vec<Response<T>>,
|
pub responses: Vec<Response<T>>,
|
||||||
pub responsedescription: Option<ResponseDescription>,
|
pub responsedescription: Option<ResponseDescription>,
|
||||||
}
|
}
|
||||||
|
@ -416,7 +445,7 @@ pub struct PropName {}
|
||||||
/// 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> {
|
pub struct PropStat<T: Extension> {
|
||||||
prop: Prop,
|
prop: Prop,
|
||||||
status: Status,
|
status: Status,
|
||||||
error: Option<Error<T>>,
|
error: Option<Error<T>>,
|
||||||
|
@ -460,13 +489,16 @@ pub struct Remove(Prop);
|
||||||
///
|
///
|
||||||
/// <!ELEMENT response (href, ((href*, status)|(propstat+)),
|
/// <!ELEMENT response (href, ((href*, status)|(propstat+)),
|
||||||
/// error?, responsedescription? , location?) >
|
/// error?, responsedescription? , location?) >
|
||||||
pub struct Response<T> {
|
pub enum StatusOrPropstat<T: Extension> {
|
||||||
href: Vec<Href>,
|
Status(Status),
|
||||||
status: Status,
|
PropStat(Vec<PropStat<T>>),
|
||||||
propstat: Vec<PropStat<T>>,
|
}
|
||||||
error: Option<Error<T>>,
|
pub struct Response<T: Extension> {
|
||||||
responsedescription: Option<ResponseDescription>,
|
pub href: Href, // It's wrong according to the spec, but I don't understand why there is an href*
|
||||||
location: Option<u64>,
|
pub status_or_propstat: StatusOrPropstat<T>,
|
||||||
|
pub error: Option<Error<T>>,
|
||||||
|
pub responsedescription: Option<ResponseDescription>,
|
||||||
|
pub location: Option<Location>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 14.25. responsedescription XML Element
|
/// 14.25. responsedescription XML Element
|
||||||
|
@ -521,7 +553,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
|
||||||
pub struct Status(http::status::StatusCode);
|
pub struct Status(pub http::status::StatusCode);
|
||||||
|
|
||||||
/// 14.29. timeout XML Element
|
/// 14.29. timeout XML Element
|
||||||
///
|
///
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
#![feature(type_alias_impl_trait)]
|
||||||
#![feature(async_fn_in_trait)]
|
#![feature(async_fn_in_trait)]
|
||||||
|
|
||||||
mod auth;
|
mod auth;
|
||||||
|
|
Loading…
Reference in a new issue