WIP: refactor Element type - namespace work
This commit is contained in:
parent
dec6f0105d
commit
5334cd4ed6
|
@ -5,7 +5,7 @@ use rsasl::mechname::MechanismNameError;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
jid::ParseError,
|
jid::ParseError,
|
||||||
stanza::{self, ElementError},
|
stanza::{self, ElementError, ElementParseError},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -22,6 +22,7 @@ pub enum JabberError {
|
||||||
NoType,
|
NoType,
|
||||||
IDMismatch,
|
IDMismatch,
|
||||||
BindError,
|
BindError,
|
||||||
|
ElementParse(ElementParseError),
|
||||||
ParseError,
|
ParseError,
|
||||||
UnexpectedEnd,
|
UnexpectedEnd,
|
||||||
UnexpectedElement,
|
UnexpectedElement,
|
||||||
|
@ -87,3 +88,9 @@ impl From<ParseError> for JabberError {
|
||||||
Self::JID(e)
|
Self::JID(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<ElementParseError> for JabberError {
|
||||||
|
fn from(e: ElementParseError) -> Self {
|
||||||
|
Self::ElementParse(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
use quick_xml::{
|
use quick_xml::{
|
||||||
events::{BytesStart, BytesText, Event},
|
events::{BytesStart, BytesText, Event},
|
||||||
name::QName,
|
name::QName,
|
||||||
Reader,
|
Reader,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{Element, IntoElement};
|
use super::{Element, IntoElement, Node};
|
||||||
use crate::{JabberError, JID};
|
use crate::{JabberError, JID};
|
||||||
|
|
||||||
const XMLNS: &str = "urn:ietf:params:xml:ns:xmpp-bind";
|
const XMLNS: &str = "urn:ietf:params:xml:ns:xmpp-bind";
|
||||||
|
@ -14,7 +16,30 @@ pub struct Bind {
|
||||||
pub jid: Option<JID>,
|
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> {
|
fn event(&self) -> quick_xml::events::Event<'static> {
|
||||||
let mut bind_event = BytesStart::new("bind");
|
let mut bind_event = BytesStart::new("bind");
|
||||||
bind_event.push_attribute(("xmlns", XMLNS));
|
bind_event.push_attribute(("xmlns", XMLNS));
|
||||||
|
|
|
@ -17,23 +17,17 @@ use tokio::io::{AsyncBufRead, AsyncWrite};
|
||||||
|
|
||||||
use crate::{JabberError, Result};
|
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>;
|
pub type Prefix<'s> = Option<&'s str>;
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
/// represents an xml element as a tree of nodes
|
/// represents an xml element as a tree of nodes
|
||||||
pub struct Element<'s> {
|
pub struct Element {
|
||||||
/// element prefix
|
/// element prefix
|
||||||
/// e.g. `foo` in `<foo:bar />`.
|
/// e.g. `foo` in `<foo:bar />`.
|
||||||
prefix: Option<&'s str>,
|
prefix: Option<String>,
|
||||||
/// element name
|
/// element name
|
||||||
/// e.g. `bar` in `<foo:bar />`.
|
/// e.g. `bar` in `<foo:bar />`.
|
||||||
localname: &'s str,
|
localname: String,
|
||||||
/// qualifying namespace
|
/// qualifying namespace
|
||||||
/// an element must be qualified by a namespace
|
/// an element must be qualified by a namespace
|
||||||
/// e.g. for `<stream:features>` in
|
/// e.g. for `<stream:features>` in
|
||||||
|
@ -61,7 +55,7 @@ pub struct Element<'s> {
|
||||||
/// </stream:stream>
|
/// </stream:stream>
|
||||||
/// ```
|
/// ```
|
||||||
/// would be `"jabber:client"`
|
/// would be `"jabber:client"`
|
||||||
namespace: &'s str,
|
namespace: String,
|
||||||
/// all namespaces applied to element
|
/// all namespaces applied to element
|
||||||
/// e.g. for `<bind>` in
|
/// e.g. for `<bind>` in
|
||||||
/// ```
|
/// ```
|
||||||
|
@ -75,22 +69,49 @@ pub struct Element<'s> {
|
||||||
/// ```
|
/// ```
|
||||||
/// would be `[(None, "urn:ietf:params:xml:ns:xmpp-bind")]` despite
|
/// would be `[(None, "urn:ietf:params:xml:ns:xmpp-bind")]` despite
|
||||||
/// `(Some("stream"), "http://etherx.jabber.org/streams")` also being available
|
/// `(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
|
/// element attributes
|
||||||
attributes: Box<BTreeMap<&'s str, &'s str>>,
|
attributes: Box<BTreeMap<String, String>>,
|
||||||
// children elements namespaces contain their parents' namespaces
|
// 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)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum Node<'s> {
|
pub enum Node {
|
||||||
Element(Element<'s>),
|
Element(Element),
|
||||||
Text(&'s str),
|
Text(String),
|
||||||
Unknown,
|
Unknown,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> From<&Node<'s>> for Vec<Event<'s>> {
|
impl From<Element> for Node {
|
||||||
fn from(node: &Node<'s>) -> Self {
|
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 {
|
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))],
|
||||||
|
@ -99,7 +120,7 @@ impl<'s> From<&Node<'s>> for Vec<Event<'s>> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> Element<'s> {
|
impl Element {
|
||||||
/// returns the fully qualified name
|
/// returns the fully qualified name
|
||||||
/// e.g. `foo:bar` in
|
/// e.g. `foo:bar` in
|
||||||
/// `<foo:bar>`.
|
/// `<foo:bar>`.
|
||||||
|
@ -107,14 +128,14 @@ impl<'s> Element<'s> {
|
||||||
if let Some(prefix) = self.prefix {
|
if let Some(prefix) = self.prefix {
|
||||||
format!("{}:{}", prefix, self.localname).as_str()
|
format!("{}:{}", prefix, self.localname).as_str()
|
||||||
} else {
|
} else {
|
||||||
self.localname
|
&self.localname
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// returns the localname.
|
/// returns the localname.
|
||||||
/// e.g. `bar` in `<foo:bar>`
|
/// e.g. `bar` in `<foo:bar>`
|
||||||
pub fn localname(&self) -> &str {
|
pub fn localname(&self) -> &str {
|
||||||
self.localname
|
&self.localname
|
||||||
}
|
}
|
||||||
|
|
||||||
/// returns the prefix.
|
/// returns the prefix.
|
||||||
|
@ -130,12 +151,12 @@ impl<'s> Element<'s> {
|
||||||
/// `<bar:element xmlns='foo' xmlns:bar='bar'>`
|
/// `<bar:element xmlns='foo' xmlns:bar='bar'>`
|
||||||
/// it will be `bar`.
|
/// it will be `bar`.
|
||||||
pub fn namespace(&self) -> &str {
|
pub fn namespace(&self) -> &str {
|
||||||
self.namespace
|
&self.namespace
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> From<&Element<'s>> for Vec<Event<'s>> {
|
impl<'s> From<&Element> for Vec<Event<'s>> {
|
||||||
fn from(element: &Element<'s>) -> Self {
|
fn from(element: &Element) -> Self {
|
||||||
let name = element.name();
|
let name = element.name();
|
||||||
|
|
||||||
let event = BytesStart::new(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
|
/// 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 {
|
if self.children.len() == 1 {
|
||||||
Ok(&self.children[0])
|
Ok(&self.children[0])
|
||||||
} else if self.children.len() > 1 {
|
} else if self.children.len() > 1 {
|
||||||
|
@ -196,7 +217,7 @@ impl<'s> Element<'s> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// returns reference to children
|
/// returns reference to children
|
||||||
pub fn children(&self) -> Result<&Vec<Node<'s>>> {
|
pub fn children(&self) -> Result<&Vec<Node>> {
|
||||||
if !self.children.is_empty() {
|
if !self.children.is_empty() {
|
||||||
Ok(&self.children)
|
Ok(&self.children)
|
||||||
} else {
|
} else {
|
||||||
|
@ -206,7 +227,7 @@ impl<'s> Element<'s> {
|
||||||
|
|
||||||
/// returns text content, error if there is none
|
/// returns text content, error if there is none
|
||||||
pub fn text_content(&self) -> Result<Vec<&str>> {
|
pub fn text_content(&self) -> Result<Vec<&str>> {
|
||||||
let text = Vec::new();
|
let mut text = Vec::new();
|
||||||
for node in *self.children {
|
for node in *self.children {
|
||||||
match node {
|
match node {
|
||||||
Node::Text(t) => text.push(t),
|
Node::Text(t) => text.push(t),
|
||||||
|
@ -214,23 +235,63 @@ impl<'s> Element<'s> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if text.is_empty() {
|
if text.is_empty() {
|
||||||
Err(ElementError::NotText)
|
return Err(ElementError::NotText.into());
|
||||||
}
|
}
|
||||||
Ok(text)
|
Ok(text)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn write<W: AsyncWrite + Unpin + Send>(&self, writer: &mut Writer<W>) -> Result<()> {
|
/// 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 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<()> {
|
||||||
|
// 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();
|
let events: Vec<Event> = self.into();
|
||||||
for event in events {
|
for event in events {
|
||||||
writer.write_event_async(event).await?
|
writer.write_event_async(event).await?
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err(ElementError::NamespaceNotQualified.into())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn write_start<W: AsyncWrite + Unpin + Send>(
|
pub async fn write_start<S: AsRef<str>, W: AsyncWrite + Unpin + Send>(
|
||||||
&self,
|
&self,
|
||||||
writer: &mut Writer<W>,
|
writer: &mut Writer<W>,
|
||||||
|
local_namespaces: &BTreeMap<Option<S>, S>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
|
if self.namespace_qualified(local_namespaces) {
|
||||||
let mut event = BytesStart::new(self.name());
|
let mut event = BytesStart::new(self.name());
|
||||||
|
|
||||||
// namespace declarations
|
// namespace declarations
|
||||||
|
@ -251,6 +312,9 @@ impl<'s> Element<'s> {
|
||||||
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>(
|
pub async fn write_end<W: AsyncWrite + Unpin + Send>(
|
||||||
|
@ -263,9 +327,9 @@ impl<'s> Element<'s> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_recursion]
|
#[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>,
|
reader: &mut Reader<R>,
|
||||||
local_namespaces: &BTreeMap<Option<&str>, &str>,
|
local_namespaces: &BTreeMap<Option<S>, S>,
|
||||||
) -> Result<Self> {
|
) -> Result<Self> {
|
||||||
let node = Node::read_recursive(reader, local_namespaces)
|
let node = Node::read_recursive(reader, local_namespaces)
|
||||||
.await?
|
.await?
|
||||||
|
@ -276,21 +340,25 @@ impl<'s> Element<'s> {
|
||||||
Node::Unknown => Err(JabberError::UnexpectedElement),
|
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>,
|
reader: &mut Reader<R>,
|
||||||
local_namespaces: &BTreeMap<Option<&str>, &str>,
|
local_namespaces: &BTreeMap<Option<S>, S>,
|
||||||
) -> Result<Self> {
|
) -> Result<Element> {
|
||||||
let mut buf = Vec::new();
|
let 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 {
|
||||||
Event::Start(e) => {
|
Event::Start(e) => {
|
||||||
let prefix = e
|
let prefix = e.name().prefix().map(|prefix| prefix.into_inner());
|
||||||
.name()
|
let converted_prefix;
|
||||||
.prefix()
|
if let Some(raw_prefix) = prefix {
|
||||||
.map(|prefix| str::from_utf8(prefix.into_inner())?);
|
converted_prefix = Some(str::from_utf8(raw_prefix)?)
|
||||||
let localname = str::from_utf8(e.local_name().into_inner())?;
|
}
|
||||||
|
let prefix = converted_prefix;
|
||||||
|
|
||||||
let mut namespaces = local_namespaces.clone();
|
let localname = str::from_utf8(e.local_name().into_inner())?.to_owned();
|
||||||
|
|
||||||
|
let mut local_namespaces = local_namespaces.clone();
|
||||||
let mut namespace_declarations = BTreeMap::new();
|
let mut namespace_declarations = BTreeMap::new();
|
||||||
let attributes = BTreeMap::new();
|
let attributes = BTreeMap::new();
|
||||||
|
|
||||||
|
@ -300,62 +368,70 @@ impl<'s> Element<'s> {
|
||||||
match prefix_declaration {
|
match prefix_declaration {
|
||||||
PrefixDeclaration::Default => {
|
PrefixDeclaration::Default => {
|
||||||
let value = str::from_utf8(attribute.value.as_ref())?;
|
let value = str::from_utf8(attribute.value.as_ref())?;
|
||||||
namespace_declarations.try_insert(None, value);
|
if let Some(_) = namespace_declarations.insert(None, value) {
|
||||||
namespaces.insert(None, value);
|
return Err(ElementParseError::DuplicateAttribute.into());
|
||||||
|
};
|
||||||
|
local_namespaces.insert(None, value);
|
||||||
}
|
}
|
||||||
PrefixDeclaration::Named(prefix) => {
|
PrefixDeclaration::Named(prefix) => {
|
||||||
let key = str::from_utf8(prefix)?;
|
let key = str::from_utf8(prefix)?;
|
||||||
let value = str::from_utf8(attribute.value.as_ref())?;
|
let value = str::from_utf8(attribute.value.as_ref())?;
|
||||||
namespace_declarations
|
if let Some(_) = namespace_declarations.insert(Some(key), value) {
|
||||||
.try_insert(Some(key), value)
|
return Err(ElementParseError::DuplicateAttribute.into());
|
||||||
.map_err(ParseError::DuplicateAttribute)?;
|
};
|
||||||
namespaces.insert(Some(key), value);
|
local_namespaces.insert(Some(key), value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
attributes
|
if let Some(_) = attributes.insert(
|
||||||
.try_insert(
|
|
||||||
str::from_utf8(attribute.key.into_inner())?,
|
str::from_utf8(attribute.key.into_inner())?,
|
||||||
str::from_utf8(attribute.value.as_ref())?,
|
str::from_utf8(attribute.value.as_ref())?,
|
||||||
)
|
) {
|
||||||
.map_err(ParseError::DuplicateAttribute)?;
|
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();
|
let mut children = Vec::new();
|
||||||
|
|
||||||
Ok(Some(Self::Element(Element {
|
Ok(Self {
|
||||||
prefix,
|
prefix,
|
||||||
localname,
|
localname,
|
||||||
namespace,
|
namespace,
|
||||||
namespace_declarations,
|
namespace_declarations: Box::new(namespace_declarations),
|
||||||
attributes,
|
attributes: Box::new(attributes),
|
||||||
children,
|
children: Box::new(children),
|
||||||
})))
|
})
|
||||||
}
|
}
|
||||||
e => Err(ElementError::NotAStart(e)),
|
e => Err(ElementError::NotAStart(e).into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> Node<'s> {
|
impl Node {
|
||||||
async fn read_recursive<R: AsyncBufRead + Unpin + Send>(
|
#[async_recursion]
|
||||||
|
async fn read_recursive<S: AsRef<str>, R: AsyncBufRead + Unpin + Send>(
|
||||||
reader: &mut Reader<R>,
|
reader: &mut Reader<R>,
|
||||||
local_namespaces: &BTreeMap<Option<&str>, &str>,
|
local_namespaces: &BTreeMap<Option<S>, S>,
|
||||||
) -> Result<Option<Node<'s>>> {
|
) -> Result<Option<Node>> {
|
||||||
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 {
|
||||||
Event::Empty(e) => {
|
Event::Empty(e) => {
|
||||||
let prefix = e
|
let prefix = e.name().prefix().map(|prefix| prefix.into_inner());
|
||||||
.name()
|
let converted_prefix;
|
||||||
.prefix()
|
if let Some(raw_prefix) = prefix {
|
||||||
.map(|prefix| str::from_utf8(prefix.into_inner())?);
|
converted_prefix = Some(str::from_utf8(raw_prefix)?)
|
||||||
let localname = str::from_utf8(e.local_name().into_inner())?;
|
}
|
||||||
|
let prefix = converted_prefix;
|
||||||
|
|
||||||
let mut namespaces = local_namespaces.clone();
|
let localname = str::from_utf8(e.local_name().into_inner())?.to_owned();
|
||||||
|
|
||||||
|
let mut local_namespaces = local_namespaces.clone();
|
||||||
let mut namespace_declarations = BTreeMap::new();
|
let mut namespace_declarations = BTreeMap::new();
|
||||||
let attributes = BTreeMap::new();
|
let attributes = BTreeMap::new();
|
||||||
|
|
||||||
|
@ -365,49 +441,56 @@ impl<'s> Node<'s> {
|
||||||
match prefix_declaration {
|
match prefix_declaration {
|
||||||
PrefixDeclaration::Default => {
|
PrefixDeclaration::Default => {
|
||||||
let value = str::from_utf8(attribute.value.as_ref())?;
|
let value = str::from_utf8(attribute.value.as_ref())?;
|
||||||
namespace_declarations.try_insert(None, value);
|
if let Some(_) = namespace_declarations.insert(None, value) {
|
||||||
namespaces.insert(None, value);
|
return Err(ElementParseError::DuplicateAttribute.into());
|
||||||
|
};
|
||||||
|
local_namespaces.insert(None, value);
|
||||||
}
|
}
|
||||||
PrefixDeclaration::Named(prefix) => {
|
PrefixDeclaration::Named(prefix) => {
|
||||||
let key = str::from_utf8(prefix)?;
|
let key = str::from_utf8(prefix)?;
|
||||||
let value = str::from_utf8(attribute.value.as_ref())?;
|
let value = str::from_utf8(attribute.value.as_ref())?;
|
||||||
namespace_declarations
|
if let Some(_) = namespace_declarations.insert(Some(key), value) {
|
||||||
.try_insert(Some(key), value)
|
return Err(ElementParseError::DuplicateAttribute.into());
|
||||||
.map_err(ParseError::DuplicateAttribute)?;
|
};
|
||||||
namespaces.insert(Some(key), value);
|
local_namespaces.insert(Some(key), value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
attributes
|
if let Some(_) = attributes.insert(
|
||||||
.try_insert(
|
|
||||||
str::from_utf8(attribute.key.into_inner())?,
|
str::from_utf8(attribute.key.into_inner())?,
|
||||||
str::from_utf8(attribute.value.as_ref())?,
|
str::from_utf8(attribute.value.as_ref())?,
|
||||||
)
|
) {
|
||||||
.map_err(ParseError::DuplicateAttribute)?;
|
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 {
|
Ok(Some(Self::Element(Element {
|
||||||
prefix,
|
prefix,
|
||||||
localname,
|
localname,
|
||||||
namespace,
|
namespace,
|
||||||
namespace_declarations,
|
namespace_declarations: Box::new(namespace_declarations),
|
||||||
attributes,
|
attributes: Box::new(attributes),
|
||||||
children,
|
children: Box::new(children),
|
||||||
})))
|
})))
|
||||||
}
|
}
|
||||||
Event::Start(e) => {
|
Event::Start(e) => {
|
||||||
let prefix = e
|
let prefix = e.name().prefix().map(|prefix| prefix.into_inner());
|
||||||
.name()
|
let converted_prefix;
|
||||||
.prefix()
|
if let Some(raw_prefix) = prefix {
|
||||||
.map(|prefix| str::from_utf8(prefix.into_inner())?);
|
converted_prefix = Some(str::from_utf8(raw_prefix)?)
|
||||||
let localname = str::from_utf8(e.local_name().into_inner())?;
|
}
|
||||||
|
let prefix = converted_prefix;
|
||||||
|
|
||||||
let mut namespaces = local_namespaces.clone();
|
let localname = str::from_utf8(e.local_name().into_inner())?.to_owned();
|
||||||
|
|
||||||
|
let mut local_namespaces = local_namespaces.clone();
|
||||||
let mut namespace_declarations = BTreeMap::new();
|
let mut namespace_declarations = BTreeMap::new();
|
||||||
let attributes = BTreeMap::new();
|
let attributes = BTreeMap::new();
|
||||||
|
|
||||||
|
@ -417,92 +500,82 @@ impl<'s> Node<'s> {
|
||||||
match prefix_declaration {
|
match prefix_declaration {
|
||||||
PrefixDeclaration::Default => {
|
PrefixDeclaration::Default => {
|
||||||
let value = str::from_utf8(attribute.value.as_ref())?;
|
let value = str::from_utf8(attribute.value.as_ref())?;
|
||||||
namespace_declarations.try_insert(None, value);
|
if let Some(_) = namespace_declarations.insert(None, value) {
|
||||||
namespaces.insert(None, value);
|
return Err(ElementParseError::DuplicateAttribute.into());
|
||||||
|
};
|
||||||
|
local_namespaces.insert(None, value);
|
||||||
}
|
}
|
||||||
PrefixDeclaration::Named(prefix) => {
|
PrefixDeclaration::Named(prefix) => {
|
||||||
let key = str::from_utf8(prefix)?;
|
let key = str::from_utf8(prefix)?;
|
||||||
let value = str::from_utf8(attribute.value.as_ref())?;
|
let value = str::from_utf8(attribute.value.as_ref())?;
|
||||||
namespace_declarations
|
if let Some(_) = namespace_declarations.insert(Some(key), value) {
|
||||||
.try_insert(Some(key), value)
|
return Err(ElementParseError::DuplicateAttribute.into());
|
||||||
.map_err(ParseError::DuplicateAttribute)?;
|
};
|
||||||
namespaces.insert(Some(key), value);
|
local_namespaces.insert(Some(key), value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
attributes
|
if let Some(_) = attributes.insert(
|
||||||
.try_insert(
|
|
||||||
str::from_utf8(attribute.key.into_inner())?,
|
str::from_utf8(attribute.key.into_inner())?,
|
||||||
str::from_utf8(attribute.value.as_ref())?,
|
str::from_utf8(attribute.value.as_ref())?,
|
||||||
)
|
) {
|
||||||
.map_err(ParseError::DuplicateAttribute)?;
|
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();
|
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)
|
children.push(child_node)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut children = Vec::new();
|
||||||
|
|
||||||
Ok(Some(Self::Element(Element {
|
Ok(Some(Self::Element(Element {
|
||||||
prefix,
|
prefix,
|
||||||
localname,
|
localname,
|
||||||
namespace,
|
namespace,
|
||||||
namespace_declarations,
|
namespace_declarations: Box::new(namespace_declarations),
|
||||||
attributes,
|
attributes: Box::new(attributes),
|
||||||
children,
|
children: Box::new(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().to_string()))),
|
||||||
e => Ok(Some(Self::Unknown)),
|
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]
|
// the issue is i don't know how to validate that an element always has a namespace when it is being written
|
||||||
// pub async fn read_start<R: AsyncBufRead + Unpin + Send>(
|
// TODO: ElementBuilder that makes it easier to build an element under a namespace
|
||||||
// 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(),
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum ElementError<'e> {
|
pub enum ElementError<'e> {
|
||||||
NotAStart(Event<'e>),
|
NotAStart(Event<'e>),
|
||||||
NotText,
|
NotText,
|
||||||
NoChildren,
|
NoChildren,
|
||||||
|
NamespaceNotQualified,
|
||||||
MultipleChildren,
|
MultipleChildren,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum ParseError {
|
pub enum ElementParseError {
|
||||||
DuplicateAttribute,
|
DuplicateAttribute,
|
||||||
NoNamespace,
|
NoNamespace,
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue