// 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<Vec<Element<'e>>>,
// }
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 `<foo:bar />`.
prefix: Option<&'s str>,
/// qualifying namespace
/// an element must be qualified by a namespace
/// e.g. for `<stream:features>` in
/// ```
/// <stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams'>
/// <stream:features>
/// <bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'/>
/// <compression xmlns='http://jabber.org/features/compress'>
/// <method>zlib</method>
/// <method>lzw</method>
/// </compression>
/// </stream:features>
/// </stream:stream>
/// ```
/// would be `"http://etherx.jabber.org/streams"` but for
/// ```
/// <stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams'>
/// <features>
/// <bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'/>
/// <compression xmlns='http://jabber.org/features/compress'>
/// <method>zlib</method>
/// <method>lzw</method>
/// </compression>
/// </features>
/// </stream:stream>
/// ```
/// would be `"jabber:client"`
namespace: &'s str,
/// element name
/// e.g. `bar` in `<foo:bar />`.
name: &'s str,
/// all namespaces applied to element
/// e.g. for `<bind>` in
/// ```
/// <stream:features xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams'>
/// <bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'/>
/// <compression xmlns='http://jabber.org/features/compress'>
/// <method>zlib</method>
/// <method>lzw</method>
/// </compression>
/// </stream:features>
/// ```
/// would be `[(None, "urn:ietf:params:xml:ns:xmpp-bind")]` despite
/// `(Some("stream"), "http://etherx.jabber.org/streams")` also being available
namespaces: Box<BTreeMap<Option<&'s str>, &'s str>>,
/// element attributes
attributes: Box<BTreeMap<&'s str, &'s str>>,
// children elements namespaces contain their parents' namespaces
///
children: Option<Box<Vec<Node<'s>>>>,
}
#[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
/// `<stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams'>`
/// it will be `http://etherx.jabber.org/streams` but for
/// `<stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams'>`
/// 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<W>,
) -> ::core::pin::Pin<
Box<
dyn ::core::future::Future<Output = Result<(), JabberError>>
+ '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<W: AsyncWrite + Unpin + Send>(
&self,
writer: &mut Writer<W>,
) -> 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<W: AsyncWrite + Unpin + Send>(
&self,
writer: &mut Writer<W>,
) -> 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<R: AsyncBufRead + Unpin + Send>(
reader: &mut Reader<R>,
) -> Result<Self, JabberError> {
let element = Self::read_recursive(reader)
.await?
.ok_or(JabberError::UnexpectedEnd);
element
}
#[async_recursion]
async fn read_recursive<R: AsyncBufRead + Unpin + Send>(
reader: &mut Reader<R>,
) -> Result<Option<Self>, 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<R: AsyncBufRead + Unpin + Send>(
reader: &mut Reader<R>,
) -> Result<Self, JabberError> {
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<Element<'e>>, 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<Vec<Element<'e>>>;
}
impl<'e, T: IntoElement<'e>> From<T> 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,
}