From 4aadc78fc1d7cdedc01a781f50b4c8223a435a5a Mon Sep 17 00:00:00 2001 From: Dmitry Samoylov Date: Tue, 18 Feb 2020 15:56:09 +0700 Subject: [PATCH] Fix (de)serialization for elements with nested namespaces --- yaserde/src/de/mod.rs | 4 +++ yaserde/tests/der_namespace.rs | 35 ++++++++++++++++++++ yaserde/tests/se_namespace.rs | 44 +++++++++++++++++++++++-- yaserde_derive/src/de/expand_struct.rs | 21 ++++++------ yaserde_derive/src/ser/expand_struct.rs | 13 +++----- 5 files changed, 96 insertions(+), 21 deletions(-) diff --git a/yaserde/src/de/mod.rs b/yaserde/src/de/mod.rs index bf8b38e..227ca0e 100644 --- a/yaserde/src/de/mod.rs +++ b/yaserde/src/de/mod.rs @@ -98,6 +98,10 @@ impl<'de, R: Read> Deserializer { Ok(()) } + pub fn depth(&self) -> usize { + self.depth + } + pub fn set_map_value(&mut self) { self.is_map_value = true; } diff --git a/yaserde/tests/der_namespace.rs b/yaserde/tests/der_namespace.rs index dabf6e5..d07d8a9 100644 --- a/yaserde/tests/der_namespace.rs +++ b/yaserde/tests/der_namespace.rs @@ -89,6 +89,41 @@ fn de_struct_namespace() { ); } +#[test] +fn de_struct_namespace_nested() { + #[derive(YaDeserialize, Default, PartialEq, Debug)] + #[yaserde(prefix = "nsa", namespace = "nsa: http://www.sample.com/ns/a")] + struct A { + #[yaserde(prefix = "nsa")] + alpha: i32, + } + + #[derive(YaDeserialize, Default, PartialEq, Debug)] + #[yaserde(prefix = "nsb", namespace = "nsb: http://www.sample.com/ns/b")] + struct B { + // Note that name `nested` resides in `nsb` though it has a type from `nsa` + #[yaserde(prefix = "nsb")] + nested: A, + } + + convert_and_validate!( + r#" + + + + 32 + + + "#, + B, + B { + nested: A { alpha: 32 } + } + ); +} + #[test] fn de_enum_namespace() { #[derive(YaDeserialize, PartialEq, Debug)] diff --git a/yaserde/tests/se_namespace.rs b/yaserde/tests/se_namespace.rs index 14453d6..201f11e 100644 --- a/yaserde/tests/se_namespace.rs +++ b/yaserde/tests/se_namespace.rs @@ -9,9 +9,17 @@ use yaserde::ser::to_string; use yaserde::YaSerialize; macro_rules! convert_and_validate { - ($model:expr, $content:expr) => { + ($model: expr, $content: expr) => { let data: Result = to_string(&$model); - assert_eq!(data, Ok(String::from($content))); + assert_eq!( + data, + Ok( + String::from($content) + .split("\n") + .map(|s| s.trim()) + .collect::() + ) + ); }; } @@ -152,3 +160,35 @@ fn ser_struct_default_namespace() { let content = "something"; convert_and_validate!(model, content); } + +#[test] +fn de_struct_namespace_nested() { + #[derive(YaSerialize, Default, PartialEq, Debug)] + #[yaserde(prefix = "nsa", namespace = "nsa: http://www.sample.com/ns/a")] + struct A { + #[yaserde(prefix = "nsa")] + alpha: i32, + } + + #[derive(YaSerialize, Default, PartialEq, Debug)] + #[yaserde(prefix = "nsb", namespace = "nsb: http://www.sample.com/ns/b")] + struct B { + // Note that name `nested` resides in `nsb` though it has a type from `nsa` + #[yaserde(prefix = "nsb")] + nested: A, + } + + convert_and_validate!( + B { + nested: A { alpha: 32 } + }, + r#" + + + + 32 + + + "# + ); +} diff --git a/yaserde_derive/src/de/expand_struct.rs b/yaserde_derive/src/de/expand_struct.rs index 428d0e9..d22652a 100644 --- a/yaserde_derive/src/de/expand_struct.rs +++ b/yaserde_derive/src/de/expand_struct.rs @@ -17,9 +17,8 @@ pub fn parse( 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 => {})) + if prefix.as_ref() == Some(p) { + Some(quote!(#ns => {})) } else { None } @@ -382,15 +381,17 @@ pub fn parse( }; 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); + if reader.depth() == 0 { + 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 diff --git a/yaserde_derive/src/ser/expand_struct.rs b/yaserde_derive/src/ser/expand_struct.rs index 88d29f5..44b872f 100644 --- a/yaserde_derive/src/ser/expand_struct.rs +++ b/yaserde_derive/src/ser/expand_struct.rs @@ -405,15 +405,10 @@ pub fn serialize( let skip = writer.skip_start_end(); if !skip { - if let Some(label) = writer.get_start_event_name() { - let struct_start_event = XmlEvent::start_element(label.as_ref()); - #build_attributes - let _ret = writer.write(struct_start_event); - } else { - let struct_start_event = XmlEvent::start_element(#root)#add_namespaces; - #build_attributes - let _ret = writer.write(struct_start_event); - } + let label = writer.get_start_event_name().unwrap_or_else(|| #root.to_string()); + let struct_start_event = XmlEvent::start_element(label.as_ref())#add_namespaces; + #build_attributes + let _ret = writer.write(struct_start_event); } #struct_inspector