WIP: refactor Element type - main architecture done
This commit is contained in:
parent
8ab4a8b436
commit
dec6f0105d
|
@ -11,6 +11,7 @@ use std::str;
|
||||||
// const DECLARATION: BytesDecl<'_> = BytesDecl::new("1.0", None, None);
|
// const DECLARATION: BytesDecl<'_> = BytesDecl::new("1.0", None, None);
|
||||||
use async_recursion::async_recursion;
|
use async_recursion::async_recursion;
|
||||||
use quick_xml::events::{BytesEnd, BytesStart, BytesText, Event};
|
use quick_xml::events::{BytesEnd, BytesStart, BytesText, Event};
|
||||||
|
use quick_xml::name::PrefixDeclaration;
|
||||||
use quick_xml::{Reader, Writer};
|
use quick_xml::{Reader, Writer};
|
||||||
use tokio::io::{AsyncBufRead, AsyncWrite};
|
use tokio::io::{AsyncBufRead, AsyncWrite};
|
||||||
|
|
||||||
|
@ -85,6 +86,7 @@ pub struct Element<'s> {
|
||||||
pub enum Node<'s> {
|
pub enum Node<'s> {
|
||||||
Element(Element<'s>),
|
Element(Element<'s>),
|
||||||
Text(&'s str),
|
Text(&'s str),
|
||||||
|
Unknown,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> From<&Node<'s>> for Vec<Event<'s>> {
|
impl<'s> From<&Node<'s>> for Vec<Event<'s>> {
|
||||||
|
@ -92,6 +94,7 @@ impl<'s> From<&Node<'s>> for Vec<Event<'s>> {
|
||||||
match node {
|
match node {
|
||||||
Node::Element(e) => e.into(),
|
Node::Element(e) => e.into(),
|
||||||
Node::Text(t) => vec![Event::Text(BytesText::new(t))],
|
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> {
|
impl<'s> Element<'s> {
|
||||||
/// if there is only one child in the vec of children, will return that element
|
/// 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 {
|
if self.children.len() == 1 {
|
||||||
Ok(&self.children[0])
|
Ok(&self.children[0])
|
||||||
|
} else if self.children.len() > 1 {
|
||||||
|
Err(ElementError::MultipleChildren.into())
|
||||||
} else {
|
} else {
|
||||||
Err(ElementError::NoChildren.into())
|
Err(ElementError::NoChildren.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// returns reference to children
|
/// 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() {
|
if !self.children.is_empty() {
|
||||||
Ok(&self.children)
|
Ok(&self.children)
|
||||||
} else {
|
} else {
|
||||||
|
@ -200,14 +205,18 @@ impl<'s> Element<'s> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// returns text content, error if there is none
|
/// 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 {
|
for node in *self.children {
|
||||||
match node {
|
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<()> {
|
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?;
|
writer.write_event_async(Event::End(event)).await?;
|
||||||
Ok(())
|
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]
|
#[async_recursion]
|
||||||
pub async fn read<R: AsyncBufRead + Unpin + Send>(
|
pub async fn read<R: AsyncBufRead + Unpin + Send>(
|
||||||
reader: &mut Reader<R>,
|
reader: &mut Reader<R>,
|
||||||
local_namespaces: BTreeMap<Option<&str>, &str>,
|
local_namespaces: &BTreeMap<Option<&str>, &str>,
|
||||||
) -> Result<Self> {
|
) -> Result<Self> {
|
||||||
let node = Node::read_recursive(reader, local_namespaces)
|
let node = Node::read_recursive(reader, local_namespaces)
|
||||||
.await?
|
.await?
|
||||||
|
@ -285,16 +273,13 @@ impl<'s> Element<'s> {
|
||||||
match node {
|
match node {
|
||||||
Node::Element(e) => Ok(e),
|
Node::Element(e) => Ok(e),
|
||||||
Node::Text(_) => Err(JabberError::UnexpectedText),
|
Node::Text(_) => Err(JabberError::UnexpectedText),
|
||||||
|
Node::Unknown => Err(JabberError::UnexpectedElement),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
pub async fn read_start<R: AsyncBufRead + Unpin + Send>(
|
||||||
|
|
||||||
impl<'s> Node<'s> {
|
|
||||||
#[async_recursion]
|
|
||||||
async fn read_recursive<R: AsyncBufRead + Unpin + Send>(
|
|
||||||
reader: &mut Reader<R>,
|
reader: &mut Reader<R>,
|
||||||
local_namespaces: BTreeMap<Option<&str>, &str>,
|
local_namespaces: &BTreeMap<Option<&str>, &str>,
|
||||||
) -> Result<Option<Node<'s>>> {
|
) -> Result<Self> {
|
||||||
let mut buf = Vec::new();
|
let mut buf = Vec::new();
|
||||||
let event = reader.read_event_into_async(&mut buf).await?;
|
let event = reader.read_event_into_async(&mut buf).await?;
|
||||||
match event {
|
match event {
|
||||||
|
@ -303,26 +288,176 @@ impl<'s> Node<'s> {
|
||||||
.name()
|
.name()
|
||||||
.prefix()
|
.prefix()
|
||||||
.map(|prefix| str::from_utf8(prefix.into_inner())?);
|
.map(|prefix| str::from_utf8(prefix.into_inner())?);
|
||||||
|
let localname = str::from_utf8(e.local_name().into_inner())?;
|
||||||
|
|
||||||
let mut children_vec: Vec = Vec::new();
|
let mut namespaces = local_namespaces.clone();
|
||||||
while let Some(sub_element) = Element::read_recursive(reader).await? {
|
let mut namespace_declarations = BTreeMap::new();
|
||||||
children_vec.push(sub_element)
|
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 {
|
Ok(Some(Self::Element(Element {
|
||||||
prefix,
|
prefix,
|
||||||
localname: e.local_name().into_inner(),
|
localname,
|
||||||
namespace: todo!(),
|
namespace,
|
||||||
namespace_declarations: todo!(),
|
namespace_declarations,
|
||||||
attributes: todo!(),
|
attributes,
|
||||||
children: todo!(),
|
children,
|
||||||
|
})))
|
||||||
|
}
|
||||||
|
e => Err(ElementError::NotAStart(e)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'s> Node<'s> {
|
||||||
|
async fn read_recursive<R: AsyncBufRead + Unpin + Send>(
|
||||||
|
reader: &mut Reader<R>,
|
||||||
|
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 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,
|
||||||
|
namespace,
|
||||||
|
namespace_declarations,
|
||||||
|
attributes,
|
||||||
|
children,
|
||||||
})))
|
})))
|
||||||
}
|
}
|
||||||
Event::End(_) => Ok(None),
|
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()))),
|
||||||
e => Ok(Some(Self {
|
e => Ok(Some(Self::Unknown)),
|
||||||
event: e.into_owned(),
|
|
||||||
children: None,
|
|
||||||
})),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -365,3 +500,9 @@ pub enum ElementError<'e> {
|
||||||
NoChildren,
|
NoChildren,
|
||||||
MultipleChildren,
|
MultipleChildren,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum ParseError {
|
||||||
|
DuplicateAttribute,
|
||||||
|
NoNamespace,
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue