// use quick_xml::events::BytesDecl; pub mod bind; pub mod iq; pub mod sasl; pub mod stream; use std::collections::BTreeMap; // const DECLARATION: BytesDecl<'_> = BytesDecl::new("1.0", None, None); use async_recursion::async_recursion; use quick_xml::events::{BytesStart, Event}; use quick_xml::{Reader, Writer}; use tokio::io::{AsyncBufRead, AsyncWrite}; use crate::JabberError; // #[derive(Clone, Debug)] // pub struct EventTree<'e> { // pub event: Event<'e>, // pub children: Option>>, // } pub type Prefix<'s> = Option<&'s str>; #[derive(Clone, Debug)] /// represents an xml element as a tree of nodes pub struct Element<'s> { /// element prefix /// e.g. `foo` in ``. prefix: Option<&'s str>, /// qualifying namespace /// an element must be qualified by a namespace /// e.g. for `` in /// ``` /// /// /// /// /// zlib /// lzw /// /// /// /// ``` /// would be `"http://etherx.jabber.org/streams"` but for /// ``` /// /// /// /// /// zlib /// lzw /// /// /// /// ``` /// would be `"jabber:client"` namespace: &'s str, /// element name /// e.g. `bar` in ``. name: &'s str, /// all namespaces applied to element /// e.g. for `` in /// ``` /// /// /// /// zlib /// lzw /// /// /// ``` /// would be `[(None, "urn:ietf:params:xml:ns:xmpp-bind")]` despite /// `(Some("stream"), "http://etherx.jabber.org/streams")` also being available namespaces: Box, &'s str>>, /// element attributes attributes: Box>, // children elements namespaces contain their parents' namespaces /// children: Option>>>, } #[derive(Clone, Debug)] pub enum Node<'s> { Element(Element<'s>), Text(&'s str), } impl<'s> From<&Element<'s>> for Event<'s> { fn from(element: &Element<'s>) -> Self { let event; if let Some(prefix) = element.prefix { event = BytesStart::new(format!("{}:{}", prefix, element.name)); } else { event = BytesStart::new(element.name); } event let event = event.with_attributes(element.attributes.into_iter()); match element.children.is_none() { true => return Event::Empty(event), false => return Event::Start(event), } } } impl<'s> Element<'s> { /// returns the namespace which applies to the current element, e.g. for /// `` /// it will be `http://etherx.jabber.org/streams` but for /// `` /// it will be `jabber:client`. pub fn get_namespace(&self) -> &str { self.namespace } } impl<'e: 'async_recursion, 'async_recursion> Element<'e> { pub fn write<'life0, W: AsyncWrite + Unpin + Send>( &'async_recursion self, writer: &'life0 mut Writer, ) -> ::core::pin::Pin< Box< dyn ::core::future::Future> + 'async_recursion + ::core::marker::Send, >, > where W: 'async_recursion, 'life0: 'async_recursion, { Box::pin(async move { match &self.children.is_empty() { true => {} } match &self.event { Event::Start(e) => { writer.write_event_async(Event::Start(e.clone())).await?; if let Some(children) = &self.children { for e in children { e.write(writer).await?; } } writer.write_event_async(Event::End(e.to_end())).await?; return Ok(()); } e => Ok(writer.write_event_async(e).await?), } }) } } impl<'e> Element<'e> { pub async fn write_start( &self, writer: &mut Writer, ) -> Result<(), JabberError> { match self.event.as_ref() { Event::Start(e) => Ok(writer.write_event_async(Event::Start(e.clone())).await?), e => Err(ElementError::NotAStart(e.clone().into_owned()).into()), } } pub async fn write_end( &self, writer: &mut Writer, ) -> Result<(), JabberError> { match self.event.as_ref() { Event::Start(e) => Ok(writer .write_event_async(Event::End(e.clone().to_end())) .await?), e => Err(ElementError::NotAStart(e.clone().into_owned()).into()), } } #[async_recursion] pub async fn read( reader: &mut Reader, ) -> Result { let element = Self::read_recursive(reader) .await? .ok_or(JabberError::UnexpectedEnd); element } #[async_recursion] async fn read_recursive( reader: &mut Reader, ) -> Result, JabberError> { let mut buf = Vec::new(); let event = reader.read_event_into_async(&mut buf).await?; match event { Event::Start(e) => { let mut children_vec = Vec::new(); while let Some(sub_element) = Element::read_recursive(reader).await? { children_vec.push(sub_element) } let mut children = None; if !children_vec.is_empty() { children = Some(children_vec) } Ok(Some(Self { event: Event::Start(e.into_owned()), children, })) } Event::End(_) => Ok(None), e => Ok(Some(Self { event: e.into_owned(), children: None, })), } } #[async_recursion] pub async fn read_start( reader: &mut Reader, ) -> Result { let mut buf = Vec::new(); let event = reader.read_event_into_async(&mut buf).await?; match event { Event::Start(e) => { return Ok(Self { event: Event::Start(e.into_owned()), children: None, }) } e => Err(ElementError::NotAStart(e.into_owned()).into()), } } /// if there is only one child in the vec of children, will return that element pub fn child<'p>(&'p self) -> Result<&'p Element<'e>, ElementError<'static>> { if let Some(children) = &self.children { if children.len() == 1 { return Ok(&children[0]); } else { return Err(ElementError::MultipleChildren); } } Err(ElementError::NoChildren) } /// returns reference to children pub fn children<'p>(&'p self) -> Result<&'p Vec>, ElementError<'e>> { if let Some(children) = &self.children { return Ok(children); } Err(ElementError::NoChildren) } } pub trait IntoElement<'e> { fn event(&self) -> Event<'e>; fn children(&self) -> Option>>; } impl<'e, T: IntoElement<'e>> From for Element<'e> { fn from(value: T) -> Self { Element { event: value.event(), children: value.children(), } } } #[derive(Debug)] pub enum ElementError<'e> { NotAStart(Event<'e>), NoChildren, MultipleChildren, }