fix check namespace

This commit is contained in:
Marc-Antoine Arnaud 2018-12-29 14:13:50 +01:00
parent d398fa47d6
commit ae3f873d69
3 changed files with 173 additions and 29 deletions

View File

@ -22,16 +22,22 @@ fn de_struct_namespace() {
#[yaserde(
root = "book",
prefix = "ns",
namespace = "ns: http://www.sample.com/ns/domain"
namespace = "ns: http://www.sample.com/ns/domain",
namespace = "ns2: http://www.sample.com/ns/domain_2",
)]
pub struct Book {
#[yaserde(prefix = "ns")]
author: String,
#[yaserde(prefix = "ns")]
#[yaserde(prefix = "ns2")]
title: String,
}
let content = "<?xml version=\"1.0\" encoding=\"utf-8\"?><ns:book xmlns:ns=\"http://www.sample.com/ns/domain\"><ns:author>Antoine de Saint-Exupéry</ns:author><ns:title>Little prince</ns:title></ns:book>";
let content = r#"<?xml version="1.0" encoding="utf-8"?>
<ns:book xmlns:ns="http://www.sample.com/ns/domain" xmlns:ns2="http://www.sample.com/ns/domain_2">
<ns:author>Antoine de Saint-Exupéry</ns:author>
<ns2:title>Little prince</ns2:title>
</ns:book>
"#;
convert_and_validate!(
content,
Book,
@ -41,9 +47,43 @@ fn de_struct_namespace() {
}
);
let content = "<?xml version=\"1.0\" encoding=\"utf-8\"?><ns:book xmlns:ns=\"http://www.sample.com/ns/domain2\"><ns:author>Antoine de Saint-Exupéry</ns:author><ns:title>Little prince</ns:title></ns:book>";
let content = r#"<?xml version="1.0" encoding="utf-8"?>
<ns:book xmlns:ns="http://www.sample.com/ns/domain">
<ns:author>Antoine de Saint-Exupéry</ns:author>
<ns2:title xmlns:ns2="http://www.sample.com/ns/domain_2">Little prince</ns2:title>
</ns:book>
"#;
convert_and_validate!(
content,
Book,
Book {
author: String::from("Antoine de Saint-Exupéry"),
title: String::from("Little prince"),
}
);
let content = r#"<?xml version="1.0" encoding="utf-8"?>
<book xmlns="http://www.sample.com/ns/domain">
<author>Antoine de Saint-Exupéry</author>
<ns2:title xmlns:ns2="http://www.sample.com/ns/domain_2">Little prince</ns2:title>
</book>
"#;
convert_and_validate!(
content,
Book,
Book {
author: String::from("Antoine de Saint-Exupéry"),
title: String::from("Little prince"),
}
);
let content = r#"<?xml version="1.0" encoding="utf-8"?>
<ns:book xmlns:ns="http://www.sample.com/ns/domain2">
<ns:author>Antoine de Saint-Exupéry</ns:author>
<ns:title>Little prince</ns:title>
</ns:book>"#;
let loaded: Result<Book, String> = from_str(content);
assert_eq!(loaded, Err("bad namespace for book with http://www.sample.com/ns/domain".to_string()));
assert_eq!(loaded, Err("bad namespace for book, found http://www.sample.com/ns/domain2".to_string()));
}
#[test]

View File

@ -11,24 +11,19 @@ pub fn parse(
data_struct: &DataStruct,
name: &Ident,
root: &str,
prefix: &Option<String>,
namespaces: &BTreeMap<String, String>,
) -> TokenStream {
let validate_namespace: TokenStream = namespaces
let namespaces_matches: TokenStream = namespaces
.iter()
.map(|(_prefix, namespace)| {
Some(quote!(
let mut found = false;
debug!("{:?}", namespace);
for (key, value) in namespace {
if #namespace == value {
found = true;
}
}
if !found {
let msg = format!("bad namespace for {} with {}", name.local_name.as_str(), #namespace);
return Err(msg);
}
))
.map(|(p, ns)| {
let str_ns = ns.as_str();
if *prefix == Some(p.to_string()) {
Some(quote!(#str_ns => {}))
} else {
None
}
})
.filter(|x| x.is_some())
.map(|x| x.unwrap())
@ -324,8 +319,7 @@ pub fn parse(
}
})
}
dude => {
println!("{:?}", dude);
_ => {
unimplemented!();
}
}
@ -421,6 +415,8 @@ pub fn parse(
&visitor_label,
label,
&label_name,
&field_attrs.prefix,
&namespaces,
)
}
Some(FieldType::FieldTypeBool) => {
@ -432,6 +428,8 @@ pub fn parse(
&visitor_label,
label,
&label_name,
&field_attrs.prefix,
&namespaces,
)
}
Some(FieldType::FieldTypeI8) => {
@ -443,6 +441,8 @@ pub fn parse(
&visitor_label,
label,
&label_name,
&field_attrs.prefix,
&namespaces,
)
}
Some(FieldType::FieldTypeU8) => {
@ -454,6 +454,8 @@ pub fn parse(
&visitor_label,
label,
&label_name,
&field_attrs.prefix,
&namespaces,
)
}
Some(FieldType::FieldTypeU16) => {
@ -465,6 +467,8 @@ pub fn parse(
&visitor_label,
label,
&label_name,
&field_attrs.prefix,
&namespaces,
)
}
Some(FieldType::FieldTypeI16) => {
@ -476,6 +480,8 @@ pub fn parse(
&visitor_label,
label,
&label_name,
&field_attrs.prefix,
&namespaces,
)
}
Some(FieldType::FieldTypeU32) => {
@ -487,6 +493,8 @@ pub fn parse(
&visitor_label,
label,
&label_name,
&field_attrs.prefix,
&namespaces,
)
}
Some(FieldType::FieldTypeI32) => {
@ -498,6 +506,8 @@ pub fn parse(
&visitor_label,
label,
&label_name,
&field_attrs.prefix,
&namespaces,
)
}
Some(FieldType::FieldTypeU64) => {
@ -509,6 +519,8 @@ pub fn parse(
&visitor_label,
label,
&label_name,
&field_attrs.prefix,
&namespaces,
)
}
Some(FieldType::FieldTypeI64) => {
@ -520,6 +532,8 @@ pub fn parse(
&visitor_label,
label,
&label_name,
&field_attrs.prefix,
&namespaces,
)
}
Some(FieldType::FieldTypeF32) => {
@ -531,6 +545,8 @@ pub fn parse(
&visitor_label,
label,
&label_name,
&field_attrs.prefix,
&namespaces,
)
}
Some(FieldType::FieldTypeF64) => {
@ -542,6 +558,8 @@ pub fn parse(
&visitor_label,
label,
&label_name,
&field_attrs.prefix,
&namespaces,
)
}
Some(FieldType::FieldTypeStruct { struct_name }) => Some(quote! {
@ -570,6 +588,8 @@ pub fn parse(
&visitor_label,
label,
&label_name,
&field_attrs.prefix,
&namespaces,
)
}
Some(&FieldType::FieldTypeBool) => {
@ -581,6 +601,8 @@ pub fn parse(
&visitor_label,
label,
&label_name,
&field_attrs.prefix,
&namespaces,
)
}
Some(&FieldType::FieldTypeU8) => {
@ -592,6 +614,8 @@ pub fn parse(
&visitor_label,
label,
&label_name,
&field_attrs.prefix,
&namespaces,
)
}
Some(&FieldType::FieldTypeI8) => {
@ -603,6 +627,8 @@ pub fn parse(
&visitor_label,
label,
&label_name,
&field_attrs.prefix,
&namespaces,
)
}
Some(&FieldType::FieldTypeU16) => {
@ -614,6 +640,8 @@ pub fn parse(
&visitor_label,
label,
&label_name,
&field_attrs.prefix,
&namespaces,
)
}
Some(&FieldType::FieldTypeI16) => {
@ -625,6 +653,8 @@ pub fn parse(
&visitor_label,
label,
&label_name,
&field_attrs.prefix,
&namespaces,
)
}
Some(&FieldType::FieldTypeU32) => {
@ -636,6 +666,8 @@ pub fn parse(
&visitor_label,
label,
&label_name,
&field_attrs.prefix,
&namespaces,
)
}
Some(&FieldType::FieldTypeI32) => {
@ -647,6 +679,8 @@ pub fn parse(
&visitor_label,
label,
&label_name,
&field_attrs.prefix,
&namespaces,
)
}
Some(&FieldType::FieldTypeU64) => {
@ -658,6 +692,8 @@ pub fn parse(
&visitor_label,
label,
&label_name,
&field_attrs.prefix,
&namespaces,
)
}
Some(&FieldType::FieldTypeI64) => {
@ -669,6 +705,8 @@ pub fn parse(
&visitor_label,
label,
&label_name,
&field_attrs.prefix,
&namespaces,
)
}
Some(&FieldType::FieldTypeF32) => {
@ -680,6 +718,8 @@ pub fn parse(
&visitor_label,
label,
&label_name,
&field_attrs.prefix,
&namespaces,
)
}
Some(&FieldType::FieldTypeF64) => {
@ -691,6 +731,8 @@ pub fn parse(
&visitor_label,
label,
&label_name,
&field_attrs.prefix,
&namespaces,
)
}
Some(&FieldType::FieldTypeStruct { ref struct_name }) => {
@ -725,6 +767,8 @@ pub fn parse(
&visitor_label,
label,
&label_name,
&field_attrs.prefix,
&namespaces,
)
}
Some(&FieldType::FieldTypeBool) => {
@ -736,6 +780,8 @@ pub fn parse(
&visitor_label,
label,
&label_name,
&field_attrs.prefix,
&namespaces,
)
}
Some(&FieldType::FieldTypeI8) => {
@ -747,6 +793,8 @@ pub fn parse(
&visitor_label,
label,
&label_name,
&field_attrs.prefix,
&namespaces,
)
}
Some(&FieldType::FieldTypeU8) => {
@ -758,6 +806,8 @@ pub fn parse(
&visitor_label,
label,
&label_name,
&field_attrs.prefix,
&namespaces,
)
}
Some(&FieldType::FieldTypeI16) => {
@ -769,6 +819,8 @@ pub fn parse(
&visitor_label,
label,
&label_name,
&field_attrs.prefix,
&namespaces,
)
}
Some(&FieldType::FieldTypeU16) => {
@ -780,6 +832,8 @@ pub fn parse(
&visitor_label,
label,
&label_name,
&field_attrs.prefix,
&namespaces,
)
}
Some(&FieldType::FieldTypeI32) => {
@ -791,6 +845,8 @@ pub fn parse(
&visitor_label,
label,
&label_name,
&field_attrs.prefix,
&namespaces,
)
}
Some(&FieldType::FieldTypeU32) => {
@ -802,6 +858,8 @@ pub fn parse(
&visitor_label,
label,
&label_name,
&field_attrs.prefix,
&namespaces,
)
}
Some(&FieldType::FieldTypeI64) => {
@ -813,6 +871,8 @@ pub fn parse(
&visitor_label,
label,
&label_name,
&field_attrs.prefix,
&namespaces,
)
}
Some(&FieldType::FieldTypeU64) => {
@ -824,6 +884,8 @@ pub fn parse(
&visitor_label,
label,
&label_name,
&field_attrs.prefix,
&namespaces,
)
}
Some(&FieldType::FieldTypeF32) => {
@ -835,6 +897,8 @@ pub fn parse(
&visitor_label,
label,
&label_name,
&field_attrs.prefix,
&namespaces,
)
}
Some(&FieldType::FieldTypeF64) => {
@ -846,6 +910,8 @@ pub fn parse(
&visitor_label,
label,
&label_name,
&field_attrs.prefix,
&namespaces,
)
}
Some(&FieldType::FieldTypeStruct { ref struct_name }) => {
@ -1209,21 +1275,30 @@ pub fn parse(
impl YaDeserialize for #name {
#[allow(unused_variables)]
fn deserialize<R: Read>(reader: &mut yaserde::de::Deserializer<R>) -> Result<Self, String> {
let named_element =
let (named_element, struct_namespace) =
if let XmlEvent::StartElement{name, ..} = reader.peek()?.to_owned() {
name.local_name.to_owned()
(name.local_name.to_owned(), name.namespace.clone())
} else {
String::from(#root)
(String::from(#root), None)
};
debug!("Struct: start to parse {:?}", named_element);
if let Some(ref namespace) = struct_namespace {
match namespace.as_str() {
#namespaces_matches
bad_ns => {
let msg = format!("bad namespace for {}, found {}", named_element, bad_ns);
return Err(msg);
}
}
};
#variables
#field_visitors
loop {
match reader.peek()?.to_owned() {
XmlEvent::StartElement{ref name, ref attributes, ref namespace} => {
#validate_namespace
XmlEvent::StartElement{ref name, ref attributes, ..} => {
match name.local_name.as_str() {
#call_visitors
@ -1283,12 +1358,41 @@ fn build_call_visitor(
visitor_label: &Ident,
label: &Option<Ident>,
label_name: &str,
prefix: &Option<String>,
namespaces: &BTreeMap<String, String>,
) -> Option<TokenStream> {
let namespaces_matches: TokenStream = namespaces
.iter()
.map(|(p, ns)| {
let str_ns = ns.as_str();
if *prefix == Some(p.to_string()) {
Some(quote!(#str_ns => {}))
} else {
None
}
})
.filter(|x| x.is_some())
.map(|x| x.unwrap())
.fold(TokenStream::new(), |mut tokens, token| {
tokens.append_all(token);
tokens
});
Some(quote! {
#label_name => {
let visitor = #visitor_label{};
if let XmlEvent::StartElement { .. } = *reader.peek()? {
if let XmlEvent::StartElement {name, ..} = reader.peek()?.clone() {
if let Some(namespace) = name.namespace {
match namespace.as_str() {
#namespaces_matches
bad_ns => {
let msg = format!("bad field namespace for {}, found {}", name.local_name.as_str(), bad_ns);
return Err(msg);
}
}
}
reader.set_map_value()
}

View File

@ -18,7 +18,7 @@ pub fn expand_derive_deserialize(ast: &syn::DeriveInput) -> Result<TokenStream,
let impl_block = match *data {
syn::Data::Struct(ref data_struct) => {
expand_struct::parse(data_struct, name, &root, &root_attrs.namespaces)
expand_struct::parse(data_struct, name, &root, &root_attrs.prefix, &root_attrs.namespaces)
}
syn::Data::Enum(ref data_enum) => {
expand_enum::parse(data_enum, name, &root, &root_attrs.namespaces)