diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/client/encrypted.rs | 7 | ||||
| -rw-r--r-- | src/lib.rs | 3 | ||||
| -rw-r--r-- | src/stanza/mod.rs | 110 | 
3 files changed, 116 insertions, 4 deletions
| diff --git a/src/client/encrypted.rs b/src/client/encrypted.rs index 86aba13..03ae295 100644 --- a/src/client/encrypted.rs +++ b/src/client/encrypted.rs @@ -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();      }  } diff --git a/src/stanza/mod.rs b/src/stanza/mod.rs index ad9e228..8251422 100644 --- a/src/stanza/mod.rs +++ b/src/stanza/mod.rs @@ -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?; | 
