diff options
Diffstat (limited to '')
| -rw-r--r-- | src/stanza/mod.rs | 359 | 
1 files changed, 225 insertions, 134 deletions
| diff --git a/src/stanza/mod.rs b/src/stanza/mod.rs index 8251422..7f4790d 100644 --- a/src/stanza/mod.rs +++ b/src/stanza/mod.rs @@ -6,14 +6,15 @@ 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::{BytesStart, Event}; +use quick_xml::events::{BytesEnd, BytesStart, BytesText, Event};  use quick_xml::{Reader, Writer};  use tokio::io::{AsyncBufRead, AsyncWrite}; -use crate::JabberError; +use crate::{JabberError, Result};  // #[derive(Clone, Debug)]  // pub struct EventTree<'e> { @@ -29,6 +30,9 @@ pub struct Element<'s> {      /// element prefix      /// e.g. `foo` in `<foo:bar />`.      prefix: Option<&'s str>, +    /// element name +    /// e.g. `bar` in `<foo:bar />`. +    localname: &'s str,      /// qualifying namespace      /// an element must be qualified by a namespace      /// e.g. for `<stream:features>` in @@ -57,9 +61,6 @@ pub struct Element<'s> {      /// ```      /// 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      /// ``` @@ -73,12 +74,11 @@ pub struct Element<'s> {      /// ```      /// 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>>, +    namespace_declarations: 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>>>>, +    children: Box<Vec<Node<'s>>>,  }  #[derive(Clone, Debug)] @@ -87,190 +87,281 @@ pub enum Node<'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)); +impl<'s> From<&Node<'s>> for Vec<Event<'s>> { +    fn from(node: &Node<'s>) -> Self { +        match node { +            Node::Element(e) => e.into(), +            Node::Text(t) => vec![Event::Text(BytesText::new(t))], +        } +    } +} + +impl<'s> Element<'s> { +    /// returns the fully qualified name +    /// e.g. `foo:bar` in +    /// `<foo:bar>`. +    pub fn name(&self) -> &str { +        if let Some(prefix) = self.prefix { +            format!("{}:{}", prefix, self.localname).as_str()          } else { -            event = BytesStart::new(element.name); +            self.localname          } +    } -        event -         -        let event = event.with_attributes(element.attributes.into_iter()); +    /// returns the localname. +    /// e.g. `bar` in `<foo:bar>` +    pub fn localname(&self) -> &str { +        self.localname +    } -        match element.children.is_none() { -            true => return Event::Empty(event), -            false => return Event::Start(event), -        } +    /// returns the prefix. +    /// e.g. `foo` in `<foo:bar>`. returns None if there is +    /// no prefix. +    pub fn prefix(&self) -> Option<&str> { +        self.prefix      } -} -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 { +    /// `<element xmlns='foo' xmlns:bar='bar'>` +    /// it will be `foo` but for +    /// `<bar:element xmlns='foo' xmlns:bar='bar'>` +    /// it will be `bar`. +    pub fn namespace(&self) -> &str {          self.namespace      }  } -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< -            dyn ::core::future::Future<Output = Result<(), JabberError>> -                + 'async_recursion -                + ::core::marker::Send, -        >, -    > -    where -        W: 'async_recursion, -        'life0: 'async_recursion, -    { -        Box::pin(async move { -            match &self.children.is_empty() { -                true => {} +impl<'s> From<&Element<'s>> for Vec<Event<'s>> { +    fn from(element: &Element<'s>) -> 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),              } -            match &self.event { -                Event::Start(e) => { -                    writer.write_event_async(Event::Start(e.clone())).await?; -                    if let Some(children) = &self.children { -                        for e in children { -                            e.write(writer).await?; -                        } -                    } -                    writer.write_event_async(Event::End(e.to_end())).await?; -                    return Ok(()); +        }); +        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<Event<'s>> = vec![Event::Start(event)]; +                    let start_and_content: Vec<Event<'s>> = start +                        .into_iter() +                        .chain({ +                            let u = element.children.iter().fold( +                                Vec::new(), +                                |acc: Vec<Event<'s>>, child: &Node<'s>| { +                                    acc.into_iter() +                                        .chain(Into::<Vec<Event<'s>>>::into(child).into_iter()) +                                        .collect() +                                }, +                            ); +                            u +                        }) +                        .collect(); +                    let full: Vec<Event<'s>> = start_and_content +                        .into_iter() +                        .chain(vec![Event::End(BytesEnd::new(name))]) +                        .collect(); +                    full                  } -                e => Ok(writer.write_event_async(e).await?),              } -        }) +        }      }  } -impl<'e> Element<'e> { +impl<'s> Element<'s> { +    /// if there is only one child in the vec of children, will return that element +    pub fn child(&self) -> Result<&Element<'s>> { +        if self.children.len() == 1 { +            Ok(&self.children[0]) +        } else { +            Err(ElementError::NoChildren.into()) +        } +    } + +    /// returns reference to children +    pub fn children(&self) -> Result<&Vec<Element<'s>>> { +        if !self.children.is_empty() { +            Ok(&self.children) +        } else { +            Err(ElementError::NoChildren.into()) +        } +    } + +    /// returns text content, error if there is none +    pub fn content(&self) -> Result<&str> { +        for node in *self.children { +            match node { +                Node::Text(t) => return Ok(t), +                _ => {} +            } +        } +        Err(ElementError::NotText) +    } + +    pub async fn write<W: AsyncWrite + Unpin + Send>(&self, writer: &mut Writer<W>) -> Result<()> { +        let events: Vec<Event> = self.into(); +        for event in events { +            writer.write_event_async(event).await? +        } +        Ok(()) +    } +      pub async fn write_start<W: AsyncWrite + Unpin + Send>(          &self,          writer: &mut Writer<W>, -    ) -> Result<(), JabberError> { -        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()), -        } +    ) -> Result<()> { +        let mut event = BytesStart::new(self.name()); + +        // namespace declarations +        self.namespace_declarations.iter().for_each(|declaration| { +            let (prefix, namespace) = declaration; +            match prefix { +                Some(prefix) => { +                    event.push_attribute((format!("xmlns:{}", prefix).as_str(), *namespace)) +                } +                None => event.push_attribute(("xmlns", *namespace)), +            } +        }); + +        // attributes +        let event = +            event.with_attributes(self.attributes.iter().map(|(attr, value)| (*attr, *value))); + +        writer.write_event_async(Event::Start(event)).await?; + +        Ok(())      }      pub async fn write_end<W: AsyncWrite + Unpin + Send>(          &self,          writer: &mut Writer<W>, -    ) -> Result<(), JabberError> { -        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()), -        } +    ) -> Result<()> { +        let event = BytesEnd::new(self.name()); +        writer.write_event_async(Event::End(event)).await?; +        Ok(())      } +    //     pub async fn write_start<W: AsyncWrite + Unpin + Send>( +    //         &self, +    //         writer: &mut Writer<W>, +    //     ) -> Result<(), JabberError> { +    //         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>, +    //     ) -> Result<(), JabberError> { +    //         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>, -    ) -> Result<Self, JabberError> { -        let element = Self::read_recursive(reader) +        local_namespaces: BTreeMap<Option<&str>, &str>, +    ) -> Result<Self> { +        let node = Node::read_recursive(reader, local_namespaces)              .await? -            .ok_or(JabberError::UnexpectedEnd); -        element +            .ok_or(JabberError::UnexpectedEnd)?; +        match node { +            Node::Element(e) => Ok(e), +            Node::Text(_) => Err(JabberError::UnexpectedText), +        }      } +} +impl<'s> Node<'s> {      #[async_recursion]      async fn read_recursive<R: AsyncBufRead + Unpin + Send>(          reader: &mut Reader<R>, -    ) -> Result<Option<Self>, JabberError> { +        local_namespaces: BTreeMap<Option<&str>, &str>, +    ) -> Result<Option<Node<'s>>> {          let mut buf = Vec::new();          let event = reader.read_event_into_async(&mut buf).await?;          match event {              Event::Start(e) => { -                let mut children_vec = Vec::new(); +                let prefix = e +                    .name() +                    .prefix() +                    .map(|prefix| str::from_utf8(prefix.into_inner())?); + +                let mut children_vec: Vec = Vec::new();                  while let Some(sub_element) = Element::read_recursive(reader).await? {                      children_vec.push(sub_element)                  } -                let mut children = None; -                if !children_vec.is_empty() { -                    children = Some(children_vec) -                } -                Ok(Some(Self { -                    event: Event::Start(e.into_owned()), -                    children, -                })) +                Ok(Some(Self::Element(Element { +                    prefix, +                    localname: e.local_name().into_inner(), +                    namespace: todo!(), +                    namespace_declarations: todo!(), +                    attributes: todo!(), +                    children: todo!(), +                })))              }              Event::End(_) => Ok(None), +            Event::Text(e) => Ok(Some(Self::Text(e.unescape()?.as_ref()))),              e => Ok(Some(Self {                  event: e.into_owned(),                  children: None,              })),          }      } - -    #[async_recursion] -    pub async fn read_start<R: AsyncBufRead + Unpin + Send>( -        reader: &mut Reader<R>, -    ) -> Result<Self, JabberError> { -        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()), -                    children: None, -                }) -            } -            e => Err(ElementError::NotAStart(e.into_owned()).into()), -        } -    } - -    /// 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); -        } -        Err(ElementError::NoChildren) -    }  } -pub trait IntoElement<'e> { -    fn event(&self) -> Event<'e>; -    fn children(&self) -> Option<Vec<Element<'e>>>; -} +// #[async_recursion] +// pub async fn read_start<R: AsyncBufRead + Unpin + Send>( +//     reader: &mut Reader<R>, +// ) -> Result<Self, JabberError> { +//     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()), +//                 children: None, +//             }) +//         } +//         e => Err(ElementError::NotAStart(e.into_owned()).into()), +//     } +// } -impl<'e, T: IntoElement<'e>> From<T> for Element<'e> { -    fn from(value: T) -> Self { -        Element { -            event: value.event(), -            children: value.children(), -        } -    } -} +// 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(), +//         } +//     } +// }  #[derive(Debug)]  pub enum ElementError<'e> {      NotAStart(Event<'e>), +    NotText,      NoChildren,      MultipleChildren,  } | 
