From ae3f873d692b3001e5dfe40e518a128ed759a2ee Mon Sep 17 00:00:00 2001 From: Marc-Antoine Arnaud Date: Sat, 29 Dec 2018 14:13:50 +0100 Subject: [PATCH] fix check namespace --- yaserde/tests/der_namespace.rs | 50 ++++++++- yaserde_derive/src/de/expand_struct.rs | 150 +++++++++++++++++++++---- yaserde_derive/src/de/mod.rs | 2 +- 3 files changed, 173 insertions(+), 29 deletions(-) diff --git a/yaserde/tests/der_namespace.rs b/yaserde/tests/der_namespace.rs index 6242587..c99d8df 100644 --- a/yaserde/tests/der_namespace.rs +++ b/yaserde/tests/der_namespace.rs @@ -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 = "Antoine de Saint-ExupéryLittle prince"; + let content = r#" + + Antoine de Saint-Exupéry + Little prince + + "#; convert_and_validate!( content, Book, @@ -41,9 +47,43 @@ fn de_struct_namespace() { } ); - let content = "Antoine de Saint-ExupéryLittle prince"; + let content = r#" + + Antoine de Saint-Exupéry + Little prince + + "#; + convert_and_validate!( + content, + Book, + Book { + author: String::from("Antoine de Saint-Exupéry"), + title: String::from("Little prince"), + } + ); + + let content = r#" + + Antoine de Saint-Exupéry + Little prince + + "#; + convert_and_validate!( + content, + Book, + Book { + author: String::from("Antoine de Saint-Exupéry"), + title: String::from("Little prince"), + } + ); + + let content = r#" + + Antoine de Saint-Exupéry + Little prince + "#; let loaded: Result = 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] diff --git a/yaserde_derive/src/de/expand_struct.rs b/yaserde_derive/src/de/expand_struct.rs index 717aace..a07f124 100644 --- a/yaserde_derive/src/de/expand_struct.rs +++ b/yaserde_derive/src/de/expand_struct.rs @@ -11,24 +11,19 @@ pub fn parse( data_struct: &DataStruct, name: &Ident, root: &str, + prefix: &Option, namespaces: &BTreeMap, ) -> 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(reader: &mut yaserde::de::Deserializer) -> Result { - 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, label_name: &str, + prefix: &Option, + namespaces: &BTreeMap, ) -> Option { + + 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() } diff --git a/yaserde_derive/src/de/mod.rs b/yaserde_derive/src/de/mod.rs index 8ea9329..02d9d93 100644 --- a/yaserde_derive/src/de/mod.rs +++ b/yaserde_derive/src/de/mod.rs @@ -18,7 +18,7 @@ pub fn expand_derive_deserialize(ast: &syn::DeriveInput) -> Result { - 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)