Rewrote the whole decoder

This commit is contained in:
Quentin 2024-03-06 23:24:54 +01:00
parent 67e5953c24
commit 5e71a7d848
Signed by: quentin
GPG Key ID: E9602264D639FF68
9 changed files with 406 additions and 470 deletions

View File

@ -7,25 +7,25 @@ use super::error;
// ---- EXTENSIONS --- // ---- EXTENSIONS ---
impl xml::QRead<Violation> for Violation { impl xml::QRead<Violation> for Violation {
async fn qread(xml: &mut xml::Reader<impl xml::IRead>) -> Result<Option<Self>, error::ParsingError> { async fn qread(xml: &mut xml::Reader<impl xml::IRead>) -> Result<Self, error::ParsingError> {
unreachable!(); unreachable!();
} }
} }
impl xml::QRead<Property> for Property { impl xml::QRead<Property> for Property {
async fn qread(xml: &mut xml::Reader<impl xml::IRead>) -> Result<Option<Self>, error::ParsingError> { async fn qread(xml: &mut xml::Reader<impl xml::IRead>) -> Result<Self, error::ParsingError> {
unreachable!(); unreachable!();
} }
} }
impl xml::QRead<PropertyRequest> for PropertyRequest { impl xml::QRead<PropertyRequest> for PropertyRequest {
async fn qread(xml: &mut xml::Reader<impl xml::IRead>) -> Result<Option<Self>, error::ParsingError> { async fn qread(xml: &mut xml::Reader<impl xml::IRead>) -> Result<Self, error::ParsingError> {
unreachable!(); unreachable!();
} }
} }
impl xml::QRead<ResourceType> for ResourceType { impl xml::QRead<ResourceType> for ResourceType {
async fn qread(xml: &mut xml::Reader<impl xml::IRead>) -> Result<Option<Self>, error::ParsingError> { async fn qread(xml: &mut xml::Reader<impl xml::IRead>) -> Result<Self, error::ParsingError> {
unreachable!(); unreachable!();
} }
} }

View File

@ -4,8 +4,8 @@ use quick_xml::name::PrefixDeclaration;
use tokio::io::AsyncWrite; use tokio::io::AsyncWrite;
use super::caltypes::*; use super::caltypes::*;
use super::xml::{QWrite, IWrite, Writer}; use super::xml::{Node, QWrite, IWrite, Writer};
use super::types::{Extension, Node}; use super::types::Extension;
const ICAL_DATETIME_FMT: &str = "%Y%m%dT%H%M%SZ"; const ICAL_DATETIME_FMT: &str = "%Y%m%dT%H%M%SZ";

View File

@ -2,6 +2,7 @@
use chrono::{DateTime,Utc}; use chrono::{DateTime,Utc};
use super::types as dav; use super::types as dav;
use super::xml;
//@FIXME ACL (rfc3744) is missing, required //@FIXME ACL (rfc3744) is missing, required
//@FIXME Versioning (rfc3253) is missing, required //@FIXME Versioning (rfc3253) is missing, required
@ -44,7 +45,7 @@ pub struct MkCalendar<E: dav::Extension>(pub dav::Set<E>);
/// ///
/// <!ELEMENT mkcol-response (propstat+)> /// <!ELEMENT mkcol-response (propstat+)>
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
pub struct MkCalendarResponse<E: dav::Extension, N: dav::Node<N>>(pub Vec<dav::PropStat<E,N>>); pub struct MkCalendarResponse<E: dav::Extension, N: xml::Node<N>>(pub Vec<dav::PropStat<E,N>>);
// --- (REPORT PART) --- // --- (REPORT PART) ---

File diff suppressed because it is too large Load Diff

View File

@ -6,7 +6,7 @@ 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}; use super::xml::{Node, Writer,QWrite,IWrite};
// --- XML ROOTS // --- XML ROOTS

View File

@ -2,6 +2,7 @@ use quick_xml::events::attributes::AttrError;
#[derive(Debug)] #[derive(Debug)]
pub enum ParsingError { pub enum ParsingError {
Recoverable,
MissingChild, MissingChild,
NamespacePrefixAlreadyUsed, NamespacePrefixAlreadyUsed,
WrongToken, WrongToken,

View File

@ -6,8 +6,8 @@ use super::error;
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
pub struct Disabled(()); pub struct Disabled(());
impl xml::QRead<Disabled> for Disabled { impl xml::QRead<Disabled> for Disabled {
async fn qread(xml: &mut xml::Reader<impl xml::IRead>) -> Result<Option<Self>, error::ParsingError> { async fn qread(xml: &mut xml::Reader<impl xml::IRead>) -> Result<Self, error::ParsingError> {
Ok(None) Err(error::ParsingError::Recoverable)
} }
} }
impl xml::QWrite for Disabled { impl xml::QWrite for Disabled {

View File

@ -7,12 +7,11 @@ use super::error;
/// It's how we implement a DAV extension /// It's how we implement a DAV extension
/// (That's the dark magic part...) /// (That's the dark magic part...)
pub trait Node<T> = xml::QRead<T> + xml::QWrite + Debug + PartialEq; pub trait Extension: std::fmt::Debug + PartialEq {
pub trait Extension { type Error: xml::Node<Self::Error>;
type Error: Node<Self::Error>; type Property: xml::Node<Self::Property>;
type Property: Node<Self::Property>; type PropertyRequest: xml::Node<Self::PropertyRequest>;
type PropertyRequest: Node<Self::PropertyRequest>; type ResourceType: xml::Node<Self::ResourceType>;
type ResourceType: Node<Self::ResourceType>;
} }
/// 14.1. activelock XML Element /// 14.1. activelock XML Element
@ -333,7 +332,7 @@ pub enum LockType {
/// ///
/// <!ELEMENT multistatus (response*, responsedescription?) > /// <!ELEMENT multistatus (response*, responsedescription?) >
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
pub struct Multistatus<E: Extension, N: Node<N>> { pub struct Multistatus<E: Extension, N: xml::Node<N>> {
pub responses: Vec<Response<E, N>>, pub responses: Vec<Response<E, N>>,
pub responsedescription: Option<ResponseDescription>, pub responsedescription: Option<ResponseDescription>,
} }
@ -465,7 +464,7 @@ pub enum PropFind<E: Extension> {
/// ///
/// <!ELEMENT propstat (prop, status, error?, responsedescription?) > /// <!ELEMENT propstat (prop, status, error?, responsedescription?) >
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
pub struct PropStat<E: Extension, N: Node<N>> { pub struct PropStat<E: Extension, N: xml::Node<N>> {
pub prop: N, pub prop: N,
pub status: Status, pub status: Status,
pub error: Option<Error<E>>, pub error: Option<Error<E>>,
@ -514,7 +513,7 @@ pub struct Remove<E: Extension>(pub PropName<E>);
/// --- rewritten as --- /// --- rewritten as ---
/// <!ELEMENT response ((href+, status)|(href, propstat+), error?, responsedescription?, location?> /// <!ELEMENT response ((href+, status)|(href, propstat+), error?, responsedescription?, location?>
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
pub enum StatusOrPropstat<E: Extension, N: Node<N>> { pub enum StatusOrPropstat<E: Extension, N: xml::Node<N>> {
// One status, multiple hrefs... // One status, multiple hrefs...
Status(Vec<Href>, Status), Status(Vec<Href>, Status),
// A single href, multiple properties... // A single href, multiple properties...
@ -522,7 +521,7 @@ pub enum StatusOrPropstat<E: Extension, N: Node<N>> {
} }
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
pub struct Response<E: Extension, N: Node<N>> { pub struct Response<E: Extension, N: xml::Node<N>> {
pub status_or_propstat: StatusOrPropstat<E, N>, pub status_or_propstat: StatusOrPropstat<E, N>,
pub error: Option<Error<E>>, pub error: Option<Error<E>>,
pub responsedescription: Option<ResponseDescription>, pub responsedescription: Option<ResponseDescription>,

View File

@ -19,9 +19,14 @@ pub trait QWrite {
async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), quick_xml::Error>; async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), quick_xml::Error>;
} }
pub trait QRead<T> { pub trait QRead<T> {
async fn qread(xml: &mut Reader<impl IRead>) -> Result<Option<T>, ParsingError>; async fn qread(xml: &mut Reader<impl IRead>) -> Result<T, ParsingError>;
} }
// The representation of an XML node in Rust
pub trait Node<T> = QRead<T> + QWrite + std::fmt::Debug + PartialEq;
// ---------------
/// Transform a Rust object into an XML stream of characters /// Transform a Rust object into an XML stream of characters
pub struct Writer<T: IWrite> { pub struct Writer<T: IWrite> {
pub q: quick_xml::writer::Writer<T>, pub q: quick_xml::writer::Writer<T>,
@ -106,6 +111,8 @@ impl<T: IRead> Reader<T> {
} }
} }
/*
* Disabled
/// maybe find start tag /// maybe find start tag
pub async fn maybe_tag_start(&mut self, ns: &[u8], key: &str) -> Result<Option<Event<'static>>, ParsingError> { pub async fn maybe_tag_start(&mut self, ns: &[u8], key: &str) -> Result<Option<Event<'static>>, ParsingError> {
println!("maybe start tag {}", key); println!("maybe start tag {}", key);
@ -118,7 +125,6 @@ impl<T: IRead> Reader<T> {
/// find start tag /// find start tag
pub async fn tag_start(&mut self, ns: &[u8], key: &str) -> Result<Event<'static>, ParsingError> { pub async fn tag_start(&mut self, ns: &[u8], key: &str) -> Result<Event<'static>, ParsingError> {
println!("search start tag {}", key);
loop { loop {
match self.peek() { match self.peek() {
Event::Start(b) if self.is_tag(ns, key) => break, Event::Start(b) if self.is_tag(ns, key) => break,
@ -127,6 +133,7 @@ impl<T: IRead> Reader<T> {
} }
self.next().await self.next().await
} }
*/
// find stop tag // find stop tag
pub async fn tag_stop(&mut self, ns: &[u8], key: &str) -> Result<Event<'static>, ParsingError> { pub async fn tag_stop(&mut self, ns: &[u8], key: &str) -> Result<Event<'static>, ParsingError> {
@ -157,5 +164,81 @@ impl<T: IRead> Reader<T> {
}; };
} }
} }
// NEW API
pub async fn maybe_read<N: Node<N>>(&mut self, t: &mut Option<N>, dirty: &mut bool) -> Result<(), ParsingError> {
match N::qread(self).await {
Ok(v) => {
*t = Some(v);
*dirty = true;
Ok(())
},
Err(ParsingError::Recoverable) => Ok(()),
Err(e) => Err(e),
}
}
pub async fn maybe_push<N: Node<N>>(&mut self, t: &mut Vec<N>, dirty: &mut bool) -> Result<(), ParsingError> {
match N::qread(self).await {
Ok(v) => {
t.push(v);
*dirty = true;
Ok(())
},
Err(ParsingError::Recoverable) => Ok(()),
Err(e) => Err(e),
}
}
pub async fn find<N: Node<N>>(&mut self) -> Result<N, ParsingError> {
loop {
// Try parse
match N::qread(self).await {
Err(ParsingError::Recoverable) => (),
otherwise => return otherwise,
}
// If recovered, skip the element
self.skip().await?;
}
}
pub async fn maybe_find<N: Node<N>>(&mut self) -> Result<Option<N>, ParsingError> {
loop {
// Try parse
match N::qread(self).await {
Err(ParsingError::Recoverable) => (),
otherwise => return otherwise.map(Some),
}
match self.peek() {
Event::End(_) => return Ok(None),
_ => self.skip().await?,
};
}
}
pub async fn collect<N: Node<N>>(&mut self) -> Result<Vec<N>, ParsingError> {
let mut acc = Vec::new();
loop {
match N::qread(self).await {
Err(ParsingError::Recoverable) => match self.peek() {
Event::End(_) => return Ok(acc),
_ => {
self.skip().await?;
},
},
Ok(v) => acc.push(v),
Err(e) => return Err(e),
}
}
}
pub async fn open(&mut self, ns: &[u8], key: &str) -> Result<Event<'static>, ParsingError> {
if self.is_tag(ns, key) {
return self.next().await
}
return Err(ParsingError::Recoverable);
}
} }