summaryrefslogtreecommitdiffstats
path: root/src/stanza/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/stanza/mod.rs')
-rw-r--r--src/stanza/mod.rs223
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,
+}