From 2a7b8834d750a312eef34ad50d56d49bc9a9341e Mon Sep 17 00:00:00 2001 From: cel 🌸 Date: Wed, 2 Aug 2023 18:21:57 +0100 Subject: WIP: refactor Element type --- src/client/encrypted.rs | 7 +++ src/lib.rs | 3 ++ 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) -> Result<()> { println!("{:?}", mechanisms); let sasl = SASLClient::new(self.jabber.auth.clone()); diff --git a/src/lib.rs b/src/lib.rs index 95a228b..8162ccc 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -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>>, +// } + +pub type Prefix<'s> = Option<&'s str>; + #[derive(Clone, Debug)] -pub struct Element<'e> { - pub event: Event<'e>, - pub children: Option>>, +/// represents an xml element as a tree of nodes +pub struct Element<'s> { + /// element prefix + /// e.g. `foo` in ``. + prefix: Option<&'s str>, + /// 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: &'s str, + /// element name + /// e.g. `bar` in ``. + name: &'s str, + /// 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 + namespaces: Box, &'s str>>, + /// element attributes + attributes: Box>, + // children elements namespaces contain their parents' namespaces + /// + children: Option>>>, +} + +#[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 + /// `` + /// it will be `http://etherx.jabber.org/streams` but for + /// `` + /// 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?; -- cgit