beginning...
This commit is contained in:
parent
ad25912a0f
commit
c9edf6c37c
2 changed files with 88 additions and 100 deletions
|
@ -1,17 +1,18 @@
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
|
||||||
use im::HashMap;
|
use quick_xml::events::{Event, BytesStart, BytesDecl, BytesText};
|
||||||
use quick_xml::events::{BytesStart, BytesText};
|
|
||||||
use quick_xml::events::attributes::AttrError;
|
use quick_xml::events::attributes::AttrError;
|
||||||
use quick_xml::name::PrefixDeclaration;
|
use quick_xml::name::{Namespace, QName, PrefixDeclaration, ResolveResult, ResolveResult::*};
|
||||||
use quick_xml::reader::Reader;
|
use quick_xml::reader::NsReader;
|
||||||
use tokio::io::AsyncBufRead;
|
use tokio::io::AsyncBufRead;
|
||||||
|
|
||||||
use super::types::*;
|
use super::types::*;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub enum ParsingError {
|
pub enum ParsingError {
|
||||||
NamespacePrefixAlreadyUsed,
|
NamespacePrefixAlreadyUsed,
|
||||||
WrongToken,
|
WrongToken,
|
||||||
|
TagNotFound,
|
||||||
QuickXml(quick_xml::Error)
|
QuickXml(quick_xml::Error)
|
||||||
}
|
}
|
||||||
impl From<AttrError> for ParsingError {
|
impl From<AttrError> for ParsingError {
|
||||||
|
@ -29,112 +30,98 @@ 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";
|
||||||
|
const DAV_NS: ResolveResult = Bound(Namespace(DAV_URN));
|
||||||
|
|
||||||
#[derive(PartialEq, Clone)]
|
pub struct PeekRead<T: AsyncBufRead+Unpin> {
|
||||||
pub enum XmlNamespace {
|
evt: Event<'static>,
|
||||||
None,
|
rdr: NsReader<T>,
|
||||||
Dav,
|
buf: Vec<u8>,
|
||||||
CalDav,
|
|
||||||
CardDav,
|
|
||||||
Xml,
|
|
||||||
Unknown(Vec<u8>),
|
|
||||||
}
|
}
|
||||||
impl From<&[u8]> for XmlNamespace {
|
impl<T: AsyncBufRead+Unpin> PeekRead<T> {
|
||||||
fn from(value: &[u8]) -> Self {
|
async fn new(mut rdr: NsReader<T>) -> Result<Self, ParsingError> {
|
||||||
match value {
|
let mut buf: Vec<u8> = vec![];
|
||||||
[] => Self::None,
|
let evt = rdr.read_event_into_async(&mut buf).await?.into_owned();
|
||||||
DAV_URN => Self::Dav,
|
buf.clear();
|
||||||
CALDAV_URN => Self::CalDav,
|
Ok(Self { evt, rdr, buf })
|
||||||
CARDDAV_URN => Self::CardDav,
|
|
||||||
XML_URN => Self::Xml,
|
|
||||||
v => Self::Unknown(v.into()),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/// Context must stay cheap to clone
|
fn peek(&self) -> &Event<'static> {
|
||||||
/// as we are cloning it from one fonction to another
|
&self.evt
|
||||||
#[derive(Clone)]
|
}
|
||||||
pub struct Context<'a, E: Extension + Clone> {
|
// skip tag, some tags can't be skipped like end, text, cdata
|
||||||
pub aliases: HashMap<&'a [u8], XmlNamespace>,
|
async fn skip(&mut self) -> Result<(), ParsingError> {
|
||||||
phantom: std::marker::PhantomData<E>,
|
match &self.evt {
|
||||||
}
|
Event::Start(b) => {
|
||||||
impl<'a, E: Extension + Clone> Context<'a, E> {
|
let _span = self.rdr.read_to_end_into_async(b.to_end().name(), &mut self.buf).await?;
|
||||||
/// External buffer
|
self.next().await
|
||||||
pub fn new() -> Self {
|
},
|
||||||
Self {
|
Event::Empty(_) | Event::Comment(_) | Event::PI(_) | Event::Decl(_) | Event::DocType(_) => self.next().await,
|
||||||
aliases: HashMap::new(),
|
_ => return Err(ParsingError::WrongToken),
|
||||||
phantom: std::marker::PhantomData
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ns_scan(&mut self, token: &'a BytesStart<'a>) -> Result<(XmlNamespace, &[u8]), ParsingError> {
|
// read one more tag
|
||||||
// Register namespace aliases from attributes (aka namespace bindings)
|
async fn next(&mut self) -> Result<(), ParsingError> {
|
||||||
for attr_res in token.attributes() {
|
let evt = self.rdr.read_event_into_async(&mut self.buf).await?.into_owned();
|
||||||
let attr = attr_res?;
|
self.buf.clear();
|
||||||
match attr.key.as_namespace_binding() {
|
self.evt = evt;
|
||||||
None => (),
|
Ok(())
|
||||||
Some(PrefixDeclaration::Named(prefix)) => self.ns_alias(attr.value.as_ref(), prefix.as_ref())?,
|
}
|
||||||
Some(PrefixDeclaration::Default) => self.ns_default(attr.value.as_ref())?,
|
}
|
||||||
|
|
||||||
|
pub trait QReadable<T: AsyncBufRead+Unpin>: Sized {
|
||||||
|
async fn read(xml: &mut PeekRead<T>) -> Result<Self, ParsingError>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<E: Extension, T: AsyncBufRead+Unpin> QReadable<T> for PropFind<E> {
|
||||||
|
async fn read(xml: &mut PeekRead<T>) -> Result<PropFind<E>, ParsingError> {
|
||||||
|
|
||||||
|
// Find propfind
|
||||||
|
loop {
|
||||||
|
match xml.peek() {
|
||||||
|
Event::Start(b) if b.local_name().into_inner() == &b"propfind"[..] => break,
|
||||||
|
_ => xml.skip().await?,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
xml.next().await?;
|
||||||
|
|
||||||
|
// Find any tag
|
||||||
|
let propfind = loop {
|
||||||
|
match xml.peek() {
|
||||||
|
Event::Start(b) | Event::Empty(b) if b.local_name().into_inner() == &b"allprop"[..] => {
|
||||||
|
unimplemented!()
|
||||||
|
},
|
||||||
|
Event::Start(b) if b.local_name().into_inner() == &b"prop"[..] => {
|
||||||
|
unimplemented!();
|
||||||
|
},
|
||||||
|
Event::Empty(b) if b.local_name().into_inner() == &b"propname"[..] => break PropFind::PropName,
|
||||||
|
_ => xml.skip().await?,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
xml.next().await?;
|
||||||
|
|
||||||
|
// Close tag
|
||||||
|
loop {
|
||||||
|
match xml.peek() {
|
||||||
|
Event::End(b) if b.local_name().into_inner() == &b"propfind"[..] => break,
|
||||||
|
_ => xml.skip().await?,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decompose tag name
|
Ok(propfind)
|
||||||
let (key, maybe_prefix) = token.name().decompose();
|
|
||||||
let ns = self.ns_resolve(maybe_prefix.map(|p| p.into_inner()).unwrap_or(&b""[..]));
|
|
||||||
|
|
||||||
Ok((ns, key.into_inner()))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn ns_default(&mut self, fqns: &[u8]) -> Result<(), ParsingError> {
|
|
||||||
self.ns_alias(fqns, &b""[..])
|
|
||||||
}
|
|
||||||
|
|
||||||
fn ns_alias(&mut self, fqns: &[u8], alias: &'a [u8]) -> Result<(), ParsingError> {
|
|
||||||
let parsed_ns = XmlNamespace::from(fqns);
|
|
||||||
if let Some(reg_fqns) = self.aliases.get(alias) {
|
|
||||||
if *reg_fqns != parsed_ns {
|
|
||||||
return Err(ParsingError::NamespacePrefixAlreadyUsed)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
self.aliases.insert(alias, parsed_ns);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the namespace is not found in the alias table (binding table)
|
|
||||||
// we suppose it's a fully qualified namespace (fqns)
|
|
||||||
fn ns_resolve(&self, prefix: &[u8]) -> XmlNamespace {
|
|
||||||
match self.aliases.get(prefix) {
|
|
||||||
Some(fqns) => fqns.clone(),
|
|
||||||
None => XmlNamespace::from(prefix),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
trait DavReader<'a> {
|
#[cfg(test)]
|
||||||
async fn doctype(&self) -> Result<(), ParsingError>;
|
mod tests {
|
||||||
async fn tag(&self) -> Result<BytesStart<'a>, ParsingError>;
|
use super::*;
|
||||||
async fn txt(&self) -> Result<Cow<'a, u8>, ParsingError>;
|
|
||||||
}
|
#[tokio::test]
|
||||||
/*impl<'a, I: AsyncBufRead+Unpin> DavReader<'a> for Reader<I> {
|
async fn basic_propfind() {
|
||||||
async fn doctype(&self) -> Result<(), ParsingError> {
|
let src = r#"<?xml version="1.0" encoding="utf-8" ?><rando/><garbage><old/></garbage><D:propfind xmlns:D="DAV:"><D:propname/></D:propfind>"#;
|
||||||
}
|
|
||||||
async fn tag(&self) -> Result<BytesStart<'a>, ParsingError> {
|
let mut rdr = PeekRead::new(NsReader::from_reader(src.as_bytes())).await.unwrap();
|
||||||
}
|
let got = PropFind::<NoExtension>::read(&mut rdr).await.unwrap();
|
||||||
async fn txt(&self) -> Result<Cow<'a, u8>, ParsingError> {
|
assert!(matches!(got, PropFind::PropName));
|
||||||
}
|
}
|
||||||
}*/
|
|
||||||
|
|
||||||
pub async fn propfind<E: Extension+Clone>(
|
|
||||||
xml: &mut Reader<impl AsyncBufRead+Unpin>,
|
|
||||||
ctx: Context<'_, E>,
|
|
||||||
buf: &mut Vec<u8>,
|
|
||||||
) -> Result<PropFind<E>, ParsingError> {
|
|
||||||
let local = ctx.clone();
|
|
||||||
|
|
||||||
match xml.read_event_into_async(buf).await? {
|
|
||||||
_ => unimplemented!(),
|
|
||||||
}
|
|
||||||
|
|
||||||
unimplemented!();
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,8 @@ impl Extension for NoExtension {
|
||||||
type Property = Disabled;
|
type Property = Disabled;
|
||||||
type PropertyRequest = Disabled;
|
type PropertyRequest = Disabled;
|
||||||
type ResourceType = Disabled;
|
type ResourceType = Disabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// 14.1. activelock XML Element
|
/// 14.1. activelock XML Element
|
||||||
///
|
///
|
||||||
|
|
Loading…
Reference in a new issue