diff --git a/examples/tests/data/svd.xml b/examples/tests/data/svd.xml index 8743645..0d806ae 100644 --- a/examples/tests/data/svd.xml +++ b/examples/tests/data/svd.xml @@ -1,4 +1,4 @@ - + Renesas diff --git a/yaserde/src/de/mod.rs b/yaserde/src/de/mod.rs index b08b138..5840820 100644 --- a/yaserde/src/de/mod.rs +++ b/yaserde/src/de/mod.rs @@ -18,6 +18,7 @@ pub struct Deserializer { depth: usize, reader: EventReader, peeked: Option, + pub inner_struct_label: Option<&'static str>, } impl Deserializer { @@ -26,6 +27,7 @@ impl Deserializer { depth: 0, reader, peeked: None, + inner_struct_label: None, } } diff --git a/yaserde/src/lib.rs b/yaserde/src/lib.rs index 6c86ac9..669e30e 100644 --- a/yaserde/src/lib.rs +++ b/yaserde/src/lib.rs @@ -328,7 +328,7 @@ macro_rules! serialize_and_validate { log::debug!("serialize_and_validate @ {}:{}", file!(), line!()); let data: Result = yaserde::ser::to_string(&$model); - let content = &format!(r#"{}"#, $content); + let content = &format!(r#"{}"#, $content); assert_eq!( data, Ok(content.split("\n").map(|s| s.trim()).collect::()) diff --git a/yaserde/tests/cdata.rs b/yaserde/tests/cdata.rs index a73868d..45b980f 100644 --- a/yaserde/tests/cdata.rs +++ b/yaserde/tests/cdata.rs @@ -18,14 +18,14 @@ fn test_cdata_serialization() { msgdata: "Some unescaped content".to_string(), }; let xml_output = yaserde::ser::to_string(&test_data).expect("Serialization failed"); - let expected_output = r#"Some unescaped content]]>"#; + let expected_output = r#"Some unescaped content]]>"#; assert_eq!(xml_output, expected_output); } #[test] fn test_cdata_deserialization() { init(); - let xml = r#"Some unescaped content]]>"#; + let xml = r#"Some unescaped content]]>"#; let r: TestStruct = yaserde::de::from_str(xml).unwrap(); let expected_output = TestStruct { msgdata: "Some unescaped content".to_string(), diff --git a/yaserde/tests/deserializer.rs b/yaserde/tests/deserializer.rs index 5b0e3af..52112d7 100644 --- a/yaserde/tests/deserializer.rs +++ b/yaserde/tests/deserializer.rs @@ -583,7 +583,7 @@ fn de_complex_enum() { Dotted(u32), } - let content = r#" + let content = r#" text @@ -598,7 +598,7 @@ fn de_complex_enum() { } ); - let content = r#" + let content = r#" text @@ -613,7 +613,7 @@ fn de_complex_enum() { } ); - let content = r#" + let content = r#" 56 @@ -628,7 +628,7 @@ fn de_complex_enum() { } ); - let content = r#" + let content = r#" @@ -646,7 +646,7 @@ fn de_complex_enum() { } ); - let content = r#" + let content = r#" text @@ -661,7 +661,7 @@ fn de_complex_enum() { } ); - let content = r#" + let content = r#" @@ -679,7 +679,7 @@ fn de_complex_enum() { } ); - let content = r#" + let content = r#" abc @@ -695,7 +695,7 @@ fn de_complex_enum() { } ); - let content = r#" + let content = r#" 12 @@ -711,7 +711,7 @@ fn de_complex_enum() { } ); - let content = r#" + let content = r#" 1223 @@ -730,7 +730,7 @@ fn de_complex_enum() { } ); - let content = r#" + let content = r#" 1223 @@ -749,7 +749,7 @@ fn de_complex_enum() { } ); - let content = r#" + let content = r#" 54 @@ -854,7 +854,7 @@ fn de_subitem_issue_12() { } convert_and_validate!( - r#" + r#" 54 @@ -884,7 +884,7 @@ fn de_subitem_issue_12_with_sub() { } convert_and_validate!( - r#" + r#" 54 @@ -911,7 +911,7 @@ fn de_subitem_issue_12_attributes() { } convert_and_validate!( - r#" + r#" @@ -940,7 +940,7 @@ fn de_subitem_issue_12_attributes_with_sub() { } convert_and_validate!( - r#" + r#" @@ -1117,3 +1117,133 @@ fn de_nested_macro_rules() { float_attrs!(f32); } + +#[test] +fn de_nested_element_equality() { + #[derive(YaDeserialize, Debug, PartialEq)] + #[yaserde(rename = "EBMLSchema")] + struct Schema { + #[yaserde(rename = "element")] + elements: Vec, + } + + #[derive(YaDeserialize, Debug, PartialEq)] + #[yaserde(rename = "element")] + struct Element { + #[yaserde(rename = "documentation")] + documentation: Vec, + } + + #[derive(YaDeserialize, Debug, PartialEq)] + #[yaserde(rename = "documentation")] + struct Documentation { + #[yaserde(text = true)] + body: String, + } + + let parent = r#" + +Test + +"#; + let parent: Schema = yaserde::de::from_str(parent).unwrap(); + + let child = r#" +Test +"#; + let child: Element = yaserde::de::from_str(child).unwrap(); + + assert_ne!(parent.elements, vec![]); + assert_eq!(parent.elements[0], child); +} + +#[test] +fn de_nested_3_levels() { + #[derive(YaSerialize, YaDeserialize, Debug, PartialEq)] + struct A { + id: String, + #[yaserde(rename = "SAME")] + many: Vec, + } + + #[derive(YaSerialize, YaDeserialize, Debug, PartialEq)] + struct B { + id: Option, + #[yaserde(rename = "SAME")] + many: Vec, + } + + #[derive(YaSerialize, YaDeserialize, Debug, PartialEq)] + struct C { + id: Option, + } + + let content = + r#"a1b1c1c2"#; + let model = A { + id: "a1".to_string(), + many: vec![B { + id: Some("b1".to_string()), + many: vec![ + C { + id: Some("c1".to_string()), + }, + C { + id: Some("c2".to_string()), + }, + ], + }], + }; + deserialize_and_validate!(content, model, A); +} + +#[test] +fn de_nested_issue_192() { + #[derive(Clone, Default, Debug, PartialEq, YaDeserialize)] + #[yaserde( + prefix = "xs", + namespaces = { + "xs" = "http://www.w3.org/2001/XMLSchema", + } + )] + pub struct XSDGroup { + #[yaserde(rename = "ref", attribute = true)] + pub reference: String, + } + + #[derive(Clone, Default, Debug, PartialEq, YaDeserialize)] + #[yaserde( + rename = "sequence", + prefix = "xs", + namespaces = { + "xs" = "http://www.w3.org/2001/XMLSchema", + } + )] + pub struct Sequence { + #[yaserde(rename = "group", prefix = "xs")] + pub groups: Vec, + + #[yaserde(rename = "sequence", prefix = "xs")] + pub sequences: Vec, + } + + let content = r#" + + + + + "#; + let model = Sequence { + groups: vec![ + XSDGroup { + reference: "AR:AR-OBJECT".to_string(), + }, + XSDGroup { + reference: "AR:AUTOSAR".to_string(), + }, + ], + sequences: vec![], + }; + + deserialize_and_validate!(content, model, Sequence); +} diff --git a/yaserde/tests/option.rs b/yaserde/tests/option.rs index fac7804..1cad3e2 100644 --- a/yaserde/tests/option.rs +++ b/yaserde/tests/option.rs @@ -144,7 +144,7 @@ mod tests { #[test] fn deserialize_without_car() { - let person = r#" + let person = r#" brown 25 diff --git a/yaserde_derive/src/de/expand_struct.rs b/yaserde_derive/src/de/expand_struct.rs index fca7486..7a6a81b 100644 --- a/yaserde_derive/src/de/expand_struct.rs +++ b/yaserde_derive/src/de/expand_struct.rs @@ -7,7 +7,6 @@ use syn::{DataStruct, Generics, Ident}; pub fn parse( data_struct: &DataStruct, name: &Ident, - root_namespace: &str, root: &str, root_attributes: &YaSerdeAttribute, generics: &Generics, @@ -160,6 +159,7 @@ pub fn parse( } if let Ok(::yaserde::__xml::reader::XmlEvent::StartElement { .. }) = reader.peek() { // If substruct's start element found then deserialize substruct + reader.inner_struct_label = Some(#label_name); let value = <#struct_name as ::yaserde::YaDeserialize>::deserialize(reader)?; #value_label #action; // read EndElement @@ -383,7 +383,6 @@ pub fn parse( build_code_for_unused_xml_events(&call_flatten_visitors) }; - let flatten = root_attributes.flatten; let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); quote! { @@ -392,6 +391,7 @@ pub fn parse( fn deserialize( reader: &mut ::yaserde::de::Deserializer, ) -> ::std::result::Result { + let root_label= reader.inner_struct_label.take().unwrap_or(#root); let (named_element, struct_namespace) = if let ::yaserde::__xml::reader::XmlEvent::StartElement { name, .. } = reader.peek()?.to_owned() { (name.local_name.to_owned(), name.namespace.clone()) @@ -421,7 +421,7 @@ pub fn parse( match event { ::yaserde::__xml::reader::XmlEvent::StartElement{ref name, ref attributes, ..} => { let namespace = name.namespace.clone().unwrap_or_default(); - if depth == 0 && name.local_name == #root && namespace.as_str() == #root_namespace { + if depth == 0 && name.local_name == root_label { // Consume root element. We must do this first. In the case it shares a name with a child element, we don't // want to prematurely match the child element below. let event = reader.next_event()?; @@ -457,9 +457,8 @@ pub fn parse( depth -= 1; } ::yaserde::__xml::reader::XmlEvent::EndDocument => { - if #flatten { - break; - } + // once we receive this once, we will keep getting it, potentially looping forever + break; } ::yaserde::__xml::reader::XmlEvent::Characters(ref text_content) => { #set_text diff --git a/yaserde_derive/src/de/mod.rs b/yaserde_derive/src/de/mod.rs index 4526209..99d243a 100644 --- a/yaserde_derive/src/de/mod.rs +++ b/yaserde_derive/src/de/mod.rs @@ -15,27 +15,11 @@ pub fn expand_derive_deserialize(ast: &syn::DeriveInput) -> Result expand_struct::parse( - data_struct, - name, - &root_namespace, - &root_name, - &root_attributes, - generics, - ), + syn::Data::Struct(ref data_struct) => { + expand_struct::parse(data_struct, name, &root_name, &root_attributes, generics) + } syn::Data::Enum(ref data_enum) => { expand_enum::parse(data_enum, name, &root_name, &root_attributes, generics) }