// use quick_xml::events::BytesDecl;
pub mod bind;
pub mod iq;
pub mod sasl;
pub mod stream;
use std::collections::BTreeMap;
use std::str;
// const DECLARATION: BytesDecl<'_> = BytesDecl::new("1.0", None, None);
use async_recursion::async_recursion;
use quick_xml::events::{BytesEnd, BytesStart, BytesText, Event};
use quick_xml::name::PrefixDeclaration;
use quick_xml::{Reader, Writer};
use tokio::io::{AsyncBufRead, AsyncWrite};
use crate::{JabberError, Result};
#[derive(Clone, Debug)]
/// represents an xml element as a tree of nodes
pub struct Element {
/// element prefix
/// e.g. `foo` in ``.
prefix: Option,
/// element name
/// e.g. `bar` in ``.
localname: String,
/// 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: String,
/// 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
// TODO: maybe not even needed, as can calculate when writing which namespaces need to be declared
// but then can't have unused namespace on element, confusing.
namespace_declarations: Box, String>>,
/// element attributes
attributes: Box>,
// children elements namespaces contain their parents' namespaces
children: Box>,
}
#[derive(Clone, Debug)]
pub enum Node {
Element(Element),
Text(String),
Unknown,
}
impl From for Node {
fn from(element: Element) -> Self {
Self::Element(element)
}
}
impl From for Node {
fn from(text: S) -> Self {
Self::Text(text.to_string())
}
}
impl<'s> From<&Node> for Vec> {
fn from(node: &Node) -> Self {
match node {
Node::Element(e) => e.into(),
Node::Text(t) => vec![Event::Text(BytesText::new(t))],
Unknown => vec![],
}
}
}
impl Element {
/// returns the fully qualified name
/// e.g. `foo:bar` in
/// ``.
pub fn name(&self) -> &str {
if let Some(prefix) = self.prefix {
format!("{}:{}", prefix, self.localname).as_str()
} else {
&self.localname
}
}
/// returns the localname.
/// e.g. `bar` in ``
pub fn localname(&self) -> &str {
&self.localname
}
/// returns the prefix.
/// e.g. `foo` in ``. returns None if there is
/// no prefix.
pub fn prefix(&self) -> Option<&str> {
self.prefix
}
/// returns the namespace which applies to the current element, e.g. for
/// ``
/// it will be `foo` but for
/// ``
/// it will be `bar`.
pub fn namespace(&self) -> &str {
&self.namespace
}
}
impl<'s> From<&Element> for Vec> {
fn from(element: &Element) -> Self {
let name = element.name();
let event = BytesStart::new(name);
// namespace declarations
let namespace_declarations = element.namespace_declarations.iter().map(|declaration| {
let (prefix, namespace) = declaration;
match prefix {
Some(prefix) => return (format!("xmlns:{}", prefix).as_str(), *namespace),
None => return ("xmlns", *namespace),
}
});
let event = event.with_attributes(namespace_declarations);
// attributes
let event = event.with_attributes(element.attributes.into_iter());
match element.children.is_empty() {
true => return vec![Event::Empty(event)],
false => {
return {
let start: Vec> = vec![Event::Start(event)];
let start_and_content: Vec> = start
.into_iter()
.chain({
let u = element.children.iter().fold(
Vec::new(),
|acc: Vec>, child: &Node<'s>| {
acc.into_iter()
.chain(Into::>>::into(child).into_iter())
.collect()
},
);
u
})
.collect();
let full: Vec> = start_and_content
.into_iter()
.chain(vec![Event::End(BytesEnd::new(name))])
.collect();
full
}
}
}
}
}
impl Element {
/// if there is only one child in the vec of children, will return that element
pub fn child(&self) -> Result<&Node> {
if self.children.len() == 1 {
Ok(&self.children[0])
} else if self.children.len() > 1 {
Err(ElementError::MultipleChildren.into())
} else {
Err(ElementError::NoChildren.into())
}
}
/// returns reference to children
pub fn children(&self) -> Result<&Vec> {
if !self.children.is_empty() {
Ok(&self.children)
} else {
Err(ElementError::NoChildren.into())
}
}
/// returns text content, error if there is none
pub fn text_content(&self) -> Result> {
let mut text = Vec::new();
for node in *self.children {
match node {
Node::Text(t) => text.push(t),
_ => {}
}
}
if text.is_empty() {
return Err(ElementError::NotText.into());
}
Ok(text)
}
/// returns whether or not the element is qualified by a namespace, either declared
/// by a parent, or itself.
fn namespace_qualified>(
&self,
namespace_context: &BTreeMap