Compare commits
No commits in common. "caf8b7506e1fb1ccd8e3f43c897a02db90397dde" and "4c235b972e2400bd2bb92b74b12558b485dc7142" have entirely different histories.
caf8b7506e
...
4c235b972e
|
@ -10,7 +10,7 @@ use crate::{
|
||||||
// when are namespaces names chosen then if they are automatically calculated
|
// when are namespaces names chosen then if they are automatically calculated
|
||||||
// namespaces are held by readers and writers.
|
// namespaces are held by readers and writers.
|
||||||
#[derive(PartialEq, Eq, Hash, Clone, Debug)]
|
#[derive(PartialEq, Eq, Hash, Clone, Debug)]
|
||||||
pub struct NamespaceDeclaration {
|
pub struct Namespace {
|
||||||
pub prefix: Option<String>,
|
pub prefix: Option<String>,
|
||||||
pub namespace: String,
|
pub namespace: String,
|
||||||
}
|
}
|
||||||
|
@ -18,8 +18,8 @@ pub struct NamespaceDeclaration {
|
||||||
// names are qualified, they contain a reference to the namespace (held within the reader/writer)
|
// names are qualified, they contain a reference to the namespace (held within the reader/writer)
|
||||||
#[derive(PartialEq, Eq, Hash, Clone, Debug)]
|
#[derive(PartialEq, Eq, Hash, Clone, Debug)]
|
||||||
pub struct Name {
|
pub struct Name {
|
||||||
pub namespace: String,
|
pub namespace: Namespace,
|
||||||
pub local_name: String,
|
pub name: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -40,7 +40,7 @@ pub struct Element {
|
||||||
// namespace: String,
|
// namespace: String,
|
||||||
// hashmap of explicit namespace declarations on the element itself only
|
// hashmap of explicit namespace declarations on the element itself only
|
||||||
// possibly not needed as can be calculated at write time depending on context and qualified namespace, and for reading, element validity and namespaces are kept track of by the reader.
|
// possibly not needed as can be calculated at write time depending on context and qualified namespace, and for reading, element validity and namespaces are kept track of by the reader.
|
||||||
pub namespace_declarations: HashSet<NamespaceDeclaration>,
|
pub namespace_decl: HashSet<Namespace>,
|
||||||
// attributes can be in a different namespace than the element. how to make sure they are valid?
|
// attributes can be in a different namespace than the element. how to make sure they are valid?
|
||||||
// maybe include the namespace instead of or with the prefix
|
// maybe include the namespace instead of or with the prefix
|
||||||
// you can calculate the prefix from the namespaced name and the current writer context
|
// you can calculate the prefix from the namespaced name and the current writer context
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use std::{num::ParseIntError, str::Utf8Error};
|
use std::{num::ParseIntError, str::Utf8Error};
|
||||||
|
|
||||||
use crate::element::{Name, NamespaceDeclaration};
|
use crate::element::{Name, Namespace};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
|
@ -10,12 +10,11 @@ pub enum Error {
|
||||||
EntityProcessError(String),
|
EntityProcessError(String),
|
||||||
// TODO: better choice for failures than string
|
// TODO: better choice for failures than string
|
||||||
InvalidCharRef(String),
|
InvalidCharRef(String),
|
||||||
DuplicateNameSpaceDeclaration(NamespaceDeclaration),
|
DuplicateNameSpace(Namespace),
|
||||||
DuplicateAttribute(String),
|
DuplicateAttribute(String),
|
||||||
UnqualifiedNamespace(String),
|
UnqualifiedNamespace(String),
|
||||||
MismatchedEndTag(Name, Name),
|
MismatchedEndTag(String, String),
|
||||||
NotInElement(String),
|
NotInElement(String),
|
||||||
ExtraData(String),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<std::io::Error> for Error {
|
impl From<std::io::Error> for Error {
|
||||||
|
|
483
src/reader.rs
483
src/reader.rs
|
@ -13,7 +13,7 @@ use tokio::io::{AsyncBufRead, AsyncBufReadExt, AsyncRead, AsyncReadExt};
|
||||||
static MAX_STANZA_SIZE: usize = 65536;
|
static MAX_STANZA_SIZE: usize = 65536;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
element::{Content, Element, Name, NamespaceDeclaration},
|
element::{Content, Element, Name, Namespace},
|
||||||
error::Error,
|
error::Error,
|
||||||
xml::{self, parsers::Parser},
|
xml::{self, parsers::Parser},
|
||||||
Result,
|
Result,
|
||||||
|
@ -26,7 +26,7 @@ pub struct Reader<R> {
|
||||||
// holds which tags we are in atm over depth
|
// holds which tags we are in atm over depth
|
||||||
// to have names reference namespaces could
|
// to have names reference namespaces could
|
||||||
depth: Vec<Name>,
|
depth: Vec<Name>,
|
||||||
namespace_declarations: Vec<HashSet<NamespaceDeclaration>>,
|
namespaces: Vec<HashSet<Namespace>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<R> Reader<R> {
|
impl<R> Reader<R> {
|
||||||
|
@ -35,7 +35,7 @@ impl<R> Reader<R> {
|
||||||
inner: reader,
|
inner: reader,
|
||||||
buffer: Buffer::with_capacity(MAX_STANZA_SIZE),
|
buffer: Buffer::with_capacity(MAX_STANZA_SIZE),
|
||||||
depth: Vec::new(),
|
depth: Vec::new(),
|
||||||
namespace_declarations: Vec::new(),
|
namespaces: Vec::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -75,11 +75,8 @@ where
|
||||||
match xml::STag::parse(input) {
|
match xml::STag::parse(input) {
|
||||||
Ok((rest, e)) => {
|
Ok((rest, e)) => {
|
||||||
let len = self.buffer.available_data() - rest.as_bytes().len();
|
let len = self.buffer.available_data() - rest.as_bytes().len();
|
||||||
let element = Reader::<R>::start_tag_from_xml(
|
let element =
|
||||||
&mut self.depth,
|
Reader::<R>::start_tag_from_xml(&mut self.depth, &mut self.namespaces, e)?;
|
||||||
&mut self.namespace_declarations,
|
|
||||||
e,
|
|
||||||
)?;
|
|
||||||
self.buffer.consume(len);
|
self.buffer.consume(len);
|
||||||
return Ok(element);
|
return Ok(element);
|
||||||
}
|
}
|
||||||
|
@ -100,11 +97,7 @@ where
|
||||||
match xml::ETag::parse(input) {
|
match xml::ETag::parse(input) {
|
||||||
Ok((rest, e)) => {
|
Ok((rest, e)) => {
|
||||||
let len = self.buffer.available_data() - rest.as_bytes().len();
|
let len = self.buffer.available_data() - rest.as_bytes().len();
|
||||||
Reader::<R>::end_tag_from_xml(
|
Reader::<R>::end_tag_from_xml(&mut self.depth, &mut self.namespaces, e)?;
|
||||||
&mut self.depth,
|
|
||||||
&mut self.namespace_declarations,
|
|
||||||
e,
|
|
||||||
)?;
|
|
||||||
self.buffer.consume(len);
|
self.buffer.consume(len);
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
@ -125,8 +118,7 @@ where
|
||||||
match xml::Element::parse(input) {
|
match xml::Element::parse(input) {
|
||||||
Ok((rest, e)) => {
|
Ok((rest, e)) => {
|
||||||
let len = self.buffer.available_data() - rest.as_bytes().len();
|
let len = self.buffer.available_data() - rest.as_bytes().len();
|
||||||
let element =
|
let element = Reader::<R>::element_from_xml(&mut self.namespaces, e)?;
|
||||||
Reader::<R>::element_from_xml(&mut self.namespace_declarations, e)?;
|
|
||||||
self.buffer.consume(len);
|
self.buffer.consume(len);
|
||||||
return Ok(element);
|
return Ok(element);
|
||||||
}
|
}
|
||||||
|
@ -164,10 +156,8 @@ where
|
||||||
} else {
|
} else {
|
||||||
let len =
|
let len =
|
||||||
self.buffer.available_data() - rest.as_bytes().len();
|
self.buffer.available_data() - rest.as_bytes().len();
|
||||||
let element = Self::element_from_xml(
|
let element =
|
||||||
&mut self.namespace_declarations,
|
Self::element_from_xml(&mut self.namespaces, element)?;
|
||||||
element,
|
|
||||||
)?;
|
|
||||||
self.buffer.consume(len);
|
self.buffer.consume(len);
|
||||||
return Ok(Content::Element(element));
|
return Ok(Content::Element(element));
|
||||||
}
|
}
|
||||||
|
@ -219,15 +209,12 @@ where
|
||||||
match xml::ContentItem::parse(input) {
|
match xml::ContentItem::parse(input) {
|
||||||
Ok((rest, content_item)) => match content_item {
|
Ok((rest, content_item)) => match content_item {
|
||||||
xml::ContentItem::Element(element) => {
|
xml::ContentItem::Element(element) => {
|
||||||
// text can still be empty
|
|
||||||
if !text.is_empty() {
|
if !text.is_empty() {
|
||||||
return Ok(Content::Text(text));
|
return Ok(Content::Text(text));
|
||||||
} else {
|
} else {
|
||||||
let len = self.buffer.available_data() - rest.as_bytes().len();
|
let len = self.buffer.available_data() - rest.as_bytes().len();
|
||||||
let element = Self::element_from_xml(
|
let element =
|
||||||
&mut self.namespace_declarations,
|
Self::element_from_xml(&mut self.namespaces, element)?;
|
||||||
element,
|
|
||||||
)?;
|
|
||||||
self.buffer.consume(len);
|
self.buffer.consume(len);
|
||||||
return Ok(Content::Element(element));
|
return Ok(Content::Element(element));
|
||||||
}
|
}
|
||||||
|
@ -277,12 +264,10 @@ where
|
||||||
impl<R> Reader<R> {
|
impl<R> Reader<R> {
|
||||||
fn start_tag_from_xml(
|
fn start_tag_from_xml(
|
||||||
depth: &mut Vec<Name>,
|
depth: &mut Vec<Name>,
|
||||||
namespace_declarations: &mut Vec<HashSet<NamespaceDeclaration>>,
|
namespaces: &mut Vec<HashSet<Namespace>>,
|
||||||
s_tag: xml::STag,
|
s_tag: xml::STag,
|
||||||
) -> Result<Element> {
|
) -> Result<Element> {
|
||||||
// namespace declarations on element
|
let mut namespace_declarations = HashSet::new();
|
||||||
|
|
||||||
let mut element_namespace_declarations = HashSet::new();
|
|
||||||
for (prefix, namespace) in s_tag.attributes.iter().filter_map(|attribute| {
|
for (prefix, namespace) in s_tag.attributes.iter().filter_map(|attribute| {
|
||||||
if let xml::Attribute::NamespaceDeclaration { ns_name, value } = attribute {
|
if let xml::Attribute::NamespaceDeclaration { ns_name, value } = attribute {
|
||||||
Some((ns_name, value))
|
Some((ns_name, value))
|
||||||
|
@ -296,53 +281,24 @@ impl<R> Reader<R> {
|
||||||
}
|
}
|
||||||
xml::NSAttName::DefaultAttName => None,
|
xml::NSAttName::DefaultAttName => None,
|
||||||
};
|
};
|
||||||
let namespace = NamespaceDeclaration {
|
let namespace = Namespace {
|
||||||
prefix,
|
prefix,
|
||||||
namespace: namespace.process()?,
|
namespace: namespace.process()?,
|
||||||
};
|
};
|
||||||
if !element_namespace_declarations.insert(namespace.clone()) {
|
if !namespace_declarations.insert(namespace.clone()) {
|
||||||
return Err(Error::DuplicateNameSpaceDeclaration(namespace));
|
return Err(Error::DuplicateNameSpace(namespace));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// all namespaces available in the element scope (from both parent elements and element itself)
|
// all namespaces available to the element (from both parent elements and element itself)
|
||||||
let namespace_declarations_stack: Vec<&NamespaceDeclaration> = namespace_declarations
|
let namespace_stack: Vec<&Namespace> = namespaces
|
||||||
.iter()
|
.iter()
|
||||||
.flatten()
|
.flatten()
|
||||||
.chain(element_namespace_declarations.iter())
|
.chain(namespace_declarations.iter())
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
// element name and default attribute namespace
|
|
||||||
|
|
||||||
let element_namespace_declaration;
|
|
||||||
let element_local_name = s_tag.name.local_part().to_string();
|
|
||||||
|
|
||||||
match s_tag.name.prefix() {
|
|
||||||
Some(prefix) => {
|
|
||||||
element_namespace_declaration = namespace_declarations_stack
|
|
||||||
.iter()
|
|
||||||
.rfind(|namespace| namespace.prefix.as_deref() == Some(prefix));
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
element_namespace_declaration = namespace_declarations_stack
|
|
||||||
.iter()
|
|
||||||
.rfind(|namespace| namespace.prefix == None);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let element_default_namespace = element_namespace_declaration
|
|
||||||
.ok_or_else(|| Error::UnqualifiedNamespace(s_tag.name.to_string()))?
|
|
||||||
.namespace
|
|
||||||
.clone();
|
|
||||||
|
|
||||||
let element_name = Name {
|
|
||||||
namespace: element_default_namespace,
|
|
||||||
local_name: element_local_name,
|
|
||||||
};
|
|
||||||
|
|
||||||
// attributes
|
|
||||||
|
|
||||||
let mut attributes = HashMap::new();
|
let mut attributes = HashMap::new();
|
||||||
|
|
||||||
for (q_name, value) in s_tag.attributes.iter().filter_map(|attribute| {
|
for (q_name, value) in s_tag.attributes.iter().filter_map(|attribute| {
|
||||||
if let xml::Attribute::Attribute { name, value } = attribute {
|
if let xml::Attribute::Attribute { name, value } = attribute {
|
||||||
Some((name, value))
|
Some((name, value))
|
||||||
|
@ -350,26 +306,29 @@ impl<R> Reader<R> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}) {
|
}) {
|
||||||
let attribute_namespace_declaration;
|
let namespace;
|
||||||
let attribute_local_name = q_name.local_part().to_string();
|
let attribute_name;
|
||||||
match q_name.prefix() {
|
match q_name {
|
||||||
Some(prefix) => {
|
xml::QName::PrefixedName(prefixed_name) => {
|
||||||
attribute_namespace_declaration =
|
namespace = namespace_stack.iter().rfind(|namespace| {
|
||||||
namespace_declarations_stack
|
namespace.prefix.as_deref() == Some(**prefixed_name.prefix)
|
||||||
.iter()
|
|
||||||
.rfind(|namespace_declaration| {
|
|
||||||
namespace_declaration.prefix.as_deref() == Some(prefix)
|
|
||||||
});
|
});
|
||||||
|
attribute_name = prefixed_name.local_part.to_string();
|
||||||
}
|
}
|
||||||
None => attribute_namespace_declaration = element_namespace_declaration,
|
xml::QName::UnprefixedName(unprefixed_name) => {
|
||||||
|
namespace = namespace_stack
|
||||||
|
.iter()
|
||||||
|
.rfind(|namespace| namespace.prefix == None);
|
||||||
|
attribute_name = unprefixed_name.to_string();
|
||||||
}
|
}
|
||||||
if let Some(namespace_declaration) = attribute_namespace_declaration {
|
}
|
||||||
|
if let Some(namespace) = namespace {
|
||||||
|
let namespace = (*namespace).clone();
|
||||||
let name = Name {
|
let name = Name {
|
||||||
namespace: namespace_declaration.namespace.clone(),
|
namespace,
|
||||||
local_name: attribute_local_name,
|
name: attribute_name,
|
||||||
};
|
};
|
||||||
let value = value.process()?;
|
let value = value.process()?;
|
||||||
// check for duplicate attribute
|
|
||||||
if let Some(_value) = attributes.insert(name, value) {
|
if let Some(_value) = attributes.insert(name, value) {
|
||||||
return Err(Error::DuplicateAttribute(q_name.to_string()));
|
return Err(Error::DuplicateAttribute(q_name.to_string()));
|
||||||
}
|
}
|
||||||
|
@ -378,13 +337,36 @@ impl<R> Reader<R> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
depth.push(element_name.clone());
|
let name;
|
||||||
|
let namespace;
|
||||||
|
match &s_tag.name {
|
||||||
|
xml::QName::PrefixedName(prefixed_name) => {
|
||||||
|
namespace = namespace_stack
|
||||||
|
.iter()
|
||||||
|
.rfind(|namespace| namespace.prefix.as_deref() == Some(**prefixed_name.prefix));
|
||||||
|
name = prefixed_name.local_part.to_string();
|
||||||
|
}
|
||||||
|
xml::QName::UnprefixedName(unprefixed_name) => {
|
||||||
|
namespace = namespace_stack
|
||||||
|
.iter()
|
||||||
|
.rfind(|namespace| namespace.prefix == None);
|
||||||
|
name = unprefixed_name.to_string();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
namespace_declarations.push(element_namespace_declarations.clone());
|
let namespace = (*namespace
|
||||||
|
.ok_or_else(|| Error::UnqualifiedNamespace(s_tag.name.to_string()))?)
|
||||||
|
.clone();
|
||||||
|
|
||||||
|
let name = Name { namespace, name };
|
||||||
|
|
||||||
|
depth.push(name.clone());
|
||||||
|
|
||||||
|
namespaces.push(namespace_declarations.clone());
|
||||||
|
|
||||||
return Ok(Element {
|
return Ok(Element {
|
||||||
name: element_name,
|
name,
|
||||||
namespace_declarations: element_namespace_declarations,
|
namespace_decl: namespace_declarations,
|
||||||
attributes,
|
attributes,
|
||||||
content: Vec::new(),
|
content: Vec::new(),
|
||||||
});
|
});
|
||||||
|
@ -392,80 +374,143 @@ impl<R> Reader<R> {
|
||||||
|
|
||||||
fn end_tag_from_xml(
|
fn end_tag_from_xml(
|
||||||
depth: &mut Vec<Name>,
|
depth: &mut Vec<Name>,
|
||||||
namespace_declarations: &mut Vec<HashSet<NamespaceDeclaration>>,
|
namespaces: &mut Vec<HashSet<Namespace>>,
|
||||||
xml_e_tag: xml::ETag,
|
e_tag: xml::ETag,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
if let Some(s_tag_name) = depth.pop() {
|
if let Some(s_tag_name) = depth.pop() {
|
||||||
let e_tag_namespace_declaration;
|
if s_tag_name.namespace.prefix.as_deref() == e_tag.name.prefix()
|
||||||
let e_tag_local_name = xml_e_tag.name.local_part().to_string();
|
&& s_tag_name.name == e_tag.name.local_part()
|
||||||
let namespace_declarations_stack: Vec<_> =
|
{
|
||||||
namespace_declarations.iter().flatten().collect();
|
namespaces.pop();
|
||||||
|
|
||||||
match xml_e_tag.name.prefix() {
|
|
||||||
Some(prefix) => {
|
|
||||||
e_tag_namespace_declaration = namespace_declarations_stack
|
|
||||||
.iter()
|
|
||||||
.rfind(|namespace| namespace.prefix.as_deref() == Some(prefix));
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
e_tag_namespace_declaration = namespace_declarations_stack
|
|
||||||
.iter()
|
|
||||||
.rfind(|namespace| namespace.prefix == None);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let e_tag_namespace = e_tag_namespace_declaration
|
|
||||||
.ok_or_else(|| Error::UnqualifiedNamespace(xml_e_tag.name.to_string()))?
|
|
||||||
.namespace
|
|
||||||
.clone();
|
|
||||||
|
|
||||||
let e_tag_name = Name {
|
|
||||||
namespace: e_tag_namespace,
|
|
||||||
local_name: e_tag_local_name,
|
|
||||||
};
|
|
||||||
|
|
||||||
if e_tag_name != s_tag_name {
|
|
||||||
return Err(Error::MismatchedEndTag(s_tag_name, e_tag_name));
|
|
||||||
}
|
|
||||||
if s_tag_name == e_tag_name {
|
|
||||||
namespace_declarations.pop();
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
} else {
|
} else {
|
||||||
return Err(Error::MismatchedEndTag(s_tag_name, e_tag_name));
|
return Err(Error::MismatchedEndTag(
|
||||||
|
s_tag_name.name,
|
||||||
|
e_tag.name.to_string(),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return Err(Error::NotInElement(xml_e_tag.name.to_string()));
|
return Err(Error::NotInElement(e_tag.name.to_string()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn element_from_xml(
|
fn element_from_xml(
|
||||||
namespace_declarations: &mut Vec<HashSet<NamespaceDeclaration>>,
|
namespaces: &mut Vec<HashSet<Namespace>>,
|
||||||
element: xml::Element,
|
element: xml::Element,
|
||||||
) -> Result<Element> {
|
) -> Result<Element> {
|
||||||
let xml_name;
|
|
||||||
let xml_attributes;
|
|
||||||
let xml_content;
|
|
||||||
let xml_e_name;
|
|
||||||
|
|
||||||
match element {
|
match element {
|
||||||
xml::Element::Empty(empty_elem_tag) => {
|
xml::Element::Empty(empty_elem_tag) => {
|
||||||
xml_name = empty_elem_tag.name;
|
let mut namespace_declarations = HashSet::new();
|
||||||
xml_attributes = empty_elem_tag.attributes;
|
for (prefix, namespace) in
|
||||||
xml_content = None;
|
empty_elem_tag.attributes.iter().filter_map(|attribute| {
|
||||||
xml_e_name = None;
|
if let xml::Attribute::NamespaceDeclaration { ns_name, value } = attribute {
|
||||||
|
Some((ns_name, value))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
{
|
||||||
|
let prefix = match prefix {
|
||||||
|
xml::NSAttName::PrefixedAttName(prefixed_att_name) => {
|
||||||
|
Some(prefixed_att_name.to_string())
|
||||||
|
}
|
||||||
|
xml::NSAttName::DefaultAttName => None,
|
||||||
|
};
|
||||||
|
let namespace = Namespace {
|
||||||
|
prefix,
|
||||||
|
namespace: namespace.process()?,
|
||||||
|
};
|
||||||
|
if !namespace_declarations.insert(namespace.clone()) {
|
||||||
|
return Err(Error::DuplicateNameSpace(namespace));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// all namespaces available to the element (from both parent elements and element itself)
|
||||||
|
let namespace_stack: Vec<&Namespace> = namespaces
|
||||||
|
.iter()
|
||||||
|
.flatten()
|
||||||
|
.chain(namespace_declarations.iter())
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let mut attributes = HashMap::new();
|
||||||
|
|
||||||
|
for (q_name, value) in empty_elem_tag.attributes.iter().filter_map(|attribute| {
|
||||||
|
if let xml::Attribute::Attribute { name, value } = attribute {
|
||||||
|
Some((name, value))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}) {
|
||||||
|
let namespace;
|
||||||
|
let attribute_name;
|
||||||
|
match q_name {
|
||||||
|
xml::QName::PrefixedName(prefixed_name) => {
|
||||||
|
namespace = namespace_stack.iter().rfind(|namespace| {
|
||||||
|
namespace.prefix.as_deref() == Some(**prefixed_name.prefix)
|
||||||
|
});
|
||||||
|
attribute_name = prefixed_name.local_part.to_string();
|
||||||
|
}
|
||||||
|
xml::QName::UnprefixedName(unprefixed_name) => {
|
||||||
|
namespace = namespace_stack
|
||||||
|
.iter()
|
||||||
|
.rfind(|namespace| namespace.prefix == None);
|
||||||
|
attribute_name = unprefixed_name.to_string();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let Some(namespace) = namespace {
|
||||||
|
let namespace = (*namespace).clone();
|
||||||
|
let name = Name {
|
||||||
|
namespace,
|
||||||
|
name: attribute_name,
|
||||||
|
};
|
||||||
|
let value = value.process()?;
|
||||||
|
if let Some(_value) = attributes.insert(name, value) {
|
||||||
|
return Err(Error::DuplicateAttribute(q_name.to_string()));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return Err(Error::UnqualifiedNamespace(q_name.to_string()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let name;
|
||||||
|
let namespace;
|
||||||
|
match &empty_elem_tag.name {
|
||||||
|
xml::QName::PrefixedName(prefixed_name) => {
|
||||||
|
namespace = namespace_stack.iter().rfind(|namespace| {
|
||||||
|
namespace.prefix.as_deref() == Some(**prefixed_name.prefix)
|
||||||
|
});
|
||||||
|
name = prefixed_name.local_part.to_string();
|
||||||
|
}
|
||||||
|
xml::QName::UnprefixedName(unprefixed_name) => {
|
||||||
|
namespace = namespace_stack
|
||||||
|
.iter()
|
||||||
|
.rfind(|namespace| namespace.prefix == None);
|
||||||
|
name = unprefixed_name.to_string();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let namespace = (*namespace
|
||||||
|
.ok_or_else(|| Error::UnqualifiedNamespace(empty_elem_tag.name.to_string()))?)
|
||||||
|
.clone();
|
||||||
|
|
||||||
|
let name = Name { namespace, name };
|
||||||
|
|
||||||
|
return Ok(Element {
|
||||||
|
name,
|
||||||
|
namespace_decl: namespace_declarations,
|
||||||
|
attributes,
|
||||||
|
content: Vec::new(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
xml::Element::NotEmpty(s_tag, content, e_tag) => {
|
xml::Element::NotEmpty(s_tag, content, e_tag) => {
|
||||||
xml_name = s_tag.name;
|
if s_tag.name != e_tag.name {
|
||||||
xml_attributes = s_tag.attributes;
|
return Err(Error::MismatchedEndTag(
|
||||||
xml_content = Some(content);
|
s_tag.name.to_string(),
|
||||||
xml_e_name = Some(e_tag.name);
|
e_tag.name.to_string(),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
let mut namespace_declarations = HashSet::new();
|
||||||
|
for (prefix, namespace) in s_tag.attributes.iter().filter_map(|attribute| {
|
||||||
// namespace declarations on element
|
|
||||||
|
|
||||||
let mut element_namespace_declarations = HashSet::new();
|
|
||||||
for (prefix, namespace) in xml_attributes.iter().filter_map(|attribute| {
|
|
||||||
if let xml::Attribute::NamespaceDeclaration { ns_name, value } = attribute {
|
if let xml::Attribute::NamespaceDeclaration { ns_name, value } = attribute {
|
||||||
Some((ns_name, value))
|
Some((ns_name, value))
|
||||||
} else {
|
} else {
|
||||||
|
@ -478,114 +523,54 @@ impl<R> Reader<R> {
|
||||||
}
|
}
|
||||||
xml::NSAttName::DefaultAttName => None,
|
xml::NSAttName::DefaultAttName => None,
|
||||||
};
|
};
|
||||||
let namespace = NamespaceDeclaration {
|
let namespace = Namespace {
|
||||||
prefix,
|
prefix,
|
||||||
namespace: namespace.process()?,
|
namespace: namespace.process()?,
|
||||||
};
|
};
|
||||||
if !element_namespace_declarations.insert(namespace.clone()) {
|
if !namespace_declarations.insert(namespace.clone()) {
|
||||||
return Err(Error::DuplicateNameSpaceDeclaration(namespace));
|
return Err(Error::DuplicateNameSpace(namespace));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// all namespaces available in the element scope (from both parent elements and element itself)
|
// all namespaces available to the element (from both parent elements and element itself)
|
||||||
let namespace_declarations_stack: Vec<&NamespaceDeclaration> = namespace_declarations
|
let namespace_stack: Vec<&Namespace> = namespaces
|
||||||
.iter()
|
.iter()
|
||||||
.flatten()
|
.flatten()
|
||||||
.chain(element_namespace_declarations.iter())
|
.chain(namespace_declarations.iter())
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
// element name and default attribute namespace
|
|
||||||
|
|
||||||
let element_namespace_declaration;
|
|
||||||
let element_local_name = xml_name.local_part().to_string();
|
|
||||||
|
|
||||||
match xml_name.prefix() {
|
|
||||||
Some(prefix) => {
|
|
||||||
element_namespace_declaration = namespace_declarations_stack
|
|
||||||
.iter()
|
|
||||||
.rfind(|namespace| namespace.prefix.as_deref() == Some(prefix));
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
element_namespace_declaration = namespace_declarations_stack
|
|
||||||
.iter()
|
|
||||||
.rfind(|namespace| namespace.prefix == None);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let element_default_namespace = element_namespace_declaration
|
|
||||||
.ok_or_else(|| Error::UnqualifiedNamespace(xml_name.to_string()))?
|
|
||||||
.namespace
|
|
||||||
.clone();
|
|
||||||
|
|
||||||
let element_name = Name {
|
|
||||||
namespace: element_default_namespace,
|
|
||||||
local_name: element_local_name,
|
|
||||||
};
|
|
||||||
|
|
||||||
// end tag name match check
|
|
||||||
|
|
||||||
if let Some(xml_e_name) = xml_e_name {
|
|
||||||
let e_tag_namespace_declaration;
|
|
||||||
let e_tag_local_name = xml_e_name.local_part().to_string();
|
|
||||||
|
|
||||||
match xml_e_name.prefix() {
|
|
||||||
Some(prefix) => {
|
|
||||||
e_tag_namespace_declaration = namespace_declarations_stack
|
|
||||||
.iter()
|
|
||||||
.rfind(|namespace| namespace.prefix.as_deref() == Some(prefix));
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
e_tag_namespace_declaration = namespace_declarations_stack
|
|
||||||
.iter()
|
|
||||||
.rfind(|namespace| namespace.prefix == None);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let e_tag_namespace = e_tag_namespace_declaration
|
|
||||||
.ok_or_else(|| Error::UnqualifiedNamespace(xml_name.to_string()))?
|
|
||||||
.namespace
|
|
||||||
.clone();
|
|
||||||
|
|
||||||
let e_tag_name = Name {
|
|
||||||
namespace: e_tag_namespace,
|
|
||||||
local_name: e_tag_local_name,
|
|
||||||
};
|
|
||||||
|
|
||||||
if e_tag_name != element_name {
|
|
||||||
return Err(Error::MismatchedEndTag(element_name, e_tag_name));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// attributes
|
|
||||||
|
|
||||||
let mut attributes = HashMap::new();
|
let mut attributes = HashMap::new();
|
||||||
for (q_name, value) in xml_attributes.iter().filter_map(|attribute| {
|
|
||||||
|
for (q_name, value) in s_tag.attributes.iter().filter_map(|attribute| {
|
||||||
if let xml::Attribute::Attribute { name, value } = attribute {
|
if let xml::Attribute::Attribute { name, value } = attribute {
|
||||||
Some((name, value))
|
Some((name, value))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}) {
|
}) {
|
||||||
let attribute_namespace_declaration;
|
let namespace;
|
||||||
let attribute_local_name = q_name.local_part().to_string();
|
let attribute_name;
|
||||||
match q_name.prefix() {
|
match q_name {
|
||||||
Some(prefix) => {
|
xml::QName::PrefixedName(prefixed_name) => {
|
||||||
attribute_namespace_declaration =
|
namespace = namespace_stack.iter().rfind(|namespace| {
|
||||||
namespace_declarations_stack
|
namespace.prefix.as_deref() == Some(**prefixed_name.prefix)
|
||||||
.iter()
|
|
||||||
.rfind(|namespace_declaration| {
|
|
||||||
namespace_declaration.prefix.as_deref() == Some(prefix)
|
|
||||||
});
|
});
|
||||||
|
attribute_name = prefixed_name.local_part.to_string();
|
||||||
}
|
}
|
||||||
None => attribute_namespace_declaration = element_namespace_declaration,
|
xml::QName::UnprefixedName(unprefixed_name) => {
|
||||||
|
namespace = namespace_stack
|
||||||
|
.iter()
|
||||||
|
.rfind(|namespace| namespace.prefix == None);
|
||||||
|
attribute_name = unprefixed_name.to_string();
|
||||||
}
|
}
|
||||||
if let Some(namespace_declaration) = attribute_namespace_declaration {
|
}
|
||||||
|
if let Some(namespace) = namespace {
|
||||||
|
let namespace = (*namespace).clone();
|
||||||
let name = Name {
|
let name = Name {
|
||||||
namespace: namespace_declaration.namespace.clone(),
|
namespace,
|
||||||
local_name: attribute_local_name,
|
name: attribute_name,
|
||||||
};
|
};
|
||||||
let value = value.process()?;
|
let value = value.process()?;
|
||||||
// check for duplicate attribute
|
|
||||||
if let Some(_value) = attributes.insert(name, value) {
|
if let Some(_value) = attributes.insert(name, value) {
|
||||||
return Err(Error::DuplicateAttribute(q_name.to_string()));
|
return Err(Error::DuplicateAttribute(q_name.to_string()));
|
||||||
}
|
}
|
||||||
|
@ -594,32 +579,52 @@ impl<R> Reader<R> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let content;
|
let name;
|
||||||
if let Some(xml_content) = xml_content {
|
let namespace;
|
||||||
namespace_declarations.push(element_namespace_declarations.clone());
|
match &s_tag.name {
|
||||||
|
xml::QName::PrefixedName(prefixed_name) => {
|
||||||
content = Self::content_from_xml(namespace_declarations, xml_content)?;
|
namespace = namespace_stack.iter().rfind(|namespace| {
|
||||||
|
namespace.prefix.as_deref() == Some(**prefixed_name.prefix)
|
||||||
namespace_declarations.pop();
|
});
|
||||||
} else {
|
name = prefixed_name.local_part.to_string();
|
||||||
content = Vec::new();
|
}
|
||||||
|
xml::QName::UnprefixedName(unprefixed_name) => {
|
||||||
|
namespace = namespace_stack
|
||||||
|
.iter()
|
||||||
|
.rfind(|namespace| namespace.prefix == None);
|
||||||
|
name = unprefixed_name.to_string();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let namespace = (*namespace
|
||||||
|
.ok_or_else(|| Error::UnqualifiedNamespace(s_tag.name.to_string()))?)
|
||||||
|
.clone();
|
||||||
|
|
||||||
|
let name = Name { namespace, name };
|
||||||
|
|
||||||
|
namespaces.push(namespace_declarations.clone());
|
||||||
|
|
||||||
|
let content = Self::content_from_xml(namespaces, content)?;
|
||||||
|
|
||||||
|
namespaces.pop();
|
||||||
|
|
||||||
return Ok(Element {
|
return Ok(Element {
|
||||||
name: element_name,
|
name,
|
||||||
namespace_declarations: element_namespace_declarations,
|
namespace_decl: namespace_declarations,
|
||||||
attributes,
|
attributes,
|
||||||
content,
|
content,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn content_from_xml(
|
fn content_from_xml(
|
||||||
namespaces: &mut Vec<HashSet<NamespaceDeclaration>>,
|
namespaces: &mut Vec<HashSet<Namespace>>,
|
||||||
xml_content: xml::Content,
|
element: xml::Content,
|
||||||
) -> Result<Vec<Content>> {
|
) -> Result<Vec<Content>> {
|
||||||
let mut content = Vec::new();
|
let mut content = Vec::new();
|
||||||
let mut text = xml_content.char_data.map(|str| String::from(*str));
|
let mut text = element.char_data.map(|str| String::from(*str));
|
||||||
for (content_item, char_data) in xml_content.content {
|
for (content_item, char_data) in element.content {
|
||||||
match content_item {
|
match content_item {
|
||||||
xml::ContentItem::Element(element) => {
|
xml::ContentItem::Element(element) => {
|
||||||
text.map(|text| content.push(Content::Text(text)));
|
text.map(|text| content.push(Content::Text(text)));
|
||||||
|
|
|
@ -1,53 +1,26 @@
|
||||||
use std::collections::HashSet;
|
use futures::{AsyncWrite, Sink};
|
||||||
|
|
||||||
use futures::Sink;
|
|
||||||
use tokio::io::AsyncWrite;
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
element::{Element, Name, NamespaceDeclaration},
|
element::{Element, Name, Namespace},
|
||||||
error::Error,
|
error::Error,
|
||||||
xml::{self, composers::Composer, parsers_complete::Parser, ETag},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// pub struct Writer<W, C = Composer> {
|
// pub struct Writer<W, C = Composer> {
|
||||||
pub struct Writer<W> {
|
pub struct Writer<W> {
|
||||||
inner: W,
|
writer: W,
|
||||||
depth: Vec<Name>,
|
depth: Vec<Name>,
|
||||||
namespaces: Vec<HashSet<NamespaceDeclaration>>,
|
namespaces: Vec<(usize, Namespace)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<W: AsyncWrite + Unpin> Writer<W> {
|
impl<W: AsyncWrite> Writer<W> {
|
||||||
pub async fn write(&mut self, element: Element) -> Result<(), Error> {
|
pub async fn write(&self, element: impl Into<Element>) -> Result<(), Error> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
pub async fn write_start(&self, element: impl Into<Element>) -> Result<(), Error> {
|
||||||
pub async fn write_start(&mut self, element: Element) -> Result<(), Error> {
|
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
pub async fn write_end(&self) -> Result<(), Error> {
|
||||||
pub async fn write_end(&mut self) -> Result<(), Error> {
|
|
||||||
todo!()
|
todo!()
|
||||||
// let e_tag;
|
|
||||||
// if let Some(name) = self.depth.pop() {
|
|
||||||
// if let Some(prefix) = name.namespace.prefix {
|
|
||||||
// e_tag = xml::ETag {
|
|
||||||
// name: xml::QName::PrefixedName(xml::PrefixedName {
|
|
||||||
// prefix: xml::Prefix::parse_full(&prefix)?,
|
|
||||||
// local_part: xml::LocalPart::parse_full(&name.name)?,
|
|
||||||
// }),
|
|
||||||
// };
|
|
||||||
// e_tag.write(&mut self.inner).await?;
|
|
||||||
// Ok(())
|
|
||||||
// } else {
|
|
||||||
// e_tag = xml::ETag {
|
|
||||||
// name: xml::QName::UnprefixedName(xml::UnprefixedName::parse_full(&name.name)?),
|
|
||||||
// };
|
|
||||||
// e_tag.write(&mut self.inner).await?;
|
|
||||||
// Ok(())
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// return Err(Error::NotInElement("".to_string()));
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,19 +30,6 @@ pub trait Parser<'s> {
|
||||||
type Output;
|
type Output;
|
||||||
|
|
||||||
fn parse(input: &'s str) -> IResult<&str, Self::Output>;
|
fn parse(input: &'s str) -> IResult<&str, Self::Output>;
|
||||||
|
|
||||||
fn parse_full(input: &'s str) -> crate::Result<Self::Output> {
|
|
||||||
match <Self as Parser>::parse(input) {
|
|
||||||
Ok((rest, output)) => {
|
|
||||||
if rest.is_empty() {
|
|
||||||
return Ok(output);
|
|
||||||
} else {
|
|
||||||
return Err(crate::error::Error::ExtraData(rest.to_string()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Result::Err(e) => return Err(crate::error::Error::ParseError(e.to_string())),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// [1] NSAttName ::= PrefixedAttName | DefaultAttName
|
/// [1] NSAttName ::= PrefixedAttName | DefaultAttName
|
||||||
|
|
Loading…
Reference in New Issue