From 9146537aaf9c8aef504dc3ed050992e97d907edd Mon Sep 17 00:00:00 2001 From: Quentin Dufour Date: Thu, 29 Feb 2024 10:17:46 +0100 Subject: [PATCH] WIP XML encoder --- src/dav/encoder.rs | 61 +++++++++++++++++++++++++++++++++++++++++++--- src/dav/types.rs | 7 +++--- 2 files changed, 61 insertions(+), 7 deletions(-) diff --git a/src/dav/encoder.rs b/src/dav/encoder.rs index 28f807a..552f183 100644 --- a/src/dav/encoder.rs +++ b/src/dav/encoder.rs @@ -1,6 +1,7 @@ use std::io::Cursor; -use anyhow::Result; +use futures::stream::{StreamExt, TryStreamExt}; +use quick_xml::Error; use quick_xml::events::{Event, BytesEnd, BytesStart, BytesText}; use quick_xml::writer::{ElementWriter, Writer}; use quick_xml::name::PrefixDeclaration; @@ -12,19 +13,52 @@ use super::types::*; //So instead of writing many cursed workarounds - I tried, I am just hardcoding the namespaces... pub trait Encode { - async fn write(&self, xml: &mut Writer) -> Result<()>; + async fn write(&self, xml: &mut Writer) -> Result<(), Error>; } impl Encode for Href { - async fn write(&self, xml: &mut Writer) -> Result<()> { + async fn write(&self, xml: &mut Writer) -> Result<(), Error> { xml.create_element("D:href") .write_text_content_async(BytesText::new(&self.0)) .await?; - Ok(()) } } +impl Encode for Multistatus { + async fn write(&self, xml: &mut Writer) -> Result<(), Error> { + xml.create_element("D:multistatus") + .with_attribute(("xmlns:D", "DAV:")) + .write_inner_content_async::<_, _, quick_xml::Error>(|inner_xml| async move { + for response in self.responses.iter() { + response.write(inner_xml).await?; + } + + if let Some(description) = &self.responsedescription { + description.write(inner_xml).await?; + } + + Ok(inner_xml) + }) + .await?; + Ok(()) + } +} + +impl Encode for Response { + async fn write(&self, xml: &mut Writer) -> Result<(), Error> { + unimplemented!(); + } +} + +impl Encode for ResponseDescription { + async fn write(&self, xml: &mut Writer) -> Result<(), Error> { + xml.create_element("D:responsedescription") + .write_text_content_async(BytesText::new(&self.0)) + .await?; + Ok(()) + } +} #[cfg(test)] mod tests { @@ -45,4 +79,23 @@ mod tests { assert_eq!(buffer.as_slice(), &b"/SOGo/dav/so/"[..]); } + + + #[tokio::test] + async fn test_multistatus() { + 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 xml: Multistatus = Multistatus { responses: vec![], responsedescription: Some(ResponseDescription("Hello world".into())) }; + xml.write(&mut writer).await.expect("xml serialization"); + tokio_buffer.flush().await.expect("tokio buffer flush"); + + let expected = r#" + Hello world +"#; + let got = std::str::from_utf8(buffer.as_slice()).unwrap(); + + assert_eq!(got, expected); + } } diff --git a/src/dav/types.rs b/src/dav/types.rs index 1ff690f..7bbea8e 100644 --- a/src/dav/types.rs +++ b/src/dav/types.rs @@ -313,8 +313,8 @@ pub enum LockType { /// /// pub struct Multistatus { - responses: Vec>, - responsedescription: Option, + pub responses: Vec>, + pub responsedescription: Option, } /// 14.17. owner XML Element @@ -480,7 +480,7 @@ pub struct Response { /// user. /// /// -pub struct ResponseDescription(String); +pub struct ResponseDescription(pub String); /// 14.26. set XML Element /// @@ -573,6 +573,7 @@ pub enum PropertyRequest { GetLastModified, LockDiscovery, ResourceType, + SupportedLock, } pub enum Property { /// 15.1. creationdate Property