2023-07-11 21:28:42 +01:00
|
|
|
// use quick_xml::events::BytesDecl;
|
|
|
|
|
2023-08-02 00:56:38 +01:00
|
|
|
pub mod bind;
|
|
|
|
pub mod iq;
|
2023-07-04 21:27:15 +01:00
|
|
|
pub mod sasl;
|
2023-06-19 19:23:54 +01:00
|
|
|
pub mod stream;
|
2023-07-11 21:28:42 +01:00
|
|
|
|
2023-08-02 18:21:57 +01:00
|
|
|
use std::collections::BTreeMap;
|
|
|
|
|
2023-07-11 21:28:42 +01:00
|
|
|
// const DECLARATION: BytesDecl<'_> = BytesDecl::new("1.0", None, None);
|
2023-07-12 12:41:36 +01:00
|
|
|
use async_recursion::async_recursion;
|
2023-08-02 18:21:57 +01:00
|
|
|
use quick_xml::events::{BytesStart, Event};
|
2023-07-12 12:41:36 +01:00
|
|
|
use quick_xml::{Reader, Writer};
|
|
|
|
use tokio::io::{AsyncBufRead, AsyncWrite};
|
|
|
|
|
2023-07-12 21:11:20 +01:00
|
|
|
use crate::JabberError;
|
2023-07-12 12:41:36 +01:00
|
|
|
|
2023-08-02 18:21:57 +01:00
|
|
|
// #[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>>>>,
|
|
|
|
}
|
|
|
|
|
2023-07-12 21:11:20 +01:00
|
|
|
#[derive(Clone, Debug)]
|
2023-08-02 18:21:57 +01:00
|
|
|
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
|
|
|
|
}
|
2023-07-12 12:41:36 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
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<
|
2023-07-12 21:11:20 +01:00
|
|
|
dyn ::core::future::Future<Output = Result<(), JabberError>>
|
2023-07-12 12:41:36 +01:00
|
|
|
+ 'async_recursion
|
|
|
|
+ ::core::marker::Send,
|
|
|
|
>,
|
|
|
|
>
|
|
|
|
where
|
|
|
|
W: 'async_recursion,
|
|
|
|
'life0: 'async_recursion,
|
|
|
|
{
|
|
|
|
Box::pin(async move {
|
2023-08-02 18:21:57 +01:00
|
|
|
match &self.children.is_empty() {
|
|
|
|
true => {}
|
|
|
|
}
|
2023-07-12 12:41:36 +01:00
|
|
|
match &self.event {
|
|
|
|
Event::Start(e) => {
|
|
|
|
writer.write_event_async(Event::Start(e.clone())).await?;
|
2023-07-12 21:11:20 +01:00
|
|
|
if let Some(children) = &self.children {
|
|
|
|
for e in children {
|
|
|
|
e.write(writer).await?;
|
2023-07-12 12:41:36 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
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>,
|
2023-07-12 21:11:20 +01:00
|
|
|
) -> Result<(), JabberError> {
|
2023-07-12 12:41:36 +01:00
|
|
|
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>,
|
2023-07-12 21:11:20 +01:00
|
|
|
) -> Result<(), JabberError> {
|
2023-07-12 12:41:36 +01:00
|
|
|
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>,
|
2023-07-12 21:11:20 +01:00
|
|
|
) -> 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> {
|
2023-07-12 12:41:36 +01:00
|
|
|
let mut buf = Vec::new();
|
|
|
|
let event = reader.read_event_into_async(&mut buf).await?;
|
|
|
|
match event {
|
|
|
|
Event::Start(e) => {
|
2023-07-12 21:11:20 +01:00
|
|
|
let mut children_vec = Vec::new();
|
|
|
|
while let Some(sub_element) = Element::read_recursive(reader).await? {
|
|
|
|
children_vec.push(sub_element)
|
2023-07-12 12:41:36 +01:00
|
|
|
}
|
2023-07-12 21:11:20 +01:00
|
|
|
let mut children = None;
|
|
|
|
if !children_vec.is_empty() {
|
|
|
|
children = Some(children_vec)
|
2023-07-12 12:41:36 +01:00
|
|
|
}
|
|
|
|
Ok(Some(Self {
|
|
|
|
event: Event::Start(e.into_owned()),
|
2023-07-12 21:11:20 +01:00
|
|
|
children,
|
2023-07-12 12:41:36 +01:00
|
|
|
}))
|
|
|
|
}
|
|
|
|
Event::End(_) => Ok(None),
|
|
|
|
e => Ok(Some(Self {
|
|
|
|
event: e.into_owned(),
|
2023-07-12 21:11:20 +01:00
|
|
|
children: None,
|
2023-07-12 12:41:36 +01:00
|
|
|
})),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[async_recursion]
|
|
|
|
pub async fn read_start<R: AsyncBufRead + Unpin + Send>(
|
|
|
|
reader: &mut Reader<R>,
|
2023-07-12 21:11:20 +01:00
|
|
|
) -> Result<Self, JabberError> {
|
2023-07-12 12:41:36 +01:00
|
|
|
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()),
|
2023-07-12 21:11:20 +01:00
|
|
|
children: None,
|
2023-07-12 12:41:36 +01:00
|
|
|
})
|
|
|
|
}
|
|
|
|
e => Err(ElementError::NotAStart(e.into_owned()).into()),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-08-02 00:56:38 +01:00
|
|
|
/// 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);
|
2023-07-12 21:11:20 +01:00
|
|
|
}
|
2023-08-02 00:56:38 +01:00
|
|
|
Err(ElementError::NoChildren)
|
2023-07-12 21:11:20 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-08-02 00:56:38 +01:00
|
|
|
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(),
|
|
|
|
}
|
2023-07-12 21:11:20 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-07-12 12:41:36 +01:00
|
|
|
#[derive(Debug)]
|
|
|
|
pub enum ElementError<'e> {
|
|
|
|
NotAStart(Event<'e>),
|
2023-07-12 21:11:20 +01:00
|
|
|
NoChildren,
|
|
|
|
MultipleChildren,
|
2023-07-12 12:41:36 +01:00
|
|
|
}
|