From dec6f0105d0da5f06f685d49fd4b118975542d07 Mon Sep 17 00:00:00 2001 From: cel 🌸 Date: Sat, 5 Aug 2023 17:38:50 +0100 Subject: WIP: refactor Element type - main architecture done --- src/stanza/mod.rs | 223 ++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 182 insertions(+), 41 deletions(-) (limited to 'src/stanza/mod.rs') 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> { @@ -92,6 +94,7 @@ impl<'s> From<&Node<'s>> for Vec> { 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> { 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>> { + pub fn children(&self) -> Result<&Vec>> { 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> { + 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(&self, writer: &mut Writer) -> Result<()> { @@ -252,32 +261,11 @@ impl<'s> Element<'s> { writer.write_event_async(Event::End(event)).await?; Ok(()) } - // pub async fn write_start( - // &self, - // writer: &mut Writer, - // ) -> 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( - // &self, - // writer: &mut Writer, - // ) -> 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( reader: &mut Reader, - local_namespaces: BTreeMap, &str>, + local_namespaces: &BTreeMap, &str>, ) -> Result { 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( + reader: &mut Reader, + local_namespaces: &BTreeMap, &str>, + ) -> Result { + 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( reader: &mut Reader, - local_namespaces: BTreeMap, &str>, + local_namespaces: &BTreeMap, &str>, ) -> Result>> { 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, +} -- cgit