diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/stanza/mod.rs | 223 | 
1 files changed, 182 insertions, 41 deletions
| diff --git a/src/stanza/mod.rs b/src/stanza/mod.rs index 7f4790d..e96ae9c 100644 --- a/src/stanza/mod.rs +++ b/src/stanza/mod.rs @@ -11,6 +11,7 @@ use std::str;  // const DECLARATION: BytesDecl<'_> = BytesDecl::new("1.0", None, None);  use async_recursion::async_recursion;  use quick_xml::events::{BytesEnd, BytesStart, BytesText, Event}; +use quick_xml::name::PrefixDeclaration;  use quick_xml::{Reader, Writer};  use tokio::io::{AsyncBufRead, AsyncWrite}; @@ -85,6 +86,7 @@ pub struct Element<'s> {  pub enum Node<'s> {      Element(Element<'s>),      Text(&'s str), +    Unknown,  }  impl<'s> From<&Node<'s>> for Vec<Event<'s>> { @@ -92,6 +94,7 @@ impl<'s> From<&Node<'s>> for Vec<Event<'s>> {          match node {              Node::Element(e) => e.into(),              Node::Text(t) => vec![Event::Text(BytesText::new(t))], +            Unknown => vec![],          }      }  } @@ -182,16 +185,18 @@ impl<'s> From<&Element<'s>> for Vec<Event<'s>> {  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>> { +    pub fn child(&self) -> Result<&Node<'s>> {          if self.children.len() == 1 {              Ok(&self.children[0]) +        } else if self.children.len() > 1 { +            Err(ElementError::MultipleChildren.into())          } else {              Err(ElementError::NoChildren.into())          }      }      /// returns reference to children -    pub fn children(&self) -> Result<&Vec<Element<'s>>> { +    pub fn children(&self) -> Result<&Vec<Node<'s>>> {          if !self.children.is_empty() {              Ok(&self.children)          } else { @@ -200,14 +205,18 @@ impl<'s> Element<'s> {      }      /// returns text content, error if there is none -    pub fn content(&self) -> Result<&str> { +    pub fn text_content(&self) -> Result<Vec<&str>> { +        let text = Vec::new();          for node in *self.children {              match node { -                Node::Text(t) => return Ok(t), +                Node::Text(t) => text.push(t),                  _ => {}              }          } -        Err(ElementError::NotText) +        if text.is_empty() { +            Err(ElementError::NotText) +        } +        Ok(text)      }      pub async fn write<W: AsyncWrite + Unpin + Send>(&self, writer: &mut Writer<W>) -> Result<()> { @@ -252,32 +261,11 @@ impl<'s> Element<'s> {          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>, -        local_namespaces: BTreeMap<Option<&str>, &str>, +        local_namespaces: &BTreeMap<Option<&str>, &str>,      ) -> Result<Self> {          let node = Node::read_recursive(reader, local_namespaces)              .await? @@ -285,44 +273,191 @@ impl<'s> Element<'s> {          match node {              Node::Element(e) => Ok(e),              Node::Text(_) => Err(JabberError::UnexpectedText), +            Node::Unknown => Err(JabberError::UnexpectedElement), +        } +    } +    pub async fn read_start<R: AsyncBufRead + Unpin + Send>( +        reader: &mut Reader<R>, +        local_namespaces: &BTreeMap<Option<&str>, &str>, +    ) -> Result<Self> { +        let mut 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 mut namespaces = local_namespaces.clone(); +                let mut namespace_declarations = BTreeMap::new(); +                let attributes = BTreeMap::new(); + +                for attribute in e.attributes() { +                    let attribute = attribute?; +                    if let Some(prefix_declaration) = attribute.key.as_namespace_binding() { +                        match prefix_declaration { +                            PrefixDeclaration::Default => { +                                let value = str::from_utf8(attribute.value.as_ref())?; +                                namespace_declarations.try_insert(None, value); +                                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); +                            } +                        } +                    } else { +                        attributes +                            .try_insert( +                                str::from_utf8(attribute.key.into_inner())?, +                                str::from_utf8(attribute.value.as_ref())?, +                            ) +                            .map_err(ParseError::DuplicateAttribute)?; +                    } +                } + +                let namespace = *namespaces.get(&prefix).ok_or(ParseError::NoNamespace)?; + +                let mut children = Vec::new(); + +                Ok(Some(Self::Element(Element { +                    prefix, +                    localname, +                    namespace, +                    namespace_declarations, +                    attributes, +                    children, +                }))) +            } +            e => Err(ElementError::NotAStart(e)),          }      }  }  impl<'s> Node<'s> { -    #[async_recursion]      async fn read_recursive<R: AsyncBufRead + Unpin + Send>(          reader: &mut Reader<R>, -        local_namespaces: BTreeMap<Option<&str>, &str>, +        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::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 mut namespaces = local_namespaces.clone(); +                let mut namespace_declarations = BTreeMap::new(); +                let attributes = BTreeMap::new(); + +                for attribute in e.attributes() { +                    let attribute = attribute?; +                    if let Some(prefix_declaration) = attribute.key.as_namespace_binding() { +                        match prefix_declaration { +                            PrefixDeclaration::Default => { +                                let value = str::from_utf8(attribute.value.as_ref())?; +                                namespace_declarations.try_insert(None, value); +                                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); +                            } +                        } +                    } else { +                        attributes +                            .try_insert( +                                str::from_utf8(attribute.key.into_inner())?, +                                str::from_utf8(attribute.value.as_ref())?, +                            ) +                            .map_err(ParseError::DuplicateAttribute)?; +                    } +                } + +                let namespace = *namespaces.get(&prefix).ok_or(ParseError::NoNamespace)?; + +                let children = Vec::new(); + +                Ok(Some(Self::Element(Element { +                    prefix, +                    localname, +                    namespace, +                    namespace_declarations, +                    attributes, +                    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 mut namespaces = local_namespaces.clone(); +                let mut namespace_declarations = BTreeMap::new(); +                let attributes = BTreeMap::new(); + +                for attribute in e.attributes() { +                    let attribute = attribute?; +                    if let Some(prefix_declaration) = attribute.key.as_namespace_binding() { +                        match prefix_declaration { +                            PrefixDeclaration::Default => { +                                let value = str::from_utf8(attribute.value.as_ref())?; +                                namespace_declarations.try_insert(None, value); +                                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); +                            } +                        } +                    } else { +                        attributes +                            .try_insert( +                                str::from_utf8(attribute.key.into_inner())?, +                                str::from_utf8(attribute.value.as_ref())?, +                            ) +                            .map_err(ParseError::DuplicateAttribute)?; +                    } +                } -                let mut children_vec: Vec = Vec::new(); -                while let Some(sub_element) = Element::read_recursive(reader).await? { -                    children_vec.push(sub_element) +                let namespace = *namespaces.get(&prefix).ok_or(ParseError::NoNamespace)?; + +                let mut children = Vec::new(); +                while let Some(child_node) = Node::read_recursive(reader, &namespaces).await? { +                    children.push(child_node)                  } +                  Ok(Some(Self::Element(Element {                      prefix, -                    localname: e.local_name().into_inner(), -                    namespace: todo!(), -                    namespace_declarations: todo!(), -                    attributes: todo!(), -                    children: todo!(), +                    localname, +                    namespace, +                    namespace_declarations, +                    attributes, +                    children,                  })))              }              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, -            })), +            e => Ok(Some(Self::Unknown)),          }      }  } @@ -365,3 +500,9 @@ pub enum ElementError<'e> {      NoChildren,      MultipleChildren,  } + +#[derive(Debug)] +pub enum ParseError { +    DuplicateAttribute, +    NoNamespace, +} | 
