diff options
Diffstat (limited to 'src/dav/xml.rs')
-rw-r--r-- | src/dav/xml.rs | 273 |
1 files changed, 0 insertions, 273 deletions
diff --git a/src/dav/xml.rs b/src/dav/xml.rs deleted file mode 100644 index 02263fd..0000000 --- a/src/dav/xml.rs +++ /dev/null @@ -1,273 +0,0 @@ -use tokio::io::{AsyncWrite, AsyncBufRead}; -use quick_xml::events::{Event, BytesEnd, BytesStart, BytesText}; -use quick_xml::name::{Namespace, QName, PrefixDeclaration, ResolveResult, ResolveResult::*}; -use quick_xml::reader::NsReader; - -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 { - 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<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>, - pub ns_to_apply: Vec<(String, String)>, -} -impl<T: IWrite> Writer<T> { - 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<T: IRead> { - pub rdr: NsReader<T>, - cur: Event<'static>, - parents: Vec<Event<'static>>, - buf: Vec<u8>, -} -impl<T: IRead> Reader<T> { - pub async fn new(mut rdr: NsReader<T>) -> Result<Self, ParsingError> { - let mut buf: Vec<u8> = 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<Event<'static>, 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<Event<'static>, 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<String, ParsingError> { - 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<N: Node<N>>(&mut self, t: &mut Option<N>, 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<N: Node<N>>(&mut self, t: &mut Vec<N>, 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<N: Node<N>>(&mut self) -> Result<N, ParsingError> { - 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<N: Node<N>>(&mut self) -> Result<Option<N>, 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<N: Node<N>>(&mut self) -> Result<Vec<N>, 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<Event<'static>, 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<Option<Event<'static>>, 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<Event<'static>, 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?, - }; - } - } -} - |