Namespaces fixes - deserializer (#10)
This commit is contained in:
parent
ba40445c5e
commit
fcf20aa507
|
@ -1,7 +1,7 @@
|
||||||
use proc_macro2::{Ident, Span, TokenStream};
|
use proc_macro2::{Ident, Span, TokenStream};
|
||||||
use quote::quote;
|
use quote::quote;
|
||||||
|
|
||||||
use crate::{get_namespaces, retrieve_attr};
|
use crate::{get_namespaces, retrieve_field_attribute, FieldAttribute};
|
||||||
|
|
||||||
struct Tokens {
|
struct Tokens {
|
||||||
enum_: TokenStream,
|
enum_: TokenStream,
|
||||||
|
@ -37,8 +37,9 @@ impl Deserializer {
|
||||||
let name = ident.to_string();
|
let name = ident.to_string();
|
||||||
let mut out = TokenStream::new();
|
let mut out = TokenStream::new();
|
||||||
|
|
||||||
let (_, other_namespaces) = get_namespaces(&input.attrs);
|
let (default_namespace, other_namespaces) = get_namespaces(&input.attrs);
|
||||||
let mut namespaces_map = quote!(let mut namespaces_map = std::collections::HashMap::new(););
|
let mut namespaces_map = quote!(let mut namespaces_map = std::collections::HashMap::new(););
|
||||||
|
|
||||||
for (k, v) in other_namespaces.iter() {
|
for (k, v) in other_namespaces.iter() {
|
||||||
namespaces_map.extend(quote!(
|
namespaces_map.extend(quote!(
|
||||||
namespaces_map.insert(#k, #v);
|
namespaces_map.insert(#k, #v);
|
||||||
|
@ -58,16 +59,26 @@ impl Deserializer {
|
||||||
match data.fields {
|
match data.fields {
|
||||||
syn::Fields::Named(ref fields) => {
|
syn::Fields::Named(ref fields) => {
|
||||||
fields.named.iter().enumerate().for_each(|(index, field)| {
|
fields.named.iter().enumerate().for_each(|(index, field)| {
|
||||||
let is_element;
|
let mut field_namespace = None;
|
||||||
let tokens = match retrieve_attr("attribute", &field.attrs) {
|
let (tokens, def_prefix, is_element) = match retrieve_field_attribute(field) {
|
||||||
Some(true) => {
|
Some(FieldAttribute::Namespace(value)) => {
|
||||||
is_element = false;
|
field_namespace = Some(value);
|
||||||
&mut attributes_tokens
|
(&mut elements_tokens, None, true)
|
||||||
}
|
}
|
||||||
_ => {
|
Some(FieldAttribute::PrefixIdentifier(def_prefix)) => {
|
||||||
is_element = true;
|
if other_namespaces.get(&def_prefix).is_none() {
|
||||||
&mut elements_tokens
|
panic!("Namespace with such prefix do not exist for this struct");
|
||||||
|
}
|
||||||
|
|
||||||
|
(&mut elements_tokens, Some(def_prefix), true)
|
||||||
|
},
|
||||||
|
Some(FieldAttribute::Attribute) => {
|
||||||
|
(&mut attributes_tokens, None, false)
|
||||||
}
|
}
|
||||||
|
None => {
|
||||||
|
(&mut elements_tokens, None, true)
|
||||||
|
},
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Self::process_field(
|
Self::process_field(
|
||||||
|
@ -77,10 +88,12 @@ impl Deserializer {
|
||||||
&mut return_val,
|
&mut return_val,
|
||||||
tokens,
|
tokens,
|
||||||
is_element,
|
is_element,
|
||||||
|
def_prefix,
|
||||||
|
field_namespace,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
syn::Fields::Unnamed(_) => todo!(),
|
syn::Fields::Unnamed(_) => panic!("unamed"),
|
||||||
syn::Fields::Unit => {}
|
syn::Fields::Unit => {}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -137,7 +150,6 @@ impl Deserializer {
|
||||||
fn visit_struct<'a>(&self, deserializer: &mut ::instant_xml::Deserializer) -> Result<Self::Value, ::instant_xml::Error>
|
fn visit_struct<'a>(&self, deserializer: &mut ::instant_xml::Deserializer) -> Result<Self::Value, ::instant_xml::Error>
|
||||||
{
|
{
|
||||||
#declare_values
|
#declare_values
|
||||||
|
|
||||||
while let Some(( key, _ )) = deserializer.peek_next_attribute() {
|
while let Some(( key, _ )) = deserializer.peek_next_attribute() {
|
||||||
match get_attribute(&key) {
|
match get_attribute(&key) {
|
||||||
#attr_type_match
|
#attr_type_match
|
||||||
|
@ -149,10 +161,11 @@ impl Deserializer {
|
||||||
XmlRecord::Open(item) => {
|
XmlRecord::Open(item) => {
|
||||||
match get_element(&item.key.as_ref()) {
|
match get_element(&item.key.as_ref()) {
|
||||||
#elem_type_match
|
#elem_type_match
|
||||||
__Elements::__Ignore => todo!(),
|
__Elements::__Ignore => panic!("No such element"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
XmlRecord::Close(tag) => {
|
XmlRecord::Close(tag) => {
|
||||||
|
println!("Close: {}", tag);
|
||||||
if tag == &#name {
|
if tag == &#name {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -168,7 +181,7 @@ impl Deserializer {
|
||||||
}
|
}
|
||||||
|
|
||||||
#namespaces_map;
|
#namespaces_map;
|
||||||
deserializer.deserialize_struct(StructVisitor{}, #name, &namespaces_map)
|
deserializer.deserialize_struct(StructVisitor{}, #name, #default_namespace, &namespaces_map)
|
||||||
}
|
}
|
||||||
));
|
));
|
||||||
|
|
||||||
|
@ -179,6 +192,7 @@ impl Deserializer {
|
||||||
Deserializer { out }
|
Deserializer { out }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::too_many_arguments)]
|
||||||
fn process_field(
|
fn process_field(
|
||||||
field: &syn::Field,
|
field: &syn::Field,
|
||||||
index: usize,
|
index: usize,
|
||||||
|
@ -186,13 +200,15 @@ impl Deserializer {
|
||||||
return_val: &mut TokenStream,
|
return_val: &mut TokenStream,
|
||||||
tokens: &mut Tokens,
|
tokens: &mut Tokens,
|
||||||
is_element: bool,
|
is_element: bool,
|
||||||
|
def_prefix: Option<String>,
|
||||||
|
field_namespace: Option<String>,
|
||||||
) {
|
) {
|
||||||
let field_var = field.ident.as_ref().unwrap();
|
let field_var = field.ident.as_ref().unwrap();
|
||||||
let field_var_str = field_var.to_string();
|
let field_var_str = field_var.to_string();
|
||||||
let const_field_var_str = Ident::new(&field_var_str.to_uppercase(), Span::call_site());
|
let const_field_var_str = Ident::new(&field_var_str.to_uppercase(), Span::call_site());
|
||||||
let field_type = match &field.ty {
|
let field_type = match &field.ty {
|
||||||
syn::Type::Path(v) => v.path.get_ident(),
|
syn::Type::Path(v) => v.path.get_ident(),
|
||||||
_ => todo!(),
|
_ => panic!("Wrong field attribute format"),
|
||||||
};
|
};
|
||||||
|
|
||||||
let enum_name = Ident::new(&format!("__Value{index}"), Span::call_site());
|
let enum_name = Ident::new(&format!("__Value{index}"), Span::call_site());
|
||||||
|
@ -219,6 +235,18 @@ impl Deserializer {
|
||||||
let mut #enum_name: Option<#field_type> = None;
|
let mut #enum_name: Option<#field_type> = None;
|
||||||
));
|
));
|
||||||
|
|
||||||
|
let def_prefix = match def_prefix {
|
||||||
|
Some(def_prefix) => quote!(let def_prefix: Option<&str> = Some(#def_prefix);),
|
||||||
|
None => quote!(let def_prefix: Option<&str> = None;),
|
||||||
|
};
|
||||||
|
|
||||||
|
let field_namespace = match field_namespace {
|
||||||
|
Some(field_namespace) => {
|
||||||
|
quote!(let field_namespace: Option<&str> = Some(#field_namespace);)
|
||||||
|
}
|
||||||
|
None => quote!(let field_namespace: Option<&str> = None;),
|
||||||
|
};
|
||||||
|
|
||||||
if is_element {
|
if is_element {
|
||||||
tokens.match_.extend(quote!(
|
tokens.match_.extend(quote!(
|
||||||
__Elements::#enum_name => {
|
__Elements::#enum_name => {
|
||||||
|
@ -226,11 +254,35 @@ impl Deserializer {
|
||||||
panic!("duplicated value");
|
panic!("duplicated value");
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(item) = item.prefix {
|
match item.prefix {
|
||||||
let prefix = item.to_owned();
|
Some(item) => {
|
||||||
deserializer.verify_namespace(&prefix);
|
let parser_prefix = item.to_owned();
|
||||||
|
#def_prefix
|
||||||
|
match def_prefix {
|
||||||
|
Some(def_prefix) => {
|
||||||
|
// Check if defined and gotten namespaces equals for each field
|
||||||
|
if deserializer.get_parser_namespace(&parser_prefix)
|
||||||
|
!= deserializer.get_def_namespace(def_prefix) {
|
||||||
|
return Err(Error::WrongNamespace)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
return Err(Error::WrongNamespace);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
#def_prefix
|
||||||
|
match def_prefix {
|
||||||
|
Some(_) => {
|
||||||
|
return Err(Error::WrongNamespace)
|
||||||
|
},
|
||||||
|
None => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
#field_namespace
|
||||||
|
deserializer.set_next_def_namespace(field_namespace)?;
|
||||||
#enum_name = Some(#field_type::deserialize(deserializer)?);
|
#enum_name = Some(#field_type::deserialize(deserializer)?);
|
||||||
},
|
},
|
||||||
));
|
));
|
||||||
|
|
|
@ -16,23 +16,25 @@ const XML: &str = "xml";
|
||||||
pub(crate) enum FieldAttribute {
|
pub(crate) enum FieldAttribute {
|
||||||
Namespace(String),
|
Namespace(String),
|
||||||
PrefixIdentifier(String),
|
PrefixIdentifier(String),
|
||||||
|
Attribute,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn get_namespaces(
|
pub(crate) fn get_namespaces(
|
||||||
attributes: &Vec<syn::Attribute>,
|
attributes: &Vec<syn::Attribute>,
|
||||||
) -> (Option<String>, HashMap<String, String>) {
|
) -> (String, HashMap<String, String>) {
|
||||||
let mut default_namespace = None;
|
let mut default_namespace = String::new();
|
||||||
let mut other_namespaces = HashMap::default();
|
let mut other_namespaces = HashMap::default();
|
||||||
|
|
||||||
let list = match retrieve_attr_list("namespace", attributes) {
|
let (list, name) = match retrieve_attr_list(attributes) {
|
||||||
Some(v) => v,
|
Some((Some(list), name)) => (list, name),
|
||||||
None => return (default_namespace, other_namespaces),
|
None => return (default_namespace, other_namespaces),
|
||||||
|
_ => panic!("wrong parameters"),
|
||||||
};
|
};
|
||||||
|
|
||||||
if list.path.get_ident().unwrap() == "namespace" {
|
if name == "namespace" {
|
||||||
let mut iter = list.nested.iter();
|
let mut iter = list.nested.iter();
|
||||||
if let Some(NestedMeta::Lit(Lit::Str(v))) = iter.next() {
|
if let Some(NestedMeta::Lit(Lit::Str(v))) = iter.next() {
|
||||||
default_namespace = Some(v.value());
|
default_namespace = v.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
for item in iter {
|
for item in iter {
|
||||||
|
@ -50,24 +52,26 @@ pub(crate) fn get_namespaces(
|
||||||
(default_namespace, other_namespaces)
|
(default_namespace, other_namespaces)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn retrieve_field_attribute(name: &str, input: &syn::Field) -> Option<FieldAttribute> {
|
pub(crate) fn retrieve_field_attribute(input: &syn::Field) -> Option<FieldAttribute> {
|
||||||
if let Some(list) = retrieve_attr_list(name, &input.attrs) {
|
match retrieve_attr_list(&input.attrs) {
|
||||||
match list.nested.first() {
|
Some((Some(list), name)) if name.as_str() == "namespace" => match list.nested.first() {
|
||||||
Some(NestedMeta::Lit(Lit::Str(v))) => {
|
Some(NestedMeta::Lit(Lit::Str(v))) => Some(FieldAttribute::Namespace(v.value())),
|
||||||
return Some(FieldAttribute::Namespace(v.value()));
|
|
||||||
}
|
|
||||||
Some(NestedMeta::Meta(Meta::Path(v))) => {
|
Some(NestedMeta::Meta(Meta::Path(v))) => {
|
||||||
if let Some(ident) = v.get_ident() {
|
if let Some(ident) = v.get_ident() {
|
||||||
return Some(FieldAttribute::PrefixIdentifier(ident.to_string()));
|
Some(FieldAttribute::PrefixIdentifier(ident.to_string()))
|
||||||
|
} else {
|
||||||
|
panic!("unexpected parameter");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => panic!("unexpected parameter"),
|
||||||
};
|
},
|
||||||
|
Some((None, name)) if name.as_str() == "attribute" => Some(FieldAttribute::Attribute),
|
||||||
|
None => None,
|
||||||
|
_ => panic!("unexpected parameter"),
|
||||||
}
|
}
|
||||||
None
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn retrieve_attr(name: &str, attributes: &Vec<syn::Attribute>) -> Option<bool> {
|
fn retrieve_attr_list(attributes: &Vec<syn::Attribute>) -> Option<(Option<syn::MetaList>, String)> {
|
||||||
for attr in attributes {
|
for attr in attributes {
|
||||||
if !attr.path.is_ident(XML) {
|
if !attr.path.is_ident(XML) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -75,41 +79,19 @@ pub(crate) fn retrieve_attr(name: &str, attributes: &Vec<syn::Attribute>) -> Opt
|
||||||
|
|
||||||
let nested = match attr.parse_meta() {
|
let nested = match attr.parse_meta() {
|
||||||
Ok(Meta::List(meta)) => meta.nested,
|
Ok(Meta::List(meta)) => meta.nested,
|
||||||
_ => return Some(false),
|
Ok(_) => todo!(),
|
||||||
};
|
_ => todo!(),
|
||||||
|
|
||||||
let path = match nested.first() {
|
|
||||||
Some(NestedMeta::Meta(Meta::Path(path))) => path,
|
|
||||||
_ => return Some(false),
|
|
||||||
};
|
|
||||||
|
|
||||||
if path.get_ident()? == name {
|
|
||||||
return Some(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
None
|
|
||||||
}
|
|
||||||
|
|
||||||
fn retrieve_attr_list(name: &str, attributes: &Vec<syn::Attribute>) -> Option<syn::MetaList> {
|
|
||||||
for attr in attributes {
|
|
||||||
if !attr.path.is_ident(XML) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
let nested = match attr.parse_meta() {
|
|
||||||
Ok(Meta::List(meta)) => meta.nested,
|
|
||||||
_ => return None,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let list = match nested.first() {
|
let list = match nested.first() {
|
||||||
Some(NestedMeta::Meta(Meta::List(list))) => list,
|
Some(NestedMeta::Meta(Meta::List(list))) => list,
|
||||||
|
Some(NestedMeta::Meta(Meta::Path(path))) => {
|
||||||
|
return Some((None, path.get_ident()?.to_string()))
|
||||||
|
}
|
||||||
_ => return None,
|
_ => return None,
|
||||||
};
|
};
|
||||||
|
|
||||||
if list.path.get_ident()? == name {
|
return Some((Some(list.to_owned()), list.path.get_ident()?.to_string()));
|
||||||
return Some(list.to_owned());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
None
|
None
|
||||||
|
@ -158,7 +140,7 @@ pub fn to_xml(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
||||||
// Check if prefix exist
|
// Check if prefix exist
|
||||||
#(
|
#(
|
||||||
if serializer.parent_prefixes.get(#missing_prefixes).is_none() {
|
if serializer.parent_prefixes.get(#missing_prefixes).is_none() {
|
||||||
return Err(instant_xml::Error::UnexpectedPrefix);
|
return Err(instant_xml::Error::WrongNamespace);
|
||||||
}
|
}
|
||||||
)*;
|
)*;
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ use quote::quote;
|
||||||
use crate::{get_namespaces, retrieve_field_attribute, FieldAttribute};
|
use crate::{get_namespaces, retrieve_field_attribute, FieldAttribute};
|
||||||
|
|
||||||
pub struct Serializer {
|
pub struct Serializer {
|
||||||
default_namespace: Option<String>,
|
default_namespace: String,
|
||||||
other_namespaces: HashMap<String, String>,
|
other_namespaces: HashMap<String, String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,7 +33,8 @@ impl<'a> Serializer {
|
||||||
serializer.output.write_str(field_context.name)?;
|
serializer.output.write_str(field_context.name)?;
|
||||||
));
|
));
|
||||||
|
|
||||||
if let Some(default_namespace) = self.default_namespace.as_ref() {
|
if !self.default_namespace.is_empty() {
|
||||||
|
let default_namespace = &self.default_namespace;
|
||||||
output.extend(quote!(
|
output.extend(quote!(
|
||||||
serializer.output.write_str(" xmlns=\"")?;
|
serializer.output.write_str(" xmlns=\"")?;
|
||||||
serializer.output.write_str(#default_namespace)?;
|
serializer.output.write_str(#default_namespace)?;
|
||||||
|
@ -82,7 +83,7 @@ impl<'a> Serializer {
|
||||||
};
|
};
|
||||||
));
|
));
|
||||||
|
|
||||||
match retrieve_field_attribute("namespace", field) {
|
match retrieve_field_attribute(field) {
|
||||||
Some(FieldAttribute::Namespace(namespace_key)) => {
|
Some(FieldAttribute::Namespace(namespace_key)) => {
|
||||||
output.extend(quote!(
|
output.extend(quote!(
|
||||||
field.attribute = Some(instant_xml::FieldAttribute::Namespace(#namespace_key));
|
field.attribute = Some(instant_xml::FieldAttribute::Namespace(#namespace_key));
|
||||||
|
|
|
@ -14,11 +14,8 @@ pub mod parse;
|
||||||
pub struct TagData<'xml> {
|
pub struct TagData<'xml> {
|
||||||
pub key: &'xml str,
|
pub key: &'xml str,
|
||||||
pub attributes: Vec<(&'xml str, &'xml str)>,
|
pub attributes: Vec<(&'xml str, &'xml str)>,
|
||||||
|
|
||||||
// TODO: handle default namespace
|
|
||||||
pub default_namespace: Option<&'xml str>,
|
pub default_namespace: Option<&'xml str>,
|
||||||
|
pub namespaces: HashMap<&'xml str, &'xml str>,
|
||||||
pub namespaces: Option<HashMap<&'xml str, &'xml str>>,
|
|
||||||
pub prefix: Option<&'xml str>,
|
pub prefix: Option<&'xml str>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -236,18 +233,26 @@ pub trait Visitor<'xml>: Sized {
|
||||||
|
|
||||||
pub struct Deserializer<'xml> {
|
pub struct Deserializer<'xml> {
|
||||||
parser: XmlParser<'xml>,
|
parser: XmlParser<'xml>,
|
||||||
namespaces: HashMap<&'xml str, &'xml str>,
|
def_namespaces: HashMap<&'xml str, &'xml str>,
|
||||||
|
parser_namespaces: HashMap<&'xml str, &'xml str>,
|
||||||
|
def_defualt_namespace: &'xml str,
|
||||||
|
parser_defualt_namespace: &'xml str,
|
||||||
tag_attributes: Vec<(&'xml str, &'xml str)>,
|
tag_attributes: Vec<(&'xml str, &'xml str)>,
|
||||||
next_type: EntityType,
|
next_type: EntityType,
|
||||||
|
next_def_namespace: Option<&'xml str>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'xml> Deserializer<'xml> {
|
impl<'xml> Deserializer<'xml> {
|
||||||
pub fn new(input: &'xml str) -> Self {
|
pub fn new(input: &'xml str) -> Self {
|
||||||
Self {
|
Self {
|
||||||
parser: XmlParser::new(input),
|
parser: XmlParser::new(input),
|
||||||
namespaces: std::collections::HashMap::new(),
|
def_namespaces: std::collections::HashMap::new(),
|
||||||
|
parser_namespaces: std::collections::HashMap::new(),
|
||||||
|
def_defualt_namespace: "",
|
||||||
|
parser_defualt_namespace: "",
|
||||||
tag_attributes: Vec::new(),
|
tag_attributes: Vec::new(),
|
||||||
next_type: EntityType::Element,
|
next_type: EntityType::Element,
|
||||||
|
next_def_namespace: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -255,8 +260,16 @@ impl<'xml> Deserializer<'xml> {
|
||||||
self.parser.peek_next_tag()
|
self.parser.peek_next_tag()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn verify_namespace(&self, namespace_to_verify: &str) -> bool {
|
pub fn get_def_namespace(&self, prefix: &str) -> Option<&&str> {
|
||||||
self.namespaces.get(namespace_to_verify).is_some()
|
self.def_namespaces.get(prefix)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_parser_namespace(&self, prefix: &str) -> Option<&&str> {
|
||||||
|
self.parser_namespaces.get(prefix)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn compare_parser_and_def_default_namespaces(&self) -> bool {
|
||||||
|
self.parser_defualt_namespace == self.def_defualt_namespace
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn peek_next_attribute(&self) -> Option<&(&'xml str, &'xml str)> {
|
pub fn peek_next_attribute(&self) -> Option<&(&'xml str, &'xml str)> {
|
||||||
|
@ -267,24 +280,79 @@ impl<'xml> Deserializer<'xml> {
|
||||||
&mut self,
|
&mut self,
|
||||||
visitor: V,
|
visitor: V,
|
||||||
name: &str,
|
name: &str,
|
||||||
namespaces: &HashMap<&'xml str, &'xml str>,
|
def_default_namespace: &'xml str,
|
||||||
|
def_namespaces: &HashMap<&'xml str, &'xml str>,
|
||||||
) -> Result<V::Value, Error>
|
) -> Result<V::Value, Error>
|
||||||
where
|
where
|
||||||
V: Visitor<'xml>,
|
V: Visitor<'xml>,
|
||||||
{
|
{
|
||||||
let new_namespaces = namespaces
|
// Saveing current defined default namespace
|
||||||
|
let def_defualt_namespace_to_revert = self.def_defualt_namespace;
|
||||||
|
self.def_defualt_namespace = def_default_namespace;
|
||||||
|
|
||||||
|
// Adding struct defined namespaces
|
||||||
|
let new_def_namespaces = def_namespaces
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|(k, v)| self.namespaces.insert(k, v).is_none())
|
.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_defualt_namespace_to_revert = self.parser_defualt_namespace;
|
||||||
|
|
||||||
|
// Set parser default namespace
|
||||||
|
match tag_data.default_namespace {
|
||||||
|
Some(namespace) => {
|
||||||
|
self.parser_defualt_namespace = namespace;
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
// If there is no default namespace in the tag, check if parent default namespace equals the current one
|
||||||
|
if def_defualt_namespace_to_revert != self.def_defualt_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<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
self.process_open_tag(name, namespaces)?;
|
|
||||||
let ret = visitor.visit_struct(self)?;
|
let ret = visitor.visit_struct(self)?;
|
||||||
|
|
||||||
|
// Process close tag
|
||||||
self.check_close_tag(name)?;
|
self.check_close_tag(name)?;
|
||||||
let _ = new_namespaces
|
|
||||||
.iter()
|
|
||||||
.map(|(k, _)| self.namespaces.remove(*k));
|
|
||||||
|
|
||||||
|
// 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_defualt_namespace = def_defualt_namespace_to_revert;
|
||||||
|
|
||||||
|
// Retriving old parser namespace
|
||||||
|
self.parser_defualt_namespace = parser_defualt_namespace_to_revert;
|
||||||
Ok(ret)
|
Ok(ret)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -303,11 +371,35 @@ impl<'xml> Deserializer<'xml> {
|
||||||
ret
|
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_bool<V>(&mut self, visitor: V) -> Result<V::Value, Error>
|
fn deserialize_bool<V>(&mut self, visitor: V) -> Result<V::Value, Error>
|
||||||
where
|
where
|
||||||
V: Visitor<'xml>,
|
V: Visitor<'xml>,
|
||||||
{
|
{
|
||||||
self.parser.next();
|
// 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() {
|
match self.parser.next() {
|
||||||
Some(Ok(XmlRecord::Element(v))) => {
|
Some(Ok(XmlRecord::Element(v))) => {
|
||||||
let ret = visitor.visit_str(v);
|
let ret = visitor.visit_str(v);
|
||||||
|
@ -328,28 +420,6 @@ impl<'xml> Deserializer<'xml> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn process_open_tag(
|
|
||||||
&mut self,
|
|
||||||
name: &str,
|
|
||||||
namespaces: &HashMap<&'xml str, &'xml str>,
|
|
||||||
) -> Result<(), Error> {
|
|
||||||
let item = match self.parser.next() {
|
|
||||||
Some(Ok(XmlRecord::Open(item))) if item.key == name => item,
|
|
||||||
_ => return Err(Error::UnexpectedValue),
|
|
||||||
};
|
|
||||||
|
|
||||||
for (k, v) in item.namespaces.unwrap() {
|
|
||||||
match namespaces.get(k) {
|
|
||||||
Some(item) if *item != v => return Err(Error::UnexpectedPrefix),
|
|
||||||
None => return Err(Error::MissingdPrefix),
|
|
||||||
_ => (),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
self.tag_attributes = item.attributes;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn check_close_tag(&mut self, name: &str) -> Result<(), Error> {
|
fn check_close_tag(&mut self, name: &str) -> Result<(), Error> {
|
||||||
let item = match self.parser.next() {
|
let item = match self.parser.next() {
|
||||||
Some(item) => item?,
|
Some(item) => item?,
|
||||||
|
@ -370,7 +440,7 @@ struct State<'a> {
|
||||||
prefix: HashMap<&'a str, &'a str>,
|
prefix: HashMap<&'a str, &'a str>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error, PartialEq, Eq)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
#[error("format: {0}")]
|
#[error("format: {0}")]
|
||||||
Format(#[from] fmt::Error),
|
Format(#[from] fmt::Error),
|
||||||
|
@ -392,8 +462,8 @@ pub enum Error {
|
||||||
UnexpectedToken,
|
UnexpectedToken,
|
||||||
#[error("missing prefix")]
|
#[error("missing prefix")]
|
||||||
MissingdPrefix,
|
MissingdPrefix,
|
||||||
#[error("unexpected prefix")]
|
|
||||||
UnexpectedPrefix,
|
|
||||||
#[error("unexpected state")]
|
#[error("unexpected state")]
|
||||||
UnexpectedState,
|
UnexpectedState,
|
||||||
|
#[error("wrong namespace")]
|
||||||
|
WrongNamespace,
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,8 +35,8 @@ impl<'a> XmlParser<'a> {
|
||||||
Ok(Some(XmlRecord::Open(TagData {
|
Ok(Some(XmlRecord::Open(TagData {
|
||||||
key: local,
|
key: local,
|
||||||
attributes: Vec::new(),
|
attributes: Vec::new(),
|
||||||
default_namespace: None,
|
default_namespace: Some(""),
|
||||||
namespaces: None,
|
namespaces: HashMap::new(),
|
||||||
prefix,
|
prefix,
|
||||||
})))
|
})))
|
||||||
}
|
}
|
||||||
|
@ -89,7 +89,7 @@ impl<'xml> Iterator for XmlParser<'xml> {
|
||||||
key: key.unwrap(),
|
key: key.unwrap(),
|
||||||
attributes,
|
attributes,
|
||||||
default_namespace,
|
default_namespace,
|
||||||
namespaces: Some(namespaces),
|
namespaces,
|
||||||
prefix: prefix_ret,
|
prefix: prefix_ret,
|
||||||
})));
|
})));
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use instant_xml::{FromXml, ToXml};
|
use instant_xml::{Error, FromXml, ToXml};
|
||||||
|
|
||||||
#[derive(Debug, Eq, PartialEq, ToXml, FromXml)]
|
#[derive(Debug, Eq, PartialEq, ToXml)]
|
||||||
struct Nested {
|
struct Nested {
|
||||||
#[xml(namespace(bar))]
|
#[xml(namespace(bar))]
|
||||||
flag: bool,
|
flag: bool,
|
||||||
|
@ -66,6 +66,13 @@ fn struct_with_custom_field() {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Eq, PartialEq, ToXml, FromXml)]
|
||||||
|
#[xml(namespace("URI", bar = "BAZ"))]
|
||||||
|
struct NestedDe {
|
||||||
|
#[xml(namespace(bar))]
|
||||||
|
flag: bool,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Eq, PartialEq, ToXml)]
|
#[derive(Debug, Eq, PartialEq, ToXml)]
|
||||||
#[xml(namespace("URI", bar = "BAZ", foo = "BAR"))]
|
#[xml(namespace("URI", bar = "BAZ", foo = "BAR"))]
|
||||||
struct StructWithCustomFieldWrongPrefix {
|
struct StructWithCustomFieldWrongPrefix {
|
||||||
|
@ -89,31 +96,238 @@ struct StructWithCustomFieldFromXml {
|
||||||
flag: bool,
|
flag: bool,
|
||||||
#[xml(attribute)]
|
#[xml(attribute)]
|
||||||
flag_attribute: bool,
|
flag_attribute: bool,
|
||||||
test: Nested,
|
test: NestedDe,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn struct_with_custom_field_from_xml() {
|
fn struct_with_custom_field_from_xml() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
StructWithCustomFieldFromXml::from_xml("<StructWithCustomFieldFromXml flag_attribute=\"true\" xmlns=\"URI\" xmlns:bar=\"BAZ\" xmlns:foo=\"BAR\"><bar:flag>false</bar:flag><Nested><flag>true</flag></Nested></StructWithCustomFieldFromXml>").unwrap(),
|
StructWithCustomFieldFromXml::from_xml("<StructWithCustomFieldFromXml flag_attribute=\"true\" xmlns=\"URI\" xmlns:bar=\"BAZ\" xmlns:foo=\"BAR\"><bar:flag>false</bar:flag><NestedDe><bar:flag>true</bar:flag></NestedDe></StructWithCustomFieldFromXml>").unwrap(),
|
||||||
StructWithCustomFieldFromXml {
|
StructWithCustomFieldFromXml {
|
||||||
flag: false,
|
flag: false,
|
||||||
flag_attribute: true,
|
flag_attribute: true,
|
||||||
test: Nested { flag: true }
|
test: NestedDe { flag: true }
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
// Different order
|
// Different order
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
StructWithCustomFieldFromXml::from_xml("<StructWithCustomFieldFromXml xmlns=\"URI\" xmlns:bar=\"BAZ\" xmlns:foo=\"BAR\" flag_attribute=\"true\"><Nested><flag>true</flag></Nested><flag>false</flag></StructWithCustomFieldFromXml>").unwrap(),
|
StructWithCustomFieldFromXml::from_xml("<StructWithCustomFieldFromXml xmlns=\"URI\" xmlns:bar=\"BAZ\" xmlns:foo=\"BAR\" flag_attribute=\"true\"><NestedDe><bar:flag>true</bar:flag></NestedDe><bar:flag>false</bar:flag></StructWithCustomFieldFromXml>").unwrap(),
|
||||||
StructWithCustomFieldFromXml {
|
StructWithCustomFieldFromXml {
|
||||||
flag: false,
|
flag: false,
|
||||||
flag_attribute: true,
|
flag_attribute: true,
|
||||||
test: Nested { flag: true }
|
test: NestedDe { flag: true }
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// Different prefixes then in definition
|
||||||
|
assert_eq!(
|
||||||
|
StructWithCustomFieldFromXml::from_xml("<StructWithCustomFieldFromXml flag_attribute=\"true\" xmlns=\"URI\" xmlns:grr=\"BAZ\" xmlns:foo=\"BAR\"><grr:flag>false</grr:flag><NestedDe><grr:flag>true</grr:flag></NestedDe></StructWithCustomFieldFromXml>").unwrap(),
|
||||||
|
StructWithCustomFieldFromXml {
|
||||||
|
flag: false,
|
||||||
|
flag_attribute: true,
|
||||||
|
test: NestedDe { flag: true }
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Nested::from_xml("<Nested><flag>true</flag></Nested>").unwrap(),
|
NestedDe::from_xml(
|
||||||
Nested { flag: true }
|
"<NestedDe xmlns=\"URI\" xmlns:bar=\"BAZ\"><bar:flag>true</bar:flag></NestedDe>"
|
||||||
|
)
|
||||||
|
.unwrap(),
|
||||||
|
NestedDe { flag: true }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Eq, PartialEq, ToXml, FromXml)]
|
||||||
|
struct NestedWrongNamespace {
|
||||||
|
flag: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Eq, PartialEq, FromXml)]
|
||||||
|
#[xml(namespace("URI", bar = "BAZ"))]
|
||||||
|
struct StructWithCorrectNestedNamespace {
|
||||||
|
test: NestedDe,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Eq, PartialEq, FromXml)]
|
||||||
|
#[xml(namespace("URI", bar = "BAZ"))]
|
||||||
|
struct StructWithWrongNestedNamespace {
|
||||||
|
test: NestedWrongNamespace,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn default_namespaces() {
|
||||||
|
// Default namespace not-nested
|
||||||
|
assert_eq!(
|
||||||
|
NestedDe::from_xml(
|
||||||
|
"<NestedDe xmlns=\"URI\" xmlns:bar=\"BAZ\"><bar:flag>true</bar:flag></NestedDe>"
|
||||||
|
)
|
||||||
|
.unwrap(),
|
||||||
|
NestedDe { flag: true }
|
||||||
|
);
|
||||||
|
|
||||||
|
// Default namespace not-nested - wrong namespace
|
||||||
|
assert_eq!(
|
||||||
|
NestedDe::from_xml(
|
||||||
|
"<NestedDe xmlns=\"WRONG\" xmlns:bar=\"BAZ\"><bar:flag>true</bar:flag></NestedDe>"
|
||||||
|
)
|
||||||
|
.unwrap_err(),
|
||||||
|
Error::WrongNamespace
|
||||||
|
);
|
||||||
|
|
||||||
|
// Correct child namespace
|
||||||
|
assert_eq!(
|
||||||
|
StructWithCorrectNestedNamespace::from_xml("<StructWithCorrectNestedNamespace xmlns=\"URI\" xmlns:bar=\"BAZ\"><NestedDe xmlns=\"URI\" xmlns:bar=\"BAZ\"><bar:flag>true</bar:flag></NestedDe></StructWithCorrectNestedNamespace>").unwrap(),
|
||||||
|
StructWithCorrectNestedNamespace {
|
||||||
|
test: NestedDe { flag: true }
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// Correct child namespace - without child redefinition
|
||||||
|
assert_eq!(
|
||||||
|
StructWithCorrectNestedNamespace::from_xml("<StructWithCorrectNestedNamespace xmlns=\"URI\" xmlns:bar=\"BAZ\"><NestedDe><bar:flag>true</bar:flag></NestedDe></StructWithCorrectNestedNamespace>").unwrap(),
|
||||||
|
StructWithCorrectNestedNamespace {
|
||||||
|
test: NestedDe { flag: true }
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// Different child namespace
|
||||||
|
assert_eq!(
|
||||||
|
StructWithWrongNestedNamespace::from_xml("<StructWithWrongNestedNamespace xmlns=\"URI\" xmlns:dar=\"BAZ\"><NestedWrongNamespace xmlns=\"\"><flag>true</flag></NestedWrongNamespace></StructWithWrongNestedNamespace>").unwrap(),
|
||||||
|
StructWithWrongNestedNamespace {
|
||||||
|
test: NestedWrongNamespace {
|
||||||
|
flag: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// Wrong child namespace
|
||||||
|
assert_eq!(
|
||||||
|
StructWithWrongNestedNamespace::from_xml("<StructWithWrongNestedNamespace xmlns=\"URI\" xmlns:dar=\"BAZ\"><NestedWrongNamespace><flag>true</flag></NestedWrongNamespace></StructWithWrongNestedNamespace>").unwrap_err(),
|
||||||
|
Error::WrongNamespace
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Eq, PartialEq, FromXml)]
|
||||||
|
#[xml(namespace("URI", bar = "BAZ"))]
|
||||||
|
struct NestedOtherNamespace {
|
||||||
|
#[xml(namespace(bar))]
|
||||||
|
flag: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Eq, PartialEq, FromXml)]
|
||||||
|
#[xml(namespace("URI", bar = "BAZ"))]
|
||||||
|
struct StructOtherNamespace {
|
||||||
|
test: NestedOtherNamespace,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn other_namespaces() {
|
||||||
|
// Other namespace not-nested
|
||||||
|
assert_eq!(
|
||||||
|
NestedOtherNamespace::from_xml(
|
||||||
|
"<NestedOtherNamespace xmlns=\"URI\" xmlns:bar=\"BAZ\"><bar:flag>true</bar:flag></NestedOtherNamespace>"
|
||||||
|
)
|
||||||
|
.unwrap(),
|
||||||
|
NestedOtherNamespace { flag: true }
|
||||||
|
);
|
||||||
|
|
||||||
|
// Other namespace not-nested - wrong defined namespace
|
||||||
|
assert_eq!(
|
||||||
|
NestedOtherNamespace::from_xml(
|
||||||
|
"<NestedOtherNamespace xmlns=\"URI\" xmlns:bar=\"BAZ\"><wrong:flag>true</wrong:flag></NestedOtherNamespace>"
|
||||||
|
)
|
||||||
|
.unwrap_err(),
|
||||||
|
Error::WrongNamespace
|
||||||
|
);
|
||||||
|
|
||||||
|
// Other namespace not-nested - wrong parser namespace
|
||||||
|
assert_eq!(
|
||||||
|
NestedOtherNamespace::from_xml(
|
||||||
|
"<NestedOtherNamespace xmlns=\"URI\" xmlns:bar=\"WRONG\"><bar:flag>true</bar:flag></NestedOtherNamespace>"
|
||||||
|
)
|
||||||
|
.unwrap_err(),
|
||||||
|
Error::WrongNamespace
|
||||||
|
);
|
||||||
|
|
||||||
|
// Other namespace not-nested - missing parser prefix
|
||||||
|
assert_eq!(
|
||||||
|
NestedOtherNamespace::from_xml(
|
||||||
|
"<NestedOtherNamespace xmlns=\"URI\" xmlns:bar=\"BAR\"><flag>true</flag></NestedOtherNamespace>"
|
||||||
|
)
|
||||||
|
.unwrap_err(),
|
||||||
|
Error::WrongNamespace
|
||||||
|
);
|
||||||
|
|
||||||
|
// Correct child other namespace
|
||||||
|
assert_eq!(
|
||||||
|
StructOtherNamespace::from_xml(
|
||||||
|
"<StructOtherNamespace xmlns=\"URI\" xmlns:bar=\"BAZ\"><NestedOtherNamespace xmlns=\"URI\" xmlns:bar=\"BAZ\"><bar:flag>true</bar:flag></NestedOtherNamespace></StructOtherNamespace>"
|
||||||
|
)
|
||||||
|
.unwrap(),
|
||||||
|
StructOtherNamespace {
|
||||||
|
test: NestedOtherNamespace {
|
||||||
|
flag: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// Correct child other namespace - without child redefinition
|
||||||
|
assert_eq!(
|
||||||
|
StructOtherNamespace::from_xml(
|
||||||
|
"<StructOtherNamespace xmlns=\"URI\" xmlns:bar=\"BAZ\"><NestedOtherNamespace><bar:flag>true</bar:flag></NestedOtherNamespace></StructOtherNamespace>"
|
||||||
|
)
|
||||||
|
.unwrap(),
|
||||||
|
StructOtherNamespace {
|
||||||
|
test: NestedOtherNamespace {
|
||||||
|
flag: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// Wrong child other namespace - without child redefinition
|
||||||
|
assert_eq!(
|
||||||
|
StructOtherNamespace::from_xml(
|
||||||
|
"<StructOtherNamespace xmlns=\"URI\" xmlns:bar=\"BAZ\"><NestedOtherNamespace><wrong:flag>true</wrong:flag></NestedOtherNamespace></StructOtherNamespace>"
|
||||||
|
)
|
||||||
|
.unwrap_err(),
|
||||||
|
Error::WrongNamespace
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Eq, PartialEq, FromXml)]
|
||||||
|
#[xml(namespace("URI"))]
|
||||||
|
struct StructDirectNamespace {
|
||||||
|
#[xml(namespace("BAZ"))]
|
||||||
|
flag: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn direct_namespaces() {
|
||||||
|
// Correct direct namespace
|
||||||
|
assert_eq!(
|
||||||
|
StructDirectNamespace::from_xml(
|
||||||
|
"<StructDirectNamespace xmlns=\"URI\"><flag xmlns=\"BAZ\">true</flag></StructDirectNamespace>"
|
||||||
|
)
|
||||||
|
.unwrap(),
|
||||||
|
StructDirectNamespace { flag: true }
|
||||||
|
);
|
||||||
|
|
||||||
|
// Wrong direct namespace
|
||||||
|
assert_eq!(
|
||||||
|
StructDirectNamespace::from_xml(
|
||||||
|
"<StructDirectNamespace xmlns=\"URI\"><flag xmlns=\"WRONG\">true</flag></StructDirectNamespace>"
|
||||||
|
)
|
||||||
|
.unwrap_err(),
|
||||||
|
Error::WrongNamespace
|
||||||
|
);
|
||||||
|
|
||||||
|
// Wrong direct namespace - missing namespace
|
||||||
|
assert_eq!(
|
||||||
|
StructDirectNamespace::from_xml(
|
||||||
|
"<StructDirectNamespace xmlns=\"URI\"><flag>true</flag></StructDirectNamespace>"
|
||||||
|
)
|
||||||
|
.unwrap_err(),
|
||||||
|
Error::WrongNamespace
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue