diff options
Diffstat (limited to 'src/stanza')
| -rw-r--r-- | src/stanza/bind.rs | 29 | ||||
| -rw-r--r-- | src/stanza/mod.rs | 399 | 
2 files changed, 263 insertions, 165 deletions
| diff --git a/src/stanza/bind.rs b/src/stanza/bind.rs index f1bdc2d..5e9704f 100644 --- a/src/stanza/bind.rs +++ b/src/stanza/bind.rs @@ -1,10 +1,12 @@ +use std::collections::BTreeMap; +  use quick_xml::{      events::{BytesStart, BytesText, Event},      name::QName,      Reader,  }; -use super::{Element, IntoElement}; +use super::{Element, IntoElement, Node};  use crate::{JabberError, JID};  const XMLNS: &str = "urn:ietf:params:xml:ns:xmpp-bind"; @@ -14,7 +16,30 @@ pub struct Bind {      pub jid: Option<JID>,  } -impl<'e> IntoElement<'e> for Bind { +impl From<Bind> for Element { +    fn from(value: Bind) -> Self { +        let mut namespace_declarations = Box::new(BTreeMap::new()); +        namespace_declarations.insert(None, XMLNS.to_owned()); +        let mut children = Vec::new(); +        if let Some(resource) = value.resource { +            children.push(Node::Element( +                Element { prefix: None, localname: "", namespace: , namespace_declarations: , attributes: , children:  } +            )  +                 +            ) +        } +        Self { +            prefix: None, +            localname: "bind".to_string(), +            namespace: XMLNS.to_owned(), +            namespace_declarations, +            attributes: todo!(), +            children: todo!(), +        } +    } +} + +impl IntoElement for Bind {      fn event(&self) -> quick_xml::events::Event<'static> {          let mut bind_event = BytesStart::new("bind");          bind_event.push_attribute(("xmlns", XMLNS)); diff --git a/src/stanza/mod.rs b/src/stanza/mod.rs index e96ae9c..1bb3fc2 100644 --- a/src/stanza/mod.rs +++ b/src/stanza/mod.rs @@ -17,23 +17,17 @@ use tokio::io::{AsyncBufRead, AsyncWrite};  use crate::{JabberError, Result}; -// #[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)]  /// represents an xml element as a tree of nodes -pub struct Element<'s> { +pub struct Element {      /// element prefix      /// e.g. `foo` in `<foo:bar />`. -    prefix: Option<&'s str>, +    prefix: Option<String>,      /// element name      /// e.g. `bar` in `<foo:bar />`. -    localname: &'s str, +    localname: String,      /// qualifying namespace      /// an element must be qualified by a namespace      /// e.g. for `<stream:features>` in @@ -61,7 +55,7 @@ pub struct Element<'s> {      /// </stream:stream>      /// ```      /// would be `"jabber:client"` -    namespace: &'s str, +    namespace: String,      /// all namespaces applied to element      /// e.g. for `<bind>` in      /// ``` @@ -75,22 +69,49 @@ 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 -    namespace_declarations: Box<BTreeMap<Option<&'s str>, &'s str>>, +    // 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<BTreeMap<Option<String>, String>>,      /// element attributes -    attributes: Box<BTreeMap<&'s str, &'s str>>, +    attributes: Box<BTreeMap<String, String>>,      // children elements namespaces contain their parents' namespaces -    children: Box<Vec<Node<'s>>>, +    children: Box<Vec<Node>>, +} + +impl Element { +    pub fn new_empty<S: ToString, C: Into<Node>>( +        prefix: Option<S>, +        localname: S, +        namespace: S, +        namespace_declarations: BTreeMap<Option<S>, S>, +        attributes: BTreeMap<S, S>, +        children: Vec<C>, +    ) { +    } +    pub fn push_child<C: Into<Node>>(&mut self, node: C) {}  }  #[derive(Clone, Debug)] -pub enum Node<'s> { -    Element(Element<'s>), -    Text(&'s str), +pub enum Node { +    Element(Element), +    Text(String),      Unknown,  } -impl<'s> From<&Node<'s>> for Vec<Event<'s>> { -    fn from(node: &Node<'s>) -> Self { +impl From<Element> for Node { +    fn from(element: Element) -> Self { +        Self::Element(element) +    } +} + +impl<S: ToString> From<S> for Node { +    fn from(text: S) -> Self { +        Self::Text(text.to_string()) +    } +} + +impl<'s> From<&Node> for Vec<Event<'s>> { +    fn from(node: &Node) -> Self {          match node {              Node::Element(e) => e.into(),              Node::Text(t) => vec![Event::Text(BytesText::new(t))], @@ -99,7 +120,7 @@ impl<'s> From<&Node<'s>> for Vec<Event<'s>> {      }  } -impl<'s> Element<'s> { +impl Element {      /// returns the fully qualified name      /// e.g. `foo:bar` in      /// `<foo:bar>`. @@ -107,14 +128,14 @@ impl<'s> Element<'s> {          if let Some(prefix) = self.prefix {              format!("{}:{}", prefix, self.localname).as_str()          } else { -            self.localname +            &self.localname          }      }      /// returns the localname.      /// e.g. `bar` in `<foo:bar>`      pub fn localname(&self) -> &str { -        self.localname +        &self.localname      }      /// returns the prefix. @@ -130,12 +151,12 @@ impl<'s> Element<'s> {      /// `<bar:element xmlns='foo' xmlns:bar='bar'>`      /// it will be `bar`.      pub fn namespace(&self) -> &str { -        self.namespace +        &self.namespace      }  } -impl<'s> From<&Element<'s>> for Vec<Event<'s>> { -    fn from(element: &Element<'s>) -> Self { +impl<'s> From<&Element> for Vec<Event<'s>> { +    fn from(element: &Element) -> Self {          let name = element.name();          let event = BytesStart::new(name); @@ -183,9 +204,9 @@ impl<'s> From<&Element<'s>> for Vec<Event<'s>> {      }  } -impl<'s> Element<'s> { +impl Element {      /// if there is only one child in the vec of children, will return that element -    pub fn child(&self) -> Result<&Node<'s>> { +    pub fn child(&self) -> Result<&Node> {          if self.children.len() == 1 {              Ok(&self.children[0])          } else if self.children.len() > 1 { @@ -196,7 +217,7 @@ impl<'s> Element<'s> {      }      /// returns reference to children -    pub fn children(&self) -> Result<&Vec<Node<'s>>> { +    pub fn children(&self) -> Result<&Vec<Node>> {          if !self.children.is_empty() {              Ok(&self.children)          } else { @@ -206,7 +227,7 @@ impl<'s> Element<'s> {      /// returns text content, error if there is none      pub fn text_content(&self) -> Result<Vec<&str>> { -        let text = Vec::new(); +        let mut text = Vec::new();          for node in *self.children {              match node {                  Node::Text(t) => text.push(t), @@ -214,43 +235,86 @@ impl<'s> Element<'s> {              }          }          if text.is_empty() { -            Err(ElementError::NotText) +            return Err(ElementError::NotText.into());          }          Ok(text)      } -    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? +    /// returns whether or not the element is qualified by a namespace, either declared +    /// by a parent, or itself. +    fn namespace_qualified<S: AsRef<str>>( +        &self, +        local_namespaces: &BTreeMap<Option<S>, S>, +    ) -> bool { +        if let Some(namespace) = local_namespaces.get(self.prefix) { +            if namespace != self.namespace { +                return false; +            } +        }; + +        if let Some(namespace) = self.namespace_declarations.get(&self.prefix) { +            if namespace != self.namespace { +                return false; +            } +        } + +        for child in *self.children { +            if child.namespace_qualified(local_namespaces) == false { +                return false; +            }          } -        Ok(()) + +        true      } -    pub async fn write_start<W: AsyncWrite + Unpin + Send>( +    /// writes an element to a writer. the element's namespace must be qualified by the +    /// context given in `local_namespaces` or the element's internal namespace declarations +    pub async fn write<S: AsRef<str>, W: AsyncWrite + Unpin + Send>(          &self,          writer: &mut Writer<W>, +        local_namespaces: &BTreeMap<Option<S>, S>,      ) -> Result<()> { -        let mut event = BytesStart::new(self.name()); +        // TODO: NEXT: instead of having a check if namespace qualified function, have the namespace declarations be added if needed given the context when converting from `Element` to `Event`s +        if self.namespace_qualified(local_namespaces) { +            let events: Vec<Event> = self.into(); +            for event in events { +                writer.write_event_async(event).await? +            } +            Ok(()) +        } else { +            Err(ElementError::NamespaceNotQualified.into()) +        } +    } -        // 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)) +    pub async fn write_start<S: AsRef<str>, W: AsyncWrite + Unpin + Send>( +        &self, +        writer: &mut Writer<W>, +        local_namespaces: &BTreeMap<Option<S>, S>, +    ) -> Result<()> { +        if self.namespace_qualified(local_namespaces) { +            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)),                  } -                None => event.push_attribute(("xmlns", *namespace)), -            } -        }); +            }); -        // attributes -        let event = -            event.with_attributes(self.attributes.iter().map(|(attr, value)| (*attr, *value))); +            // attributes +            let event = +                event.with_attributes(self.attributes.iter().map(|(attr, value)| (*attr, *value))); -        writer.write_event_async(Event::Start(event)).await?; +            writer.write_event_async(Event::Start(event)).await?; -        Ok(()) +            Ok(()) +        } else { +            Err(ElementError::NamespaceNotQualified.into()) +        }      }      pub async fn write_end<W: AsyncWrite + Unpin + Send>( @@ -263,9 +327,9 @@ impl<'s> Element<'s> {      }      #[async_recursion] -    pub async fn read<R: AsyncBufRead + Unpin + Send>( +    pub async fn read<S: AsRef<str>, R: AsyncBufRead + Unpin + Send>(          reader: &mut Reader<R>, -        local_namespaces: &BTreeMap<Option<&str>, &str>, +        local_namespaces: &BTreeMap<Option<S>, S>,      ) -> Result<Self> {          let node = Node::read_recursive(reader, local_namespaces)              .await? @@ -276,21 +340,25 @@ impl<'s> Element<'s> {              Node::Unknown => Err(JabberError::UnexpectedElement),          }      } -    pub async fn read_start<R: AsyncBufRead + Unpin + Send>( + +    pub async fn read_start<S: AsRef<str>, R: AsyncBufRead + Unpin + Send>(          reader: &mut Reader<R>, -        local_namespaces: &BTreeMap<Option<&str>, &str>, -    ) -> Result<Self> { -        let mut buf = Vec::new(); +        local_namespaces: &BTreeMap<Option<S>, S>, +    ) -> Result<Element> { +        let buf = Vec::new();          let event = reader.read_event_into_async(&mut buf).await?;          match event {              Event::Start(e) => { -                let prefix = e -                    .name() -                    .prefix() -                    .map(|prefix| str::from_utf8(prefix.into_inner())?); -                let localname = str::from_utf8(e.local_name().into_inner())?; +                let prefix = e.name().prefix().map(|prefix| prefix.into_inner()); +                let converted_prefix; +                if let Some(raw_prefix) = prefix { +                    converted_prefix = Some(str::from_utf8(raw_prefix)?) +                } +                let prefix = converted_prefix; + +                let localname = str::from_utf8(e.local_name().into_inner())?.to_owned(); -                let mut namespaces = local_namespaces.clone(); +                let mut local_namespaces = local_namespaces.clone();                  let mut namespace_declarations = BTreeMap::new();                  let attributes = BTreeMap::new(); @@ -300,62 +368,70 @@ impl<'s> Element<'s> {                          match prefix_declaration {                              PrefixDeclaration::Default => {                                  let value = str::from_utf8(attribute.value.as_ref())?; -                                namespace_declarations.try_insert(None, value); -                                namespaces.insert(None, value); +                                if let Some(_) = namespace_declarations.insert(None, value) { +                                    return Err(ElementParseError::DuplicateAttribute.into()); +                                }; +                                local_namespaces.insert(None, value);                              }                              PrefixDeclaration::Named(prefix) => {                                  let key = str::from_utf8(prefix)?;                                  let value = str::from_utf8(attribute.value.as_ref())?; -                                namespace_declarations -                                    .try_insert(Some(key), value) -                                    .map_err(ParseError::DuplicateAttribute)?; -                                namespaces.insert(Some(key), value); +                                if let Some(_) = namespace_declarations.insert(Some(key), value) { +                                    return Err(ElementParseError::DuplicateAttribute.into()); +                                }; +                                local_namespaces.insert(Some(key), value);                              }                          }                      } else { -                        attributes -                            .try_insert( -                                str::from_utf8(attribute.key.into_inner())?, -                                str::from_utf8(attribute.value.as_ref())?, -                            ) -                            .map_err(ParseError::DuplicateAttribute)?; +                        if let Some(_) = attributes.insert( +                            str::from_utf8(attribute.key.into_inner())?, +                            str::from_utf8(attribute.value.as_ref())?, +                        ) { +                            return Err(ElementParseError::DuplicateAttribute.into()); +                        };                      }                  } -                let namespace = *namespaces.get(&prefix).ok_or(ParseError::NoNamespace)?; +                let namespace = *local_namespaces +                    .get(&prefix) +                    .ok_or(ElementParseError::NoNamespace)?;                  let mut children = Vec::new(); -                Ok(Some(Self::Element(Element { +                Ok(Self {                      prefix,                      localname,                      namespace, -                    namespace_declarations, -                    attributes, -                    children, -                }))) +                    namespace_declarations: Box::new(namespace_declarations), +                    attributes: Box::new(attributes), +                    children: Box::new(children), +                })              } -            e => Err(ElementError::NotAStart(e)), +            e => Err(ElementError::NotAStart(e).into()),          }      }  } -impl<'s> Node<'s> { -    async fn read_recursive<R: AsyncBufRead + Unpin + Send>( +impl Node { +    #[async_recursion] +    async fn read_recursive<S: AsRef<str>, R: AsyncBufRead + Unpin + Send>(          reader: &mut Reader<R>, -        local_namespaces: &BTreeMap<Option<&str>, &str>, -    ) -> Result<Option<Node<'s>>> { +        local_namespaces: &BTreeMap<Option<S>, S>, +    ) -> Result<Option<Node>> {          let mut buf = Vec::new();          let event = reader.read_event_into_async(&mut buf).await?;          match event {              Event::Empty(e) => { -                let prefix = e -                    .name() -                    .prefix() -                    .map(|prefix| str::from_utf8(prefix.into_inner())?); -                let localname = str::from_utf8(e.local_name().into_inner())?; +                let prefix = e.name().prefix().map(|prefix| prefix.into_inner()); +                let converted_prefix; +                if let Some(raw_prefix) = prefix { +                    converted_prefix = Some(str::from_utf8(raw_prefix)?) +                } +                let prefix = converted_prefix; + +                let localname = str::from_utf8(e.local_name().into_inner())?.to_owned(); -                let mut namespaces = local_namespaces.clone(); +                let mut local_namespaces = local_namespaces.clone();                  let mut namespace_declarations = BTreeMap::new();                  let attributes = BTreeMap::new(); @@ -365,49 +441,56 @@ impl<'s> Node<'s> {                          match prefix_declaration {                              PrefixDeclaration::Default => {                                  let value = str::from_utf8(attribute.value.as_ref())?; -                                namespace_declarations.try_insert(None, value); -                                namespaces.insert(None, value); +                                if let Some(_) = namespace_declarations.insert(None, value) { +                                    return Err(ElementParseError::DuplicateAttribute.into()); +                                }; +                                local_namespaces.insert(None, value);                              }                              PrefixDeclaration::Named(prefix) => {                                  let key = str::from_utf8(prefix)?;                                  let value = str::from_utf8(attribute.value.as_ref())?; -                                namespace_declarations -                                    .try_insert(Some(key), value) -                                    .map_err(ParseError::DuplicateAttribute)?; -                                namespaces.insert(Some(key), value); +                                if let Some(_) = namespace_declarations.insert(Some(key), value) { +                                    return Err(ElementParseError::DuplicateAttribute.into()); +                                }; +                                local_namespaces.insert(Some(key), value);                              }                          }                      } else { -                        attributes -                            .try_insert( -                                str::from_utf8(attribute.key.into_inner())?, -                                str::from_utf8(attribute.value.as_ref())?, -                            ) -                            .map_err(ParseError::DuplicateAttribute)?; +                        if let Some(_) = attributes.insert( +                            str::from_utf8(attribute.key.into_inner())?, +                            str::from_utf8(attribute.value.as_ref())?, +                        ) { +                            return Err(ElementParseError::DuplicateAttribute.into()); +                        };                      }                  } -                let namespace = *namespaces.get(&prefix).ok_or(ParseError::NoNamespace)?; +                let namespace = *local_namespaces +                    .get(&prefix) +                    .ok_or(ElementParseError::NoNamespace)?; -                let children = Vec::new(); +                let mut children = Vec::new();                  Ok(Some(Self::Element(Element {                      prefix,                      localname,                      namespace, -                    namespace_declarations, -                    attributes, -                    children, +                    namespace_declarations: Box::new(namespace_declarations), +                    attributes: Box::new(attributes), +                    children: Box::new(children),                  })))              }              Event::Start(e) => { -                let prefix = e -                    .name() -                    .prefix() -                    .map(|prefix| str::from_utf8(prefix.into_inner())?); -                let localname = str::from_utf8(e.local_name().into_inner())?; +                let prefix = e.name().prefix().map(|prefix| prefix.into_inner()); +                let converted_prefix; +                if let Some(raw_prefix) = prefix { +                    converted_prefix = Some(str::from_utf8(raw_prefix)?) +                } +                let prefix = converted_prefix; + +                let localname = str::from_utf8(e.local_name().into_inner())?.to_owned(); -                let mut namespaces = local_namespaces.clone(); +                let mut local_namespaces = local_namespaces.clone();                  let mut namespace_declarations = BTreeMap::new();                  let attributes = BTreeMap::new(); @@ -417,92 +500,82 @@ impl<'s> Node<'s> {                          match prefix_declaration {                              PrefixDeclaration::Default => {                                  let value = str::from_utf8(attribute.value.as_ref())?; -                                namespace_declarations.try_insert(None, value); -                                namespaces.insert(None, value); +                                if let Some(_) = namespace_declarations.insert(None, value) { +                                    return Err(ElementParseError::DuplicateAttribute.into()); +                                }; +                                local_namespaces.insert(None, value);                              }                              PrefixDeclaration::Named(prefix) => {                                  let key = str::from_utf8(prefix)?;                                  let value = str::from_utf8(attribute.value.as_ref())?; -                                namespace_declarations -                                    .try_insert(Some(key), value) -                                    .map_err(ParseError::DuplicateAttribute)?; -                                namespaces.insert(Some(key), value); +                                if let Some(_) = namespace_declarations.insert(Some(key), value) { +                                    return Err(ElementParseError::DuplicateAttribute.into()); +                                }; +                                local_namespaces.insert(Some(key), value);                              }                          }                      } else { -                        attributes -                            .try_insert( -                                str::from_utf8(attribute.key.into_inner())?, -                                str::from_utf8(attribute.value.as_ref())?, -                            ) -                            .map_err(ParseError::DuplicateAttribute)?; +                        if let Some(_) = attributes.insert( +                            str::from_utf8(attribute.key.into_inner())?, +                            str::from_utf8(attribute.value.as_ref())?, +                        ) { +                            return Err(ElementParseError::DuplicateAttribute.into()); +                        };                      }                  } -                let namespace = *namespaces.get(&prefix).ok_or(ParseError::NoNamespace)?; +                let namespace = *local_namespaces +                    .get(&prefix) +                    .ok_or(ElementParseError::NoNamespace)?;                  let mut children = Vec::new(); -                while let Some(child_node) = Node::read_recursive(reader, &namespaces).await? { +                while let Some(child_node) = Node::read_recursive(reader, &local_namespaces).await? +                {                      children.push(child_node)                  } +                let mut children = Vec::new(); +                  Ok(Some(Self::Element(Element {                      prefix,                      localname,                      namespace, -                    namespace_declarations, -                    attributes, -                    children, +                    namespace_declarations: Box::new(namespace_declarations), +                    attributes: Box::new(attributes), +                    children: Box::new(children),                  })))              }              Event::End(_) => Ok(None), -            Event::Text(e) => Ok(Some(Self::Text(e.unescape()?.as_ref()))), +            Event::Text(e) => Ok(Some(Self::Text(e.unescape()?.as_ref().to_string()))),              e => Ok(Some(Self::Unknown)),          }      } + +    fn namespace_qualified<S: AsRef<str>>( +        &self, +        local_namespaces: &BTreeMap<Option<S>, S>, +    ) -> bool { +        match self { +            Self::Element(e) => e.namespace_qualified(local_namespaces), +            _ => true, +        } +    }  } -// #[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()), -//     } -// } - -// 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(), -//         } -//     } -// } +// the issue is i don't know how to validate that an element always has a namespace when it is being written +// TODO: ElementBuilder that makes it easier to build an element under a namespace  #[derive(Debug)]  pub enum ElementError<'e> {      NotAStart(Event<'e>),      NotText,      NoChildren, +    NamespaceNotQualified,      MultipleChildren,  }  #[derive(Debug)] -pub enum ParseError { +pub enum ElementParseError {      DuplicateAttribute,      NoNamespace,  } | 
