Move deserializer code into de module
This commit is contained in:
parent
c04c277b49
commit
f7bbc00172
|
@ -133,8 +133,8 @@ impl Deserializer {
|
||||||
|
|
||||||
out.extend(quote!(
|
out.extend(quote!(
|
||||||
fn deserialize(deserializer: &mut ::instant_xml::Deserializer<'xml>) -> Result<Self, ::instant_xml::Error> {
|
fn deserialize(deserializer: &mut ::instant_xml::Deserializer<'xml>) -> Result<Self, ::instant_xml::Error> {
|
||||||
use ::instant_xml::parse::XmlRecord;
|
use ::instant_xml::de::{XmlRecord, Deserializer, Visitor};
|
||||||
use ::instant_xml::{Error, Deserializer, Visitor} ;
|
use ::instant_xml::Error;
|
||||||
|
|
||||||
enum __Elements {
|
enum __Elements {
|
||||||
#elements_enum
|
#elements_enum
|
||||||
|
|
|
@ -0,0 +1,376 @@
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::iter::Peekable;
|
||||||
|
|
||||||
|
use super::Error;
|
||||||
|
use xmlparser::{ElementEnd, Token, Tokenizer};
|
||||||
|
|
||||||
|
pub struct Deserializer<'xml> {
|
||||||
|
parser: XmlParser<'xml>,
|
||||||
|
def_namespaces: HashMap<&'xml str, &'xml str>,
|
||||||
|
parser_namespaces: HashMap<&'xml str, &'xml str>,
|
||||||
|
def_default_namespace: &'xml str,
|
||||||
|
parser_default_namespace: &'xml str,
|
||||||
|
tag_attributes: Vec<(&'xml str, &'xml str)>,
|
||||||
|
next_type: EntityType,
|
||||||
|
next_def_namespace: Option<&'xml str>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'xml> Deserializer<'xml> {
|
||||||
|
pub fn new(input: &'xml str) -> Self {
|
||||||
|
Self {
|
||||||
|
parser: XmlParser::new(input),
|
||||||
|
def_namespaces: std::collections::HashMap::new(),
|
||||||
|
parser_namespaces: std::collections::HashMap::new(),
|
||||||
|
def_default_namespace: "",
|
||||||
|
parser_default_namespace: "",
|
||||||
|
tag_attributes: Vec::new(),
|
||||||
|
next_type: EntityType::Element,
|
||||||
|
next_def_namespace: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn peek_next_tag(&mut self) -> Result<Option<XmlRecord<'xml>>, Error> {
|
||||||
|
self.parser.peek_next_tag()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if defined and gotten namespaces equals for each field
|
||||||
|
pub fn compare_namespace(
|
||||||
|
&self,
|
||||||
|
expected: &Option<&str>,
|
||||||
|
actual: Option<&str>,
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
match (expected, actual) {
|
||||||
|
(Some(expected), Some(actual)) => {
|
||||||
|
match self.parser_namespaces.get(expected) == self.def_namespaces.get(actual) {
|
||||||
|
true => Ok(()),
|
||||||
|
false => Err(Error::WrongNamespace),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(Some(_), None) | (None, Some(_)) => Err(Error::WrongNamespace),
|
||||||
|
(None, None) => Ok(()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn compare_parser_and_def_default_namespaces(&self) -> bool {
|
||||||
|
self.parser_default_namespace == self.def_default_namespace
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn peek_next_attribute(&self) -> Option<&(&'xml str, &'xml str)> {
|
||||||
|
self.tag_attributes.last()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn deserialize_struct<V>(
|
||||||
|
&mut self,
|
||||||
|
visitor: V,
|
||||||
|
name: &str,
|
||||||
|
def_default_namespace: &'xml str,
|
||||||
|
def_namespaces: &HashMap<&'xml str, &'xml str>,
|
||||||
|
) -> Result<V::Value, Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'xml>,
|
||||||
|
{
|
||||||
|
// Saveing current defined default namespace
|
||||||
|
let def_default_namespace_to_revert = self.def_default_namespace;
|
||||||
|
self.def_default_namespace = def_default_namespace;
|
||||||
|
|
||||||
|
// Adding struct defined namespaces
|
||||||
|
let new_def_namespaces = def_namespaces
|
||||||
|
.iter()
|
||||||
|
.filter(|(k, v)| self.def_namespaces.insert(k, v).is_none())
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
// Process open tag
|
||||||
|
let tag_data = match self.parser.next() {
|
||||||
|
Some(Ok(XmlRecord::Open(item))) if item.key == name => item,
|
||||||
|
_ => return Err(Error::UnexpectedValue),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Set current attributes
|
||||||
|
self.tag_attributes = tag_data.attributes;
|
||||||
|
|
||||||
|
// Saveing current parser default namespace
|
||||||
|
let parser_default_namespace_to_revert = self.parser_default_namespace;
|
||||||
|
|
||||||
|
// Set parser default namespace
|
||||||
|
match tag_data.default_namespace {
|
||||||
|
Some(namespace) => {
|
||||||
|
self.parser_default_namespace = namespace;
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
// If there is no default namespace in the tag, check if parent default namespace equals the current one
|
||||||
|
if def_default_namespace_to_revert != self.def_default_namespace {
|
||||||
|
return Err(Error::WrongNamespace);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compare parser namespace with defined one
|
||||||
|
if !self.compare_parser_and_def_default_namespaces() {
|
||||||
|
return Err(Error::WrongNamespace);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adding parser namespaces
|
||||||
|
let new_parser_namespaces = tag_data
|
||||||
|
.namespaces
|
||||||
|
.iter()
|
||||||
|
.filter(|(k, v)| self.parser_namespaces.insert(k, v).is_none())
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let ret = visitor.visit_struct(self)?;
|
||||||
|
|
||||||
|
// Process close tag
|
||||||
|
self.check_close_tag(name)?;
|
||||||
|
|
||||||
|
// Removing parser namespaces
|
||||||
|
let _ = new_parser_namespaces
|
||||||
|
.iter()
|
||||||
|
.map(|(k, _)| self.parser_namespaces.remove(*k));
|
||||||
|
|
||||||
|
// Removing struct defined namespaces
|
||||||
|
let _ = new_def_namespaces
|
||||||
|
.iter()
|
||||||
|
.map(|(k, _)| self.def_namespaces.remove(*k));
|
||||||
|
|
||||||
|
// Retriving old defined namespace
|
||||||
|
self.def_default_namespace = def_default_namespace_to_revert;
|
||||||
|
|
||||||
|
// Retriving old parser namespace
|
||||||
|
self.parser_default_namespace = parser_default_namespace_to_revert;
|
||||||
|
Ok(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_next_type_as_attribute(&mut self) -> Result<(), Error> {
|
||||||
|
if self.next_type == EntityType::Attribute {
|
||||||
|
return Err(Error::UnexpectedState);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.next_type = EntityType::Attribute;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn consume_next_type(&mut self) -> EntityType {
|
||||||
|
let ret = self.next_type.clone();
|
||||||
|
self.next_type = EntityType::Element;
|
||||||
|
ret
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_next_def_namespace(&mut self, namespace: Option<&'xml str>) -> Result<(), Error> {
|
||||||
|
if self.next_def_namespace.is_some() {
|
||||||
|
return Err(Error::UnexpectedState);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.next_def_namespace = namespace;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn consume_next_def_namespace(&mut self) -> Option<&'xml str> {
|
||||||
|
let ret = self.next_def_namespace;
|
||||||
|
self.next_def_namespace = None;
|
||||||
|
ret
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn deserialize_element<V>(&mut self, visitor: V) -> Result<V::Value, Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'xml>,
|
||||||
|
{
|
||||||
|
// Process open tag
|
||||||
|
let tag_data = match self.parser.next() {
|
||||||
|
Some(Ok(XmlRecord::Open(item))) => item,
|
||||||
|
_ => return Err(Error::UnexpectedValue),
|
||||||
|
};
|
||||||
|
|
||||||
|
if tag_data.default_namespace != self.consume_next_def_namespace() {
|
||||||
|
return Err(Error::WrongNamespace);
|
||||||
|
}
|
||||||
|
|
||||||
|
match self.parser.next() {
|
||||||
|
Some(Ok(XmlRecord::Element(v))) => {
|
||||||
|
let ret = visitor.visit_str(v);
|
||||||
|
self.parser.next();
|
||||||
|
ret
|
||||||
|
}
|
||||||
|
_ => Err(Error::UnexpectedValue),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn deserialize_attribute<V>(&mut self, visitor: V) -> Result<V::Value, Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'xml>,
|
||||||
|
{
|
||||||
|
match self.tag_attributes.pop() {
|
||||||
|
Some((_, value)) => visitor.visit_str(value),
|
||||||
|
None => Err(Error::UnexpectedEndOfStream),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_close_tag(&mut self, name: &str) -> Result<(), Error> {
|
||||||
|
let item = match self.parser.next() {
|
||||||
|
Some(item) => item?,
|
||||||
|
None => return Err(Error::MissingTag),
|
||||||
|
};
|
||||||
|
|
||||||
|
match item {
|
||||||
|
XmlRecord::Close(v) if v == name => Ok(()),
|
||||||
|
_ => Err(Error::UnexpectedTag),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct XmlParser<'xml> {
|
||||||
|
stack: Vec<&'xml str>,
|
||||||
|
iter: Peekable<Tokenizer<'xml>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> XmlParser<'a> {
|
||||||
|
pub fn new(input: &'a str) -> XmlParser<'a> {
|
||||||
|
XmlParser {
|
||||||
|
stack: Vec::new(),
|
||||||
|
iter: Tokenizer::from(input).peekable(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn peek_next_tag(&mut self) -> Result<Option<XmlRecord<'a>>, Error> {
|
||||||
|
let item = match self.iter.peek() {
|
||||||
|
Some(v) => v,
|
||||||
|
None => return Ok(None),
|
||||||
|
};
|
||||||
|
|
||||||
|
match item {
|
||||||
|
Ok(Token::ElementStart { prefix, local, .. }) => {
|
||||||
|
let prefix = match prefix.is_empty() {
|
||||||
|
true => None,
|
||||||
|
false => Some(prefix.as_str()),
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(Some(XmlRecord::Open(TagData {
|
||||||
|
key: local.as_str(),
|
||||||
|
attributes: Vec::new(),
|
||||||
|
default_namespace: Some(""),
|
||||||
|
namespaces: HashMap::new(),
|
||||||
|
prefix,
|
||||||
|
})))
|
||||||
|
}
|
||||||
|
Ok(Token::ElementEnd {
|
||||||
|
end: ElementEnd::Close(..),
|
||||||
|
..
|
||||||
|
}) => {
|
||||||
|
if self.stack.is_empty() {
|
||||||
|
return Err(Error::UnexpectedEndOfStream);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Ok(Some(XmlRecord::Close(self.stack.last().unwrap())));
|
||||||
|
}
|
||||||
|
Ok(_) => Err(Error::UnexpectedToken),
|
||||||
|
Err(e) => Err(Error::Parse(*e)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'xml> Iterator for XmlParser<'xml> {
|
||||||
|
type Item = Result<XmlRecord<'xml>, Error>;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
let mut key: Option<&str> = None;
|
||||||
|
let mut prefix_ret: Option<&str> = None;
|
||||||
|
let mut default_namespace = None;
|
||||||
|
let mut namespaces = HashMap::new();
|
||||||
|
let mut attributes = Vec::new();
|
||||||
|
|
||||||
|
loop {
|
||||||
|
let item = match self.iter.next() {
|
||||||
|
Some(v) => v,
|
||||||
|
None => return None,
|
||||||
|
};
|
||||||
|
|
||||||
|
match item {
|
||||||
|
Ok(Token::ElementStart { prefix, local, .. }) => {
|
||||||
|
key = Some(local.as_str());
|
||||||
|
prefix_ret = match prefix.is_empty() {
|
||||||
|
true => None,
|
||||||
|
false => Some(prefix.as_str()),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
Ok(Token::ElementEnd { end, .. }) => match end {
|
||||||
|
ElementEnd::Open => {
|
||||||
|
self.stack.push(key.unwrap());
|
||||||
|
|
||||||
|
return Some(Ok(XmlRecord::Open(TagData {
|
||||||
|
key: key.unwrap(),
|
||||||
|
attributes,
|
||||||
|
default_namespace,
|
||||||
|
namespaces,
|
||||||
|
prefix: prefix_ret,
|
||||||
|
})));
|
||||||
|
}
|
||||||
|
ElementEnd::Close(_, v) => match self.stack.pop() {
|
||||||
|
Some(last) if last == v.as_str() => {
|
||||||
|
return Some(Ok(XmlRecord::Close(last)));
|
||||||
|
}
|
||||||
|
_ => return Some(Err(Error::UnexpectedValue)),
|
||||||
|
},
|
||||||
|
ElementEnd::Empty => {
|
||||||
|
todo!();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Ok(Token::Attribute {
|
||||||
|
prefix,
|
||||||
|
local,
|
||||||
|
value,
|
||||||
|
..
|
||||||
|
}) => {
|
||||||
|
if prefix.is_empty() && local.as_str() == "xmlns" {
|
||||||
|
// Default namespace
|
||||||
|
default_namespace = Some(value.as_str());
|
||||||
|
} else if prefix.as_str() == "xmlns" {
|
||||||
|
// Namespaces
|
||||||
|
namespaces.insert(local.as_str(), value.as_str());
|
||||||
|
} else if prefix.is_empty() {
|
||||||
|
// Other attributes
|
||||||
|
attributes.push((local.as_str(), value.as_str()));
|
||||||
|
} else {
|
||||||
|
// TODO: Can the attributes have the prefix?
|
||||||
|
todo!();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(Token::Text { text }) => {
|
||||||
|
return Some(Ok(XmlRecord::Element(text.as_str())));
|
||||||
|
}
|
||||||
|
Ok(_) => return Some(Err(Error::UnexpectedToken)),
|
||||||
|
Err(e) => return Some(Err(Error::Parse(e))),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait Visitor<'xml>: Sized {
|
||||||
|
type Value;
|
||||||
|
|
||||||
|
fn visit_str(self, _value: &'xml str) -> Result<Self::Value, Error> {
|
||||||
|
unimplemented!();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_struct(&self, _deserializer: &mut Deserializer<'xml>) -> Result<Self::Value, Error> {
|
||||||
|
unimplemented!();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum XmlRecord<'xml> {
|
||||||
|
Open(TagData<'xml>),
|
||||||
|
Element(&'xml str),
|
||||||
|
Close(&'xml str),
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct TagData<'xml> {
|
||||||
|
pub key: &'xml str,
|
||||||
|
pub attributes: Vec<(&'xml str, &'xml str)>,
|
||||||
|
pub default_namespace: Option<&'xml str>,
|
||||||
|
pub namespaces: HashMap<&'xml str, &'xml str>,
|
||||||
|
pub prefix: Option<&'xml str>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, PartialEq, Eq)]
|
||||||
|
pub enum EntityType {
|
||||||
|
Element,
|
||||||
|
Attribute,
|
||||||
|
}
|
|
@ -3,9 +3,8 @@ use std::fmt;
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use crate::{
|
use crate::de::{EntityType, Visitor};
|
||||||
Deserializer, EntityType, Error, FieldAttribute, FromXml, Serializer, TagName, ToXml, Visitor,
|
use crate::{Deserializer, Error, FieldAttribute, FromXml, Serializer, TagName, ToXml};
|
||||||
};
|
|
||||||
|
|
||||||
// Deserializer
|
// Deserializer
|
||||||
struct FromStrToVisitor<T: FromStr>(PhantomData<T>)
|
struct FromStrToVisitor<T: FromStr>(PhantomData<T>)
|
||||||
|
|
|
@ -6,25 +6,11 @@ use thiserror::Error;
|
||||||
pub use xmlparser;
|
pub use xmlparser;
|
||||||
|
|
||||||
pub use macros::{FromXml, ToXml};
|
pub use macros::{FromXml, ToXml};
|
||||||
use parse::XmlParser;
|
|
||||||
|
|
||||||
pub mod impls;
|
mod impls;
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub mod parse;
|
pub mod de;
|
||||||
|
pub use de::Deserializer;
|
||||||
pub struct TagData<'xml> {
|
|
||||||
pub key: &'xml str,
|
|
||||||
pub attributes: Vec<(&'xml str, &'xml str)>,
|
|
||||||
pub default_namespace: Option<&'xml str>,
|
|
||||||
pub namespaces: HashMap<&'xml str, &'xml str>,
|
|
||||||
pub prefix: Option<&'xml str>,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub enum XmlRecord<'xml> {
|
|
||||||
Open(TagData<'xml>),
|
|
||||||
Element(&'xml str),
|
|
||||||
Close(&'xml str),
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait ToXml {
|
pub trait ToXml {
|
||||||
fn to_xml(&self) -> Result<String, Error> {
|
fn to_xml(&self) -> Result<String, Error> {
|
||||||
|
@ -173,12 +159,6 @@ pub struct FieldContext<'xml> {
|
||||||
pub attribute: Option<FieldAttribute<'xml>>,
|
pub attribute: Option<FieldAttribute<'xml>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Eq)]
|
|
||||||
pub enum EntityType {
|
|
||||||
Element,
|
|
||||||
Attribute,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub enum TagName {
|
pub enum TagName {
|
||||||
FieldName,
|
FieldName,
|
||||||
Custom(&'static str),
|
Custom(&'static str),
|
||||||
|
@ -201,230 +181,6 @@ pub trait FromXml<'xml>: Sized {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Visitor<'xml>: Sized {
|
|
||||||
type Value;
|
|
||||||
|
|
||||||
fn visit_str(self, _value: &'xml str) -> Result<Self::Value, Error> {
|
|
||||||
unimplemented!();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_struct(&self, _deserializer: &mut Deserializer<'xml>) -> Result<Self::Value, Error> {
|
|
||||||
unimplemented!();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Deserializer<'xml> {
|
|
||||||
parser: XmlParser<'xml>,
|
|
||||||
def_namespaces: HashMap<&'xml str, &'xml str>,
|
|
||||||
parser_namespaces: HashMap<&'xml str, &'xml str>,
|
|
||||||
def_default_namespace: &'xml str,
|
|
||||||
parser_default_namespace: &'xml str,
|
|
||||||
tag_attributes: Vec<(&'xml str, &'xml str)>,
|
|
||||||
next_type: EntityType,
|
|
||||||
next_def_namespace: Option<&'xml str>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'xml> Deserializer<'xml> {
|
|
||||||
pub fn new(input: &'xml str) -> Self {
|
|
||||||
Self {
|
|
||||||
parser: XmlParser::new(input),
|
|
||||||
def_namespaces: std::collections::HashMap::new(),
|
|
||||||
parser_namespaces: std::collections::HashMap::new(),
|
|
||||||
def_default_namespace: "",
|
|
||||||
parser_default_namespace: "",
|
|
||||||
tag_attributes: Vec::new(),
|
|
||||||
next_type: EntityType::Element,
|
|
||||||
next_def_namespace: None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn peek_next_tag(&mut self) -> Result<Option<XmlRecord<'xml>>, Error> {
|
|
||||||
self.parser.peek_next_tag()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if defined and gotten namespaces equals for each field
|
|
||||||
pub fn compare_namespace(
|
|
||||||
&self,
|
|
||||||
expected: &Option<&str>,
|
|
||||||
actual: Option<&str>,
|
|
||||||
) -> Result<(), Error> {
|
|
||||||
match (expected, actual) {
|
|
||||||
(Some(expected), Some(actual)) => {
|
|
||||||
match self.parser_namespaces.get(expected) == self.def_namespaces.get(actual) {
|
|
||||||
true => Ok(()),
|
|
||||||
false => Err(Error::WrongNamespace),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
(Some(_), None) | (None, Some(_)) => Err(Error::WrongNamespace),
|
|
||||||
(None, None) => Ok(()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn compare_parser_and_def_default_namespaces(&self) -> bool {
|
|
||||||
self.parser_default_namespace == self.def_default_namespace
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn peek_next_attribute(&self) -> Option<&(&'xml str, &'xml str)> {
|
|
||||||
self.tag_attributes.last()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn deserialize_struct<V>(
|
|
||||||
&mut self,
|
|
||||||
visitor: V,
|
|
||||||
name: &str,
|
|
||||||
def_default_namespace: &'xml str,
|
|
||||||
def_namespaces: &HashMap<&'xml str, &'xml str>,
|
|
||||||
) -> Result<V::Value, Error>
|
|
||||||
where
|
|
||||||
V: Visitor<'xml>,
|
|
||||||
{
|
|
||||||
// Saveing current defined default namespace
|
|
||||||
let def_default_namespace_to_revert = self.def_default_namespace;
|
|
||||||
self.def_default_namespace = def_default_namespace;
|
|
||||||
|
|
||||||
// Adding struct defined namespaces
|
|
||||||
let new_def_namespaces = def_namespaces
|
|
||||||
.iter()
|
|
||||||
.filter(|(k, v)| self.def_namespaces.insert(k, v).is_none())
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
// Process open tag
|
|
||||||
let tag_data = match self.parser.next() {
|
|
||||||
Some(Ok(XmlRecord::Open(item))) if item.key == name => item,
|
|
||||||
_ => return Err(Error::UnexpectedValue),
|
|
||||||
};
|
|
||||||
|
|
||||||
// Set current attributes
|
|
||||||
self.tag_attributes = tag_data.attributes;
|
|
||||||
|
|
||||||
// Saveing current parser default namespace
|
|
||||||
let parser_default_namespace_to_revert = self.parser_default_namespace;
|
|
||||||
|
|
||||||
// Set parser default namespace
|
|
||||||
match tag_data.default_namespace {
|
|
||||||
Some(namespace) => {
|
|
||||||
self.parser_default_namespace = namespace;
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
// If there is no default namespace in the tag, check if parent default namespace equals the current one
|
|
||||||
if def_default_namespace_to_revert != self.def_default_namespace {
|
|
||||||
return Err(Error::WrongNamespace);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Compare parser namespace with defined one
|
|
||||||
if !self.compare_parser_and_def_default_namespaces() {
|
|
||||||
return Err(Error::WrongNamespace);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Adding parser namespaces
|
|
||||||
let new_parser_namespaces = tag_data
|
|
||||||
.namespaces
|
|
||||||
.iter()
|
|
||||||
.filter(|(k, v)| self.parser_namespaces.insert(k, v).is_none())
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
let ret = visitor.visit_struct(self)?;
|
|
||||||
|
|
||||||
// Process close tag
|
|
||||||
self.check_close_tag(name)?;
|
|
||||||
|
|
||||||
// Removing parser namespaces
|
|
||||||
let _ = new_parser_namespaces
|
|
||||||
.iter()
|
|
||||||
.map(|(k, _)| self.parser_namespaces.remove(*k));
|
|
||||||
|
|
||||||
// Removing struct defined namespaces
|
|
||||||
let _ = new_def_namespaces
|
|
||||||
.iter()
|
|
||||||
.map(|(k, _)| self.def_namespaces.remove(*k));
|
|
||||||
|
|
||||||
// Retriving old defined namespace
|
|
||||||
self.def_default_namespace = def_default_namespace_to_revert;
|
|
||||||
|
|
||||||
// Retriving old parser namespace
|
|
||||||
self.parser_default_namespace = parser_default_namespace_to_revert;
|
|
||||||
Ok(ret)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_next_type_as_attribute(&mut self) -> Result<(), Error> {
|
|
||||||
if self.next_type == EntityType::Attribute {
|
|
||||||
return Err(Error::UnexpectedState);
|
|
||||||
}
|
|
||||||
|
|
||||||
self.next_type = EntityType::Attribute;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn consume_next_type(&mut self) -> EntityType {
|
|
||||||
let ret = self.next_type.clone();
|
|
||||||
self.next_type = EntityType::Element;
|
|
||||||
ret
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_next_def_namespace(&mut self, namespace: Option<&'xml str>) -> Result<(), Error> {
|
|
||||||
if self.next_def_namespace.is_some() {
|
|
||||||
return Err(Error::UnexpectedState);
|
|
||||||
}
|
|
||||||
|
|
||||||
self.next_def_namespace = namespace;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn consume_next_def_namespace(&mut self) -> Option<&'xml str> {
|
|
||||||
let ret = self.next_def_namespace;
|
|
||||||
self.next_def_namespace = None;
|
|
||||||
ret
|
|
||||||
}
|
|
||||||
|
|
||||||
fn deserialize_element<V>(&mut self, visitor: V) -> Result<V::Value, Error>
|
|
||||||
where
|
|
||||||
V: Visitor<'xml>,
|
|
||||||
{
|
|
||||||
// Process open tag
|
|
||||||
let tag_data = match self.parser.next() {
|
|
||||||
Some(Ok(XmlRecord::Open(item))) => item,
|
|
||||||
_ => return Err(Error::UnexpectedValue),
|
|
||||||
};
|
|
||||||
|
|
||||||
if tag_data.default_namespace != self.consume_next_def_namespace() {
|
|
||||||
return Err(Error::WrongNamespace);
|
|
||||||
}
|
|
||||||
|
|
||||||
match self.parser.next() {
|
|
||||||
Some(Ok(XmlRecord::Element(v))) => {
|
|
||||||
let ret = visitor.visit_str(v);
|
|
||||||
self.parser.next();
|
|
||||||
ret
|
|
||||||
}
|
|
||||||
_ => Err(Error::UnexpectedValue),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn deserialize_attribute<V>(&mut self, visitor: V) -> Result<V::Value, Error>
|
|
||||||
where
|
|
||||||
V: Visitor<'xml>,
|
|
||||||
{
|
|
||||||
match self.tag_attributes.pop() {
|
|
||||||
Some((_, value)) => visitor.visit_str(value),
|
|
||||||
None => Err(Error::UnexpectedEndOfStream),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn check_close_tag(&mut self, name: &str) -> Result<(), Error> {
|
|
||||||
let item = match self.parser.next() {
|
|
||||||
Some(item) => item?,
|
|
||||||
None => return Err(Error::MissingTag),
|
|
||||||
};
|
|
||||||
|
|
||||||
match item {
|
|
||||||
XmlRecord::Close(v) if v == name => Ok(()),
|
|
||||||
_ => Err(Error::UnexpectedTag),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait FromXmlOwned: for<'xml> FromXml<'xml> {}
|
pub trait FromXmlOwned: for<'xml> FromXml<'xml> {}
|
||||||
|
|
||||||
#[derive(Debug, Error, PartialEq, Eq)]
|
#[derive(Debug, Error, PartialEq, Eq)]
|
||||||
|
|
|
@ -1,134 +0,0 @@
|
||||||
use std::collections::HashMap;
|
|
||||||
use std::iter::Peekable;
|
|
||||||
|
|
||||||
use xmlparser::{ElementEnd, Token, Tokenizer};
|
|
||||||
|
|
||||||
use crate::Error;
|
|
||||||
pub use crate::{TagData, XmlRecord};
|
|
||||||
|
|
||||||
pub struct XmlParser<'xml> {
|
|
||||||
stack: Vec<&'xml str>,
|
|
||||||
iter: Peekable<Tokenizer<'xml>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> XmlParser<'a> {
|
|
||||||
pub fn new(input: &'a str) -> XmlParser<'a> {
|
|
||||||
XmlParser {
|
|
||||||
stack: Vec::new(),
|
|
||||||
iter: Tokenizer::from(input).peekable(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn peek_next_tag(&mut self) -> Result<Option<XmlRecord<'a>>, Error> {
|
|
||||||
let item = match self.iter.peek() {
|
|
||||||
Some(v) => v,
|
|
||||||
None => return Ok(None),
|
|
||||||
};
|
|
||||||
|
|
||||||
match item {
|
|
||||||
Ok(Token::ElementStart { prefix, local, .. }) => {
|
|
||||||
let prefix = match prefix.is_empty() {
|
|
||||||
true => None,
|
|
||||||
false => Some(prefix.as_str()),
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(Some(XmlRecord::Open(TagData {
|
|
||||||
key: local.as_str(),
|
|
||||||
attributes: Vec::new(),
|
|
||||||
default_namespace: Some(""),
|
|
||||||
namespaces: HashMap::new(),
|
|
||||||
prefix,
|
|
||||||
})))
|
|
||||||
}
|
|
||||||
Ok(Token::ElementEnd {
|
|
||||||
end: ElementEnd::Close(..),
|
|
||||||
..
|
|
||||||
}) => {
|
|
||||||
if self.stack.is_empty() {
|
|
||||||
return Err(Error::UnexpectedEndOfStream);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Ok(Some(XmlRecord::Close(self.stack.last().unwrap())));
|
|
||||||
}
|
|
||||||
Ok(_) => Err(Error::UnexpectedToken),
|
|
||||||
Err(e) => Err(Error::Parse(*e)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'xml> Iterator for XmlParser<'xml> {
|
|
||||||
type Item = Result<XmlRecord<'xml>, Error>;
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
|
||||||
let mut key: Option<&str> = None;
|
|
||||||
let mut prefix_ret: Option<&str> = None;
|
|
||||||
let mut default_namespace = None;
|
|
||||||
let mut namespaces = HashMap::new();
|
|
||||||
let mut attributes = Vec::new();
|
|
||||||
|
|
||||||
loop {
|
|
||||||
let item = match self.iter.next() {
|
|
||||||
Some(v) => v,
|
|
||||||
None => return None,
|
|
||||||
};
|
|
||||||
|
|
||||||
match item {
|
|
||||||
Ok(Token::ElementStart { prefix, local, .. }) => {
|
|
||||||
key = Some(local.as_str());
|
|
||||||
prefix_ret = match prefix.is_empty() {
|
|
||||||
true => None,
|
|
||||||
false => Some(prefix.as_str()),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
Ok(Token::ElementEnd { end, .. }) => match end {
|
|
||||||
ElementEnd::Open => {
|
|
||||||
self.stack.push(key.unwrap());
|
|
||||||
|
|
||||||
return Some(Ok(XmlRecord::Open(TagData {
|
|
||||||
key: key.unwrap(),
|
|
||||||
attributes,
|
|
||||||
default_namespace,
|
|
||||||
namespaces,
|
|
||||||
prefix: prefix_ret,
|
|
||||||
})));
|
|
||||||
}
|
|
||||||
ElementEnd::Close(_, v) => match self.stack.pop() {
|
|
||||||
Some(last) if last == v.as_str() => {
|
|
||||||
return Some(Ok(XmlRecord::Close(last)));
|
|
||||||
}
|
|
||||||
_ => return Some(Err(Error::UnexpectedValue)),
|
|
||||||
},
|
|
||||||
ElementEnd::Empty => {
|
|
||||||
todo!();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Ok(Token::Attribute {
|
|
||||||
prefix,
|
|
||||||
local,
|
|
||||||
value,
|
|
||||||
..
|
|
||||||
}) => {
|
|
||||||
if prefix.is_empty() && local.as_str() == "xmlns" {
|
|
||||||
// Default namespace
|
|
||||||
default_namespace = Some(value.as_str());
|
|
||||||
} else if prefix.as_str() == "xmlns" {
|
|
||||||
// Namespaces
|
|
||||||
namespaces.insert(local.as_str(), value.as_str());
|
|
||||||
} else if prefix.is_empty() {
|
|
||||||
// Other attributes
|
|
||||||
attributes.push((local.as_str(), value.as_str()));
|
|
||||||
} else {
|
|
||||||
// TODO: Can the attributes have the prefix?
|
|
||||||
todo!();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(Token::Text { text }) => {
|
|
||||||
return Some(Ok(XmlRecord::Element(text.as_str())));
|
|
||||||
}
|
|
||||||
Ok(_) => return Some(Err(Error::UnexpectedToken)),
|
|
||||||
Err(e) => return Some(Err(Error::Parse(e))),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue