From 1a43ce5ac7033c148f64a033f2b1d335e95e11d5 Mon Sep 17 00:00:00 2001 From: Quentin Dufour Date: Fri, 8 Mar 2024 08:17:03 +0100 Subject: WIP refactor --- aero-dav/src/xml.rs | 274 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 274 insertions(+) create mode 100644 aero-dav/src/xml.rs (limited to 'aero-dav/src/xml.rs') diff --git a/aero-dav/src/xml.rs b/aero-dav/src/xml.rs new file mode 100644 index 0000000..98037ac --- /dev/null +++ b/aero-dav/src/xml.rs @@ -0,0 +1,274 @@ +use futures::Future; +use quick_xml::events::{Event, BytesStart}; +use quick_xml::name::ResolveResult; +use quick_xml::reader::NsReader; +use tokio::io::{AsyncWrite, AsyncBufRead}; + +use super::error::ParsingError; + +// Constants +pub const DAV_URN: &[u8] = b"DAV:"; +pub const CAL_URN: &[u8] = b"urn:ietf:params:xml:ns:caldav"; +pub const CARD_URN: &[u8] = b"urn:ietf:params:xml:ns:carddav"; + +// Async traits +pub trait IWrite = AsyncWrite + Unpin; +pub trait IRead = AsyncBufRead + Unpin; + +// Serialization/Deserialization traits +pub trait QWrite { + fn qwrite(&self, xml: &mut Writer) -> impl Future>; +} +pub trait QRead { + fn qread(xml: &mut Reader) -> impl Future>; +} + +// The representation of an XML node in Rust +pub trait Node = QRead + QWrite + std::fmt::Debug + PartialEq; + +// --------------- + +/// Transform a Rust object into an XML stream of characters +pub struct Writer { + pub q: quick_xml::writer::Writer, + pub ns_to_apply: Vec<(String, String)>, +} +impl Writer { + pub fn create_dav_element(&mut self, name: &str) -> BytesStart<'static> { + self.create_ns_element("D", name) + } + pub fn create_cal_element(&mut self, name: &str) -> BytesStart<'static> { + self.create_ns_element("C", name) + } + + fn create_ns_element(&mut self, ns: &str, name: &str) -> BytesStart<'static> { + let mut start = BytesStart::new(format!("{}:{}", ns, name)); + if !self.ns_to_apply.is_empty() { + start.extend_attributes(self.ns_to_apply.iter().map(|(k, n)| (k.as_str(), n.as_str()))); + self.ns_to_apply.clear() + } + start + } +} + +/// Transform an XML stream of characters into a Rust object +pub struct Reader { + pub rdr: NsReader, + cur: Event<'static>, + parents: Vec>, + buf: Vec, +} +impl Reader { + pub async fn new(mut rdr: NsReader) -> Result { + let mut buf: Vec = vec![]; + let cur = rdr.read_event_into_async(&mut buf).await?.into_owned(); + let parents = vec![]; + buf.clear(); + Ok(Self { cur, parents, rdr, buf }) + } + + /// read one more tag + /// do not expose it publicly + async fn next(&mut self) -> Result, ParsingError> { + let evt = self.rdr.read_event_into_async(&mut self.buf).await?.into_owned(); + self.buf.clear(); + let old_evt = std::mem::replace(&mut self.cur, evt); + Ok(old_evt) + } + + /// skip a node at current level + /// I would like to make this one private but not ready + pub async fn skip(&mut self) -> Result, ParsingError> { + //println!("skipping inside node {:?}", self.parents.last()); + match &self.cur { + Event::Start(b) => { + let _span = self.rdr.read_to_end_into_async(b.to_end().name(), &mut self.buf).await?; + self.next().await + }, + Event::End(_) => Err(ParsingError::WrongToken), + Event::Eof => Err(ParsingError::Eof), + _ => self.next().await, + } + } + + /// check if this is the desired tag + fn is_tag(&self, ns: &[u8], key: &str) -> bool { + let qname = match self.peek() { + Event::Start(bs) | Event::Empty(bs) => bs.name(), + Event::End(be) => be.name(), + _ => return false, + }; + + let (extr_ns, local) = self.rdr.resolve_element(qname); + + if local.into_inner() != key.as_bytes() { + return false + } + + match extr_ns { + ResolveResult::Bound(v) => v.into_inner() == ns, + _ => false, + } + } + + fn parent_has_child(&self) -> bool { + matches!(self.parents.last(), Some(Event::Start(_)) | None) + } + + fn ensure_parent_has_child(&self) -> Result<(), ParsingError> { + match self.parent_has_child() { + true => Ok(()), + false => Err(ParsingError::Recoverable), + } + } + + pub fn peek(&self) -> &Event<'static> { + &self.cur + } + + // NEW API + pub async fn tag_string(&mut self) -> Result { + self.ensure_parent_has_child()?; + + let mut acc = String::new(); + loop { + match self.peek() { + Event::CData(unescaped) => { + acc.push_str(std::str::from_utf8(unescaped.as_ref())?); + self.next().await? + }, + Event::Text(escaped) => { + acc.push_str(escaped.unescape()?.as_ref()); + self.next().await? + } + Event::End(_) | Event::Start(_) | Event::Empty(_) => return Ok(acc), + _ => self.next().await?, + }; + } + } + + pub async fn maybe_read>(&mut self, t: &mut Option, dirty: &mut bool) -> Result<(), ParsingError> { + if !self.parent_has_child() { + return Ok(()) + } + + 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>(&mut self, t: &mut Vec, dirty: &mut bool) -> Result<(), ParsingError> { + if !self.parent_has_child() { + return Ok(()) + } + + 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>(&mut self) -> Result { + self.ensure_parent_has_child()?; + + 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>(&mut self) -> Result, ParsingError> { + self.ensure_parent_has_child()?; + + 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>(&mut self) -> Result, ParsingError> { + self.ensure_parent_has_child()?; + 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, ParsingError> { + let evt = match self.peek() { + Event::Empty(_) if self.is_tag(ns, key) => self.cur.clone(), + Event::Start(_) if self.is_tag(ns, key) => self.next().await?, + _ => return Err(ParsingError::Recoverable), + }; + + //println!("open tag {:?}", evt); + self.parents.push(evt.clone()); + Ok(evt) + } + + pub async fn maybe_open(&mut self, ns: &[u8], key: &str) -> Result>, ParsingError> { + match self.open(ns, key).await { + Ok(v) => Ok(Some(v)), + Err(ParsingError::Recoverable) => Ok(None), + Err(e) => Err(e), + } + } + + // find stop tag + pub async fn close(&mut self) -> Result, ParsingError> { + //println!("close tag {:?}", self.parents.last()); + + // Handle the empty case + if !self.parent_has_child() { + self.parents.pop(); + return self.next().await + } + + // Handle the start/end case + loop { + match self.peek() { + Event::End(_) => { + self.parents.pop(); + return self.next().await + }, + _ => self.skip().await?, + }; + } + } +} + -- cgit v1.2.3 From 4d65366ff368cc9ea35115cb7e701bfebb166bc6 Mon Sep 17 00:00:00 2001 From: Quentin Dufour Date: Fri, 8 Mar 2024 11:34:24 +0100 Subject: Fixed some parsing bugs --- aero-dav/src/xml.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'aero-dav/src/xml.rs') diff --git a/aero-dav/src/xml.rs b/aero-dav/src/xml.rs index 98037ac..f9e04eb 100644 --- a/aero-dav/src/xml.rs +++ b/aero-dav/src/xml.rs @@ -79,7 +79,7 @@ impl Reader { /// skip a node at current level /// I would like to make this one private but not ready pub async fn skip(&mut self) -> Result, ParsingError> { - //println!("skipping inside node {:?}", self.parents.last()); + //println!("skipping inside node {:?} value {:?}", self.parents.last(), self.cur); match &self.cur { Event::Start(b) => { let _span = self.rdr.read_to_end_into_async(b.to_end().name(), &mut self.buf).await?; @@ -212,8 +212,10 @@ impl Reader { } pub async fn collect>(&mut self) -> Result, ParsingError> { - self.ensure_parent_has_child()?; let mut acc = Vec::new(); + if !self.parent_has_child() { + return Ok(acc) + } loop { match N::qread(self).await { @@ -230,6 +232,7 @@ impl Reader { } pub async fn open(&mut self, ns: &[u8], key: &str) -> Result, ParsingError> { + //println!("try open tag {:?}", key); let evt = match self.peek() { Event::Empty(_) if self.is_tag(ns, key) => self.cur.clone(), Event::Start(_) if self.is_tag(ns, key) => self.next().await?, -- cgit v1.2.3 From 7459f50b5486a137bc90b7e6e04e915d82230e28 Mon Sep 17 00:00:00 2001 From: Quentin Dufour Date: Fri, 8 Mar 2024 18:23:23 +0100 Subject: WIP implem cal decoder --- aero-dav/src/xml.rs | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) (limited to 'aero-dav/src/xml.rs') diff --git a/aero-dav/src/xml.rs b/aero-dav/src/xml.rs index f9e04eb..e021543 100644 --- a/aero-dav/src/xml.rs +++ b/aero-dav/src/xml.rs @@ -55,6 +55,7 @@ impl Writer { pub struct Reader { pub rdr: NsReader, cur: Event<'static>, + prev: Event<'static>, parents: Vec>, buf: Vec, } @@ -63,8 +64,9 @@ impl Reader { let mut buf: Vec = vec![]; let cur = rdr.read_event_into_async(&mut buf).await?.into_owned(); let parents = vec![]; + let prev = Event::Eof; buf.clear(); - Ok(Self { cur, parents, rdr, buf }) + Ok(Self { cur, prev, parents, rdr, buf }) } /// read one more tag @@ -72,8 +74,8 @@ impl Reader { async fn next(&mut self) -> Result, ParsingError> { let evt = self.rdr.read_event_into_async(&mut self.buf).await?.into_owned(); self.buf.clear(); - let old_evt = std::mem::replace(&mut self.cur, evt); - Ok(old_evt) + self.prev = std::mem::replace(&mut self.cur, evt); + Ok(self.prev.clone()) } /// skip a node at current level @@ -252,6 +254,16 @@ impl Reader { } } + pub fn prev_attr(&self, attr: &str) -> Option { + match &self.prev { + Event::Start(bs) | Event::Empty(bs) => match bs.try_get_attribute(attr) { + Ok(Some(attr)) => attr.decode_and_unescape_value(&self.rdr).ok().map(|v| v.into_owned()), + _ => None, + } + _ => None, + } + } + // find stop tag pub async fn close(&mut self) -> Result, ParsingError> { //println!("close tag {:?}", self.parents.last()); -- cgit v1.2.3 From 6d1f538091ca9445cdc0d72b051fa5090b6ec68a Mon Sep 17 00:00:00 2001 From: Quentin Dufour Date: Fri, 8 Mar 2024 22:03:46 +0100 Subject: Improve my XML parser --- aero-dav/src/xml.rs | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'aero-dav/src/xml.rs') diff --git a/aero-dav/src/xml.rs b/aero-dav/src/xml.rs index e021543..347a123 100644 --- a/aero-dav/src/xml.rs +++ b/aero-dav/src/xml.rs @@ -236,12 +236,20 @@ impl Reader { pub async fn open(&mut self, ns: &[u8], key: &str) -> Result, ParsingError> { //println!("try open tag {:?}", key); let evt = match self.peek() { - Event::Empty(_) if self.is_tag(ns, key) => self.cur.clone(), + Event::Empty(_) if self.is_tag(ns, key) => { + // hack to make `prev_attr` works + // here we duplicate the current tag + // as in other words, we virtually moved one token + // which is useful for prev_attr and any logic based on + // self.prev + self.open() on empty nodes + self.prev = self.cur.clone(); + self.cur.clone() + }, Event::Start(_) if self.is_tag(ns, key) => self.next().await?, _ => return Err(ParsingError::Recoverable), }; - //println!("open tag {:?}", evt); + println!("open tag {:?}", evt); self.parents.push(evt.clone()); Ok(evt) } @@ -266,7 +274,7 @@ impl Reader { // find stop tag pub async fn close(&mut self) -> Result, ParsingError> { - //println!("close tag {:?}", self.parents.last()); + println!("close tag {:?}", self.parents.last()); // Handle the empty case if !self.parent_has_child() { -- cgit v1.2.3 From 442433d70bf13b1641ec76077d9955f5d63ee965 Mon Sep 17 00:00:00 2001 From: Quentin Dufour Date: Tue, 12 Mar 2024 10:18:13 +0100 Subject: fix parsing --- aero-dav/src/xml.rs | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'aero-dav/src/xml.rs') diff --git a/aero-dav/src/xml.rs b/aero-dav/src/xml.rs index 347a123..2f3b7a6 100644 --- a/aero-dav/src/xml.rs +++ b/aero-dav/src/xml.rs @@ -128,6 +128,10 @@ impl Reader { &self.cur } + pub fn previous(&self) -> &Event<'static> { + &self.prev + } + // NEW API pub async fn tag_string(&mut self) -> Result { self.ensure_parent_has_child()?; -- cgit v1.2.3 From 98adb1e20d90a1538b474659a96450d4c7b264c5 Mon Sep 17 00:00:00 2001 From: Quentin Dufour Date: Wed, 13 Mar 2024 09:11:52 +0100 Subject: fix caldecoder + xml --- aero-dav/src/xml.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'aero-dav/src/xml.rs') diff --git a/aero-dav/src/xml.rs b/aero-dav/src/xml.rs index 2f3b7a6..1f8a6b1 100644 --- a/aero-dav/src/xml.rs +++ b/aero-dav/src/xml.rs @@ -113,7 +113,7 @@ impl Reader { } } - fn parent_has_child(&self) -> bool { + pub fn parent_has_child(&self) -> bool { matches!(self.parents.last(), Some(Event::Start(_)) | None) } @@ -238,7 +238,7 @@ impl Reader { } pub async fn open(&mut self, ns: &[u8], key: &str) -> Result, ParsingError> { - //println!("try open tag {:?}", key); + //println!("try open tag {:?}, on {:?}", key, self.peek()); let evt = match self.peek() { Event::Empty(_) if self.is_tag(ns, key) => { // hack to make `prev_attr` works @@ -253,7 +253,7 @@ impl Reader { _ => return Err(ParsingError::Recoverable), }; - println!("open tag {:?}", evt); + //println!("open tag {:?}", evt); self.parents.push(evt.clone()); Ok(evt) } @@ -278,7 +278,7 @@ impl Reader { // find stop tag pub async fn close(&mut self) -> Result, ParsingError> { - println!("close tag {:?}", self.parents.last()); + //println!("close tag {:?}", self.parents.last()); // Handle the empty case if !self.parent_has_child() { -- cgit v1.2.3 From 902d33c4344f4e38c021ff20b2197ee1dfbd347f Mon Sep 17 00:00:00 2001 From: Quentin Dufour Date: Sat, 16 Mar 2024 16:48:46 +0100 Subject: bind streaming codec to hyper 1.x --- aero-dav/src/xml.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'aero-dav/src/xml.rs') diff --git a/aero-dav/src/xml.rs b/aero-dav/src/xml.rs index 1f8a6b1..e078c6f 100644 --- a/aero-dav/src/xml.rs +++ b/aero-dav/src/xml.rs @@ -12,19 +12,19 @@ pub const CAL_URN: &[u8] = b"urn:ietf:params:xml:ns:caldav"; pub const CARD_URN: &[u8] = b"urn:ietf:params:xml:ns:carddav"; // Async traits -pub trait IWrite = AsyncWrite + Unpin; +pub trait IWrite = AsyncWrite + Unpin + Send; pub trait IRead = AsyncBufRead + Unpin; // Serialization/Deserialization traits pub trait QWrite { - fn qwrite(&self, xml: &mut Writer) -> impl Future>; + fn qwrite(&self, xml: &mut Writer) -> impl Future> + Send; } pub trait QRead { fn qread(xml: &mut Reader) -> impl Future>; } // The representation of an XML node in Rust -pub trait Node = QRead + QWrite + std::fmt::Debug + PartialEq; +pub trait Node = QRead + QWrite + std::fmt::Debug + PartialEq + Sync; // --------------- -- cgit v1.2.3 From f372a95b017587bd964ef80fdfdef7c2128bca15 Mon Sep 17 00:00:00 2001 From: Quentin Dufour Date: Sun, 17 Mar 2024 10:31:05 +0100 Subject: basic propfind --- aero-dav/src/xml.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'aero-dav/src/xml.rs') diff --git a/aero-dav/src/xml.rs b/aero-dav/src/xml.rs index e078c6f..827e9d0 100644 --- a/aero-dav/src/xml.rs +++ b/aero-dav/src/xml.rs @@ -24,7 +24,7 @@ pub trait QRead { } // The representation of an XML node in Rust -pub trait Node = QRead + QWrite + std::fmt::Debug + PartialEq + Sync; +pub trait Node = QRead + QWrite + std::fmt::Debug + PartialEq + Clone + Sync; // --------------- -- cgit v1.2.3 From d0c47b93fe19a9ebc35d624b9dbed7d1d539ecaa Mon Sep 17 00:00:00 2001 From: Quentin Dufour Date: Mon, 18 Mar 2024 20:45:30 +0100 Subject: Rework webdav types --- aero-dav/src/xml.rs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'aero-dav/src/xml.rs') diff --git a/aero-dav/src/xml.rs b/aero-dav/src/xml.rs index 827e9d0..26f54cc 100644 --- a/aero-dav/src/xml.rs +++ b/aero-dav/src/xml.rs @@ -258,6 +258,17 @@ impl Reader { Ok(evt) } + pub async fn open_start(&mut self, ns: &[u8], key: &str) -> Result, ParsingError> { + let evt = match self.peek() { + Event::Start(_) if self.is_tag(ns, key) => self.next().await?, + _ => return Err(ParsingError::Recoverable), + }; + + //println!("open tag {:?}", evt); + self.parents.push(evt.clone()); + Ok(evt) + } + pub async fn maybe_open(&mut self, ns: &[u8], key: &str) -> Result>, ParsingError> { match self.open(ns, key).await { Ok(v) => Ok(Some(v)), @@ -266,6 +277,14 @@ impl Reader { } } + pub async fn maybe_open_start(&mut self, ns: &[u8], key: &str) -> Result>, ParsingError> { + match self.open_start(ns, key).await { + Ok(v) => Ok(Some(v)), + Err(ParsingError::Recoverable) => Ok(None), + Err(e) => Err(e), + } + } + pub fn prev_attr(&self, attr: &str) -> Option { match &self.prev { Event::Start(bs) | Event::Empty(bs) => match bs.try_get_attribute(attr) { -- cgit v1.2.3 From fb6a379f43ff579dbc224fb52180ba3a6d6cde5c Mon Sep 17 00:00:00 2001 From: Quentin Dufour Date: Tue, 19 Mar 2024 17:36:32 +0100 Subject: Working thunderbird autodetect --- aero-dav/src/xml.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'aero-dav/src/xml.rs') diff --git a/aero-dav/src/xml.rs b/aero-dav/src/xml.rs index 26f54cc..020ee6c 100644 --- a/aero-dav/src/xml.rs +++ b/aero-dav/src/xml.rs @@ -264,7 +264,7 @@ impl Reader { _ => return Err(ParsingError::Recoverable), }; - //println!("open tag {:?}", evt); + //println!("open start tag {:?}", evt); self.parents.push(evt.clone()); Ok(evt) } -- cgit v1.2.3 From 22e4f295556fdd4c25cf43983a56ff74acab7739 Mon Sep 17 00:00:00 2001 From: Quentin Dufour Date: Wed, 20 Mar 2024 14:46:07 +0100 Subject: working report calendar-multiget --- aero-dav/src/xml.rs | 1 + 1 file changed, 1 insertion(+) (limited to 'aero-dav/src/xml.rs') diff --git a/aero-dav/src/xml.rs b/aero-dav/src/xml.rs index 020ee6c..d57093e 100644 --- a/aero-dav/src/xml.rs +++ b/aero-dav/src/xml.rs @@ -259,6 +259,7 @@ impl Reader { } pub async fn open_start(&mut self, ns: &[u8], key: &str) -> Result, ParsingError> { + //println!("try open start tag {:?}, on {:?}", key, self.peek()); let evt = match self.peek() { Event::Start(_) if self.is_tag(ns, key) => self.next().await?, _ => return Err(ParsingError::Recoverable), -- cgit v1.2.3 From 32dfd25f570b7a55bf43752684d286be0f6b2dc2 Mon Sep 17 00:00:00 2001 From: Quentin Dufour Date: Thu, 16 May 2024 17:38:34 +0200 Subject: format + WIP calendar-query --- aero-dav/src/xml.rs | 124 +++++++++++++++++++++++++++++++++++----------------- 1 file changed, 83 insertions(+), 41 deletions(-) (limited to 'aero-dav/src/xml.rs') diff --git a/aero-dav/src/xml.rs b/aero-dav/src/xml.rs index d57093e..c89f531 100644 --- a/aero-dav/src/xml.rs +++ b/aero-dav/src/xml.rs @@ -1,8 +1,8 @@ use futures::Future; -use quick_xml::events::{Event, BytesStart}; +use quick_xml::events::{BytesStart, Event}; use quick_xml::name::ResolveResult; use quick_xml::reader::NsReader; -use tokio::io::{AsyncWrite, AsyncBufRead}; +use tokio::io::{AsyncBufRead, AsyncWrite}; use super::error::ParsingError; @@ -17,7 +17,10 @@ pub trait IRead = AsyncBufRead + Unpin; // Serialization/Deserialization traits pub trait QWrite { - fn qwrite(&self, xml: &mut Writer) -> impl Future> + Send; + fn qwrite( + &self, + xml: &mut Writer, + ) -> impl Future> + Send; } pub trait QRead { fn qread(xml: &mut Reader) -> impl Future>; @@ -44,7 +47,11 @@ impl Writer { fn create_ns_element(&mut self, ns: &str, name: &str) -> BytesStart<'static> { let mut start = BytesStart::new(format!("{}:{}", ns, name)); if !self.ns_to_apply.is_empty() { - start.extend_attributes(self.ns_to_apply.iter().map(|(k, n)| (k.as_str(), n.as_str()))); + start.extend_attributes( + self.ns_to_apply + .iter() + .map(|(k, n)| (k.as_str(), n.as_str())), + ); self.ns_to_apply.clear() } start @@ -66,16 +73,26 @@ impl Reader { let parents = vec![]; let prev = Event::Eof; buf.clear(); - Ok(Self { cur, prev, parents, rdr, buf }) + Ok(Self { + cur, + prev, + parents, + rdr, + buf, + }) } /// read one more tag /// do not expose it publicly async fn next(&mut self) -> Result, ParsingError> { - let evt = self.rdr.read_event_into_async(&mut self.buf).await?.into_owned(); - self.buf.clear(); - self.prev = std::mem::replace(&mut self.cur, evt); - Ok(self.prev.clone()) + let evt = self + .rdr + .read_event_into_async(&mut self.buf) + .await? + .into_owned(); + self.buf.clear(); + self.prev = std::mem::replace(&mut self.cur, evt); + Ok(self.prev.clone()) } /// skip a node at current level @@ -84,9 +101,12 @@ impl Reader { //println!("skipping inside node {:?} value {:?}", self.parents.last(), self.cur); match &self.cur { Event::Start(b) => { - let _span = self.rdr.read_to_end_into_async(b.to_end().name(), &mut self.buf).await?; + let _span = self + .rdr + .read_to_end_into_async(b.to_end().name(), &mut self.buf) + .await?; self.next().await - }, + } Event::End(_) => Err(ParsingError::WrongToken), Event::Eof => Err(ParsingError::Eof), _ => self.next().await, @@ -100,13 +120,13 @@ impl Reader { Event::End(be) => be.name(), _ => return false, }; - + let (extr_ns, local) = self.rdr.resolve_element(qname); if local.into_inner() != key.as_bytes() { - return false + return false; } - + match extr_ns { ResolveResult::Bound(v) => v.into_inner() == ns, _ => false, @@ -142,7 +162,7 @@ impl Reader { Event::CData(unescaped) => { acc.push_str(std::str::from_utf8(unescaped.as_ref())?); self.next().await? - }, + } Event::Text(escaped) => { acc.push_str(escaped.unescape()?.as_ref()); self.next().await? @@ -153,33 +173,41 @@ impl Reader { } } - pub async fn maybe_read>(&mut self, t: &mut Option, dirty: &mut bool) -> Result<(), ParsingError> { + pub async fn maybe_read>( + &mut self, + t: &mut Option, + dirty: &mut bool, + ) -> Result<(), ParsingError> { if !self.parent_has_child() { - return Ok(()) + return Ok(()); } match N::qread(self).await { - Ok(v) => { - *t = Some(v); + Ok(v) => { + *t = Some(v); *dirty = true; - Ok(()) - }, + Ok(()) + } Err(ParsingError::Recoverable) => Ok(()), Err(e) => Err(e), } } - pub async fn maybe_push>(&mut self, t: &mut Vec, dirty: &mut bool) -> Result<(), ParsingError> { + pub async fn maybe_push>( + &mut self, + t: &mut Vec, + dirty: &mut bool, + ) -> Result<(), ParsingError> { if !self.parent_has_child() { - return Ok(()) + return Ok(()); } match N::qread(self).await { - Ok(v) => { - t.push(v); + Ok(v) => { + t.push(v); *dirty = true; - Ok(()) - }, + Ok(()) + } Err(ParsingError::Recoverable) => Ok(()), Err(e) => Err(e), } @@ -220,7 +248,7 @@ impl Reader { pub async fn collect>(&mut self) -> Result, ParsingError> { let mut acc = Vec::new(); if !self.parent_has_child() { - return Ok(acc) + return Ok(acc); } loop { @@ -229,7 +257,7 @@ impl Reader { Event::End(_) => return Ok(acc), _ => { self.skip().await?; - }, + } }, Ok(v) => acc.push(v), Err(e) => return Err(e), @@ -242,13 +270,13 @@ impl Reader { let evt = match self.peek() { Event::Empty(_) if self.is_tag(ns, key) => { // hack to make `prev_attr` works - // here we duplicate the current tag - // as in other words, we virtually moved one token + // here we duplicate the current tag + // as in other words, we virtually moved one token // which is useful for prev_attr and any logic based on // self.prev + self.open() on empty nodes self.prev = self.cur.clone(); self.cur.clone() - }, + } Event::Start(_) if self.is_tag(ns, key) => self.next().await?, _ => return Err(ParsingError::Recoverable), }; @@ -258,7 +286,11 @@ impl Reader { Ok(evt) } - pub async fn open_start(&mut self, ns: &[u8], key: &str) -> Result, ParsingError> { + pub async fn open_start( + &mut self, + ns: &[u8], + key: &str, + ) -> Result, ParsingError> { //println!("try open start tag {:?}, on {:?}", key, self.peek()); let evt = match self.peek() { Event::Start(_) if self.is_tag(ns, key) => self.next().await?, @@ -270,7 +302,11 @@ impl Reader { Ok(evt) } - pub async fn maybe_open(&mut self, ns: &[u8], key: &str) -> Result>, ParsingError> { + pub async fn maybe_open( + &mut self, + ns: &[u8], + key: &str, + ) -> Result>, ParsingError> { match self.open(ns, key).await { Ok(v) => Ok(Some(v)), Err(ParsingError::Recoverable) => Ok(None), @@ -278,7 +314,11 @@ impl Reader { } } - pub async fn maybe_open_start(&mut self, ns: &[u8], key: &str) -> Result>, ParsingError> { + pub async fn maybe_open_start( + &mut self, + ns: &[u8], + key: &str, + ) -> Result>, ParsingError> { match self.open_start(ns, key).await { Ok(v) => Ok(Some(v)), Err(ParsingError::Recoverable) => Ok(None), @@ -289,9 +329,12 @@ impl Reader { pub fn prev_attr(&self, attr: &str) -> Option { match &self.prev { Event::Start(bs) | Event::Empty(bs) => match bs.try_get_attribute(attr) { - Ok(Some(attr)) => attr.decode_and_unescape_value(&self.rdr).ok().map(|v| v.into_owned()), + Ok(Some(attr)) => attr + .decode_and_unescape_value(&self.rdr) + .ok() + .map(|v| v.into_owned()), _ => None, - } + }, _ => None, } } @@ -303,7 +346,7 @@ impl Reader { // Handle the empty case if !self.parent_has_child() { self.parents.pop(); - return self.next().await + return self.next().await; } // Handle the start/end case @@ -311,11 +354,10 @@ impl Reader { match self.peek() { Event::End(_) => { self.parents.pop(); - return self.next().await - }, + return self.next().await; + } _ => self.skip().await?, }; } } } - -- cgit v1.2.3 From a859fe38b1044c576f042254a0f9677054b417a0 Mon Sep 17 00:00:00 2001 From: Quentin Dufour Date: Thu, 23 May 2024 08:55:53 +0200 Subject: test calendar-query vevent filtering --- aero-dav/src/xml.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'aero-dav/src/xml.rs') diff --git a/aero-dav/src/xml.rs b/aero-dav/src/xml.rs index c89f531..e59f136 100644 --- a/aero-dav/src/xml.rs +++ b/aero-dav/src/xml.rs @@ -229,7 +229,10 @@ impl Reader { } pub async fn maybe_find>(&mut self) -> Result, ParsingError> { - self.ensure_parent_has_child()?; + // We can't find anything inside a self-closed tag + if !self.parent_has_child() { + return Ok(None); + } loop { // Try parse @@ -238,6 +241,7 @@ impl Reader { otherwise => return otherwise.map(Some), } + // Skip or stop match self.peek() { Event::End(_) => return Ok(None), _ => self.skip().await?, -- cgit v1.2.3