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 ---
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!();
}
}
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!();
}
}
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!();
}
}
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!();
}
}

View file

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

View file

@ -2,6 +2,7 @@
use chrono::{DateTime,Utc};
use super::types as dav;
use super::xml;
//@FIXME ACL (rfc3744) 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+)>
#[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) ---

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 tokio::io::AsyncWrite;
use super::types::*;
use super::xml::{Writer,QWrite,IWrite};
use super::xml::{Node, Writer,QWrite,IWrite};
// --- XML ROOTS

View file

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

View file

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

View file

@ -7,12 +7,11 @@ use super::error;
/// It's how we implement a DAV extension
/// (That's the dark magic part...)
pub trait Node<T> = xml::QRead<T> + xml::QWrite + Debug + PartialEq;
pub trait Extension {
type Error: Node<Self::Error>;
type Property: Node<Self::Property>;
type PropertyRequest: Node<Self::PropertyRequest>;
type ResourceType: Node<Self::ResourceType>;
pub trait Extension: std::fmt::Debug + PartialEq {
type Error: xml::Node<Self::Error>;
type Property: xml::Node<Self::Property>;
type PropertyRequest: xml::Node<Self::PropertyRequest>;
type ResourceType: xml::Node<Self::ResourceType>;
}
/// 14.1. activelock XML Element
@ -333,7 +332,7 @@ pub enum LockType {
///
/// <!ELEMENT multistatus (response*, responsedescription?) >
#[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 responsedescription: Option<ResponseDescription>,
}
@ -465,7 +464,7 @@ pub enum PropFind<E: Extension> {
///
/// <!ELEMENT propstat (prop, status, error?, responsedescription?) >
#[derive(Debug, PartialEq)]
pub struct PropStat<E: Extension, N: Node<N>> {
pub struct PropStat<E: Extension, N: xml::Node<N>> {
pub prop: N,
pub status: Status,
pub error: Option<Error<E>>,
@ -514,7 +513,7 @@ pub struct Remove<E: Extension>(pub PropName<E>);
/// --- rewritten as ---
/// <!ELEMENT response ((href+, status)|(href, propstat+), error?, responsedescription?, location?>
#[derive(Debug, PartialEq)]
pub enum StatusOrPropstat<E: Extension, N: Node<N>> {
pub enum StatusOrPropstat<E: Extension, N: xml::Node<N>> {
// One status, multiple hrefs...
Status(Vec<Href>, Status),
// A single href, multiple properties...
@ -522,7 +521,7 @@ pub enum StatusOrPropstat<E: Extension, N: Node<N>> {
}
#[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 error: Option<Error<E>>,
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>;
}
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
pub struct Writer<T: IWrite> {
pub q: quick_xml::writer::Writer<T>,
@ -106,6 +111,8 @@ impl<T: IRead> Reader<T> {
}
}
/*
* Disabled
/// maybe find start tag
pub async fn maybe_tag_start(&mut self, ns: &[u8], key: &str) -> Result<Option<Event<'static>>, ParsingError> {
println!("maybe start tag {}", key);
@ -118,7 +125,6 @@ impl<T: IRead> Reader<T> {
/// find start tag
pub async fn tag_start(&mut self, ns: &[u8], key: &str) -> Result<Event<'static>, ParsingError> {
println!("search start tag {}", key);
loop {
match self.peek() {
Event::Start(b) if self.is_tag(ns, key) => break,
@ -127,6 +133,7 @@ impl<T: IRead> Reader<T> {
}
self.next().await
}
*/
// find stop tag
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);
}
}