diff options
Diffstat (limited to '')
-rw-r--r-- | src/stanza/mod.rs | 120 | ||||
-rw-r--r-- | src/stanza/stream.rs | 3 |
2 files changed, 122 insertions, 1 deletions
diff --git a/src/stanza/mod.rs b/src/stanza/mod.rs index 02ea277..16f3bdd 100644 --- a/src/stanza/mod.rs +++ b/src/stanza/mod.rs @@ -4,3 +4,123 @@ pub mod sasl; pub mod stream; // const DECLARATION: BytesDecl<'_> = BytesDecl::new("1.0", None, None); +use async_recursion::async_recursion; +use quick_xml::events::Event; +use quick_xml::{Reader, Writer}; +use tokio::io::{AsyncBufRead, AsyncWrite}; + +use crate::Result; + +#[derive(Debug)] +pub struct Element<'e> { + pub event: Event<'e>, + pub content: Option<Vec<Element<'e>>>, +} + +impl<'e: 'async_recursion, 'async_recursion> Element<'e> { + pub fn write<'life0, W: AsyncWrite + Unpin + Send>( + &'async_recursion self, + writer: &'life0 mut Writer<W>, + ) -> ::core::pin::Pin< + Box< + dyn ::core::future::Future<Output = Result<()>> + + 'async_recursion + + ::core::marker::Send, + >, + > + where + W: 'async_recursion, + 'life0: 'async_recursion, + { + Box::pin(async move { + match &self.event { + Event::Start(e) => { + writer.write_event_async(Event::Start(e.clone())).await?; + if let Some(content) = &self.content { + for _e in content { + self.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<W: AsyncWrite + Unpin + Send>( + &self, + writer: &mut Writer<W>, + ) -> Result<()> { + 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<W: AsyncWrite + Unpin + Send>( + &self, + writer: &mut Writer<W>, + ) -> Result<()> { + 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<R: AsyncBufRead + Unpin + Send>( + reader: &mut Reader<R>, + ) -> Result<Option<Self>> { + let mut buf = Vec::new(); + let event = reader.read_event_into_async(&mut buf).await?; + match event { + Event::Start(e) => { + let mut content_vec = Vec::new(); + while let Some(sub_element) = Element::read(reader).await? { + content_vec.push(sub_element) + } + let mut content = None; + if !content_vec.is_empty() { + content = Some(content_vec) + } + Ok(Some(Self { + event: Event::Start(e.into_owned()), + content, + })) + } + Event::End(_) => Ok(None), + e => Ok(Some(Self { + event: e.into_owned(), + content: None, + })), + } + } + + #[async_recursion] + pub async fn read_start<R: AsyncBufRead + Unpin + Send>( + reader: &mut Reader<R>, + ) -> Result<Self> { + 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()), + content: None, + }) + } + e => Err(ElementError::NotAStart(e.into_owned()).into()), + } + } +} + +#[derive(Debug)] +pub enum ElementError<'e> { + NotAStart(Event<'e>), +} diff --git a/src/stanza/stream.rs b/src/stanza/stream.rs index f0fb6a1..59d0b90 100644 --- a/src/stanza/stream.rs +++ b/src/stanza/stream.rs @@ -5,7 +5,8 @@ use quick_xml::{ name::QName, }; -use crate::{element::Element, JabberError, Result, JID}; +use super::Element; +use crate::{JabberError, Result, JID}; const XMLNS_STREAM: &str = "http://etherx.jabber.org/streams"; const VERSION: &str = "1.0"; |