WIP: refactor Element type
This commit is contained in:
parent
cd7bb95c0a
commit
2a7b8834d7
|
@ -85,6 +85,13 @@ impl<'j> JabberClient<'j> {
|
|||
}
|
||||
}
|
||||
|
||||
pub async fn watch(&mut self) -> Result<()> {
|
||||
loop {
|
||||
let element = Element::read(&mut self.reader).await?;
|
||||
println!("{:#?}", element);
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn sasl(&mut self, mechanisms: &Vec<String>) -> Result<()> {
|
||||
println!("{:?}", mechanisms);
|
||||
let sasl = SASLClient::new(self.jabber.auth.clone());
|
||||
|
|
|
@ -52,6 +52,9 @@ mod tests {
|
|||
.unwrap()
|
||||
.login()
|
||||
.await
|
||||
.unwrap()
|
||||
.watch()
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,18 +5,117 @@ 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::Event;
|
||||
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)]
|
||||
pub struct Element<'e> {
|
||||
pub event: Event<'e>,
|
||||
pub children: Option<Vec<Element<'e>>>,
|
||||
/// 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> {
|
||||
|
@ -35,6 +134,9 @@ impl<'e: 'async_recursion, 'async_recursion> Element<'e> {
|
|||
'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?;
|
||||
|
|
Loading…
Reference in New Issue