From b4bb23986c8dec713225ab7cd8a0e51037a2b95a Mon Sep 17 00:00:00 2001 From: marcelbuesing Date: Tue, 21 Dec 2021 13:38:12 +0100 Subject: [PATCH 01/14] initial choice type support --- xml_schema/tests/choice.rs | 41 ++++++++++++++ xml_schema/tests/choice.xsd | 25 +++++++++ xml_schema_derive/src/xsd/choice.rs | 68 +++++++++++++++++++++++ xml_schema_derive/src/xsd/complex_type.rs | 19 ++++++- xml_schema_derive/src/xsd/element.rs | 4 +- xml_schema_derive/src/xsd/extension.rs | 2 +- xml_schema_derive/src/xsd/mod.rs | 1 + xml_schema_derive/src/xsd/sequence.rs | 4 +- 8 files changed, 159 insertions(+), 5 deletions(-) create mode 100644 xml_schema/tests/choice.rs create mode 100644 xml_schema/tests/choice.xsd create mode 100644 xml_schema_derive/src/xsd/choice.rs diff --git a/xml_schema/tests/choice.rs b/xml_schema/tests/choice.rs new file mode 100644 index 0000000..17280fb --- /dev/null +++ b/xml_schema/tests/choice.rs @@ -0,0 +1,41 @@ +#[macro_use] +extern crate yaserde_derive; + +use log::debug; +use std::io::prelude::*; +use xml_schema_derive::XmlSchema; +use yaserde::de::from_str; +use yaserde::ser::to_string; +use yaserde::{YaDeserialize, YaSerialize}; + +#[test] +fn choice() { + #[derive(Debug, XmlSchema)] + #[xml_schema(source = "xml_schema/tests/choice.xsd")] + struct ChoiceTypeSchema; + + let xml_1 = r#" + + + John + + "#; + + let sample_1: Parent = from_str(xml_1).unwrap(); + + let model = Parent { + x_firstname: Some(Firstname { + content: "John".to_string(), + scope: None, + }), + x_lastname: None, + }; + + assert_eq!(sample_1, model); + + let data = to_string(&model).unwrap(); + assert_eq!( + data, + r#"John"# + ); +} diff --git a/xml_schema/tests/choice.xsd b/xml_schema/tests/choice.xsd new file mode 100644 index 0000000..9b126fd --- /dev/null +++ b/xml_schema/tests/choice.xsd @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/xml_schema_derive/src/xsd/choice.rs b/xml_schema_derive/src/xsd/choice.rs new file mode 100644 index 0000000..4121768 --- /dev/null +++ b/xml_schema_derive/src/xsd/choice.rs @@ -0,0 +1,68 @@ +//! The children of a choice are mapped to Option fields. +//! Generating an enum would have been the better way but the choice element +//! may not have a name, so it's impossible to name the generated Rust enum. +//! The enum would have been nice to avoid runtime checks that only a single choice element is used. + +use crate::xsd::{ + annotation::Annotation, attribute::Attribute, element::Element, max_occurences::MaxOccurences, + Implementation, XsdContext, +}; +use log::{debug, info}; +use proc_macro2::TokenStream; +use std::io::prelude::*; +use yaserde::YaDeserialize; + +#[derive(Clone, Default, Debug, PartialEq, YaDeserialize)] +#[yaserde( + rename = "choice" + prefix = "xs", + namespace = "xs: http://www.w3.org/2001/XMLSchema" +)] +pub struct Choice { + #[yaserde(attribute)] + pub id: Option, + #[yaserde(rename = "attribute")] + pub attributes: Vec, + #[yaserde(rename = "minOccurs", attribute)] + pub min_occurences: Option, + #[yaserde(rename = "maxOccurs", attribute)] + pub max_occurences: Option, + #[yaserde(rename = "annotation")] + pub annotation: Option, + #[yaserde(rename = "element")] + pub element: Vec, +} + +impl Implementation for Choice { + fn implement( + &self, + namespace_definition: &TokenStream, + prefix: &Option, + context: &XsdContext, + ) -> TokenStream { + let elements: TokenStream = self + .element + .iter() + .map(|element| element.implement(&namespace_definition, prefix, context)) + .collect(); + + quote! { + #elements + } + } +} + +impl Choice { + pub fn get_field_implementation( + &self, + context: &XsdContext, + prefix: &Option, + ) -> TokenStream { + info!("Generate choice elements"); + self + .element + .iter() + .map(|element| element.get_field_implementation(context, prefix, false, true)) + .collect() + } +} diff --git a/xml_schema_derive/src/xsd/complex_type.rs b/xml_schema_derive/src/xsd/complex_type.rs index d531559..d5e5028 100644 --- a/xml_schema_derive/src/xsd/complex_type.rs +++ b/xml_schema_derive/src/xsd/complex_type.rs @@ -1,5 +1,5 @@ use crate::xsd::{ - annotation::Annotation, attribute::Attribute, complex_content::ComplexContent, + annotation::Annotation, attribute::Attribute, choice::Choice, complex_content::ComplexContent, sequence::Sequence, simple_content::SimpleContent, Implementation, XsdContext, }; use heck::ToUpperCamelCase; @@ -24,6 +24,8 @@ pub struct ComplexType { pub complex_content: Option, #[yaserde(rename = "annotation")] pub annotation: Option, + #[yaserde(rename = "choice")] + pub choice: Option, } impl Implementation for ComplexType { @@ -81,6 +83,18 @@ impl Implementation for ComplexType { .map(|annotation| annotation.implement(namespace_definition, prefix, context)) .unwrap_or_default(); + let choice = self + .choice + .as_ref() + .map(|choice| choice.implement(&namespace_definition, prefix, context)) + .unwrap_or_else(TokenStream::new); + + let choice_field = self + .choice + .as_ref() + .map(|choice| choice.get_field_implementation(context, prefix)) + .unwrap_or_else(TokenStream::new); + quote! { #docs @@ -90,10 +104,13 @@ impl Implementation for ComplexType { #sequence #simple_content #complex_content + #choice_field #attributes } #sub_types_implementation + + #choice } } } diff --git a/xml_schema_derive/src/xsd/element.rs b/xml_schema_derive/src/xsd/element.rs index 17832e2..bdd4f72 100644 --- a/xml_schema_derive/src/xsd/element.rs +++ b/xml_schema_derive/src/xsd/element.rs @@ -102,6 +102,8 @@ impl Element { &self, context: &XsdContext, prefix: &Option, + multiple: bool, + optional: bool, ) -> TokenStream { if self.name.is_empty() { return quote!(); @@ -146,7 +148,7 @@ impl Element { rust_type }; - let rust_type = if !multiple && self.min_occurences == Some(0) { + let rust_type = if optional || (!multiple && self.min_occurences == Some(0)) { quote!(Option<#rust_type>) } else { rust_type diff --git a/xml_schema_derive/src/xsd/extension.rs b/xml_schema_derive/src/xsd/extension.rs index 536787f..1fcc064 100644 --- a/xml_schema_derive/src/xsd/extension.rs +++ b/xml_schema_derive/src/xsd/extension.rs @@ -1,5 +1,5 @@ use crate::xsd::{ - attribute::Attribute, group::Group, rust_types_mapping::RustTypesMapping, sequence::Sequence, + attribute::Attribute, choice::Choice, group::Group, rust_types_mapping::RustTypesMapping, sequence::Sequence, Implementation, XsdContext, }; use proc_macro2::TokenStream; diff --git a/xml_schema_derive/src/xsd/mod.rs b/xml_schema_derive/src/xsd/mod.rs index 43811b4..ce53212 100644 --- a/xml_schema_derive/src/xsd/mod.rs +++ b/xml_schema_derive/src/xsd/mod.rs @@ -1,6 +1,7 @@ mod annotation; mod attribute; mod attribute_group; +mod choice; mod complex_content; mod complex_type; mod element; diff --git a/xml_schema_derive/src/xsd/sequence.rs b/xml_schema_derive/src/xsd/sequence.rs index a39d2f1..2a94faa 100644 --- a/xml_schema_derive/src/xsd/sequence.rs +++ b/xml_schema_derive/src/xsd/sequence.rs @@ -20,7 +20,7 @@ impl Implementation for Sequence { self .elements .iter() - .map(|element| element.get_field_implementation(context, prefix)) + .map(|element| element.get_field_implementation(context, prefix, false, false)) .collect() } } @@ -48,7 +48,7 @@ impl Sequence { self .elements .iter() - .map(|element| element.get_field_implementation(context, prefix)) + .map(|element| element.get_field_implementation(context, prefix, true, false)) .collect() } } From c4cfd83390609325a24121796186098d9b967adb Mon Sep 17 00:00:00 2001 From: marcelbuesing Date: Tue, 21 Dec 2021 20:39:07 +0100 Subject: [PATCH 02/14] support choice in sequences --- xml_schema/tests/choice.rs | 34 +++++++++++++++++++++ xml_schema/tests/choice_sequence.xsd | 28 ++++++++++++++++++ xml_schema_derive/src/xsd/complex_type.rs | 1 + xml_schema_derive/src/xsd/extension.rs | 2 ++ xml_schema_derive/src/xsd/sequence.rs | 36 +++++++++++++++++++---- 5 files changed, 95 insertions(+), 6 deletions(-) create mode 100644 xml_schema/tests/choice_sequence.xsd diff --git a/xml_schema/tests/choice.rs b/xml_schema/tests/choice.rs index 17280fb..9b7bf27 100644 --- a/xml_schema/tests/choice.rs +++ b/xml_schema/tests/choice.rs @@ -39,3 +39,37 @@ fn choice() { r#"John"# ); } + +#[test] +fn choice_sequence() { + #[derive(Debug, XmlSchema)] + #[xml_schema(source = "xml_schema/tests/choice_sequence.xsd")] + struct ChoiceTypeSchema; + + let xml_1 = r#" + + + Doe + John + + "#; + + let sample_1: Parent = from_str(xml_1).unwrap(); + + let model = Parent { + name: "Doe".to_string(), + x_firstname: Some(Firstname { + content: "John".to_string(), + scope: None, + }), + x_lastname: None, + }; + + assert_eq!(sample_1, model); + + let data = to_string(&model).unwrap(); + assert_eq!( + data, + r#"DoeJohn"# + ); +} diff --git a/xml_schema/tests/choice_sequence.xsd b/xml_schema/tests/choice_sequence.xsd new file mode 100644 index 0000000..7eabaa8 --- /dev/null +++ b/xml_schema/tests/choice_sequence.xsd @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/xml_schema_derive/src/xsd/complex_type.rs b/xml_schema_derive/src/xsd/complex_type.rs index d5e5028..452c62b 100644 --- a/xml_schema_derive/src/xsd/complex_type.rs +++ b/xml_schema_derive/src/xsd/complex_type.rs @@ -17,6 +17,7 @@ pub struct ComplexType { pub name: String, #[yaserde(rename = "attribute")] pub attributes: Vec, + #[yaserde(rename = "sequence")] pub sequence: Option, #[yaserde(rename = "simpleContent")] pub simple_content: Option, diff --git a/xml_schema_derive/src/xsd/extension.rs b/xml_schema_derive/src/xsd/extension.rs index 1fcc064..d662f79 100644 --- a/xml_schema_derive/src/xsd/extension.rs +++ b/xml_schema_derive/src/xsd/extension.rs @@ -19,6 +19,8 @@ pub struct Extension { pub sequences: Vec, #[yaserde(rename = "group")] pub group: Option, + #[yaserde(rename = "choice")] + pub choices: Vec, } impl Implementation for Extension { diff --git a/xml_schema_derive/src/xsd/sequence.rs b/xml_schema_derive/src/xsd/sequence.rs index 2a94faa..621280d 100644 --- a/xml_schema_derive/src/xsd/sequence.rs +++ b/xml_schema_derive/src/xsd/sequence.rs @@ -1,4 +1,4 @@ -use crate::xsd::{element::Element, Implementation, XsdContext}; +use crate::xsd::{choice::Choice, element::Element, Implementation, XsdContext}; use log::info; use proc_macro2::TokenStream; @@ -7,6 +7,8 @@ use proc_macro2::TokenStream; pub struct Sequence { #[yaserde(rename = "element")] pub elements: Vec, + #[yaserde(rename = "choice")] + pub choices: Vec, } impl Implementation for Sequence { @@ -17,11 +19,22 @@ impl Implementation for Sequence { context: &XsdContext, ) -> TokenStream { info!("Generate elements"); - self + let elements: TokenStream = self .elements .iter() .map(|element| element.get_field_implementation(context, prefix, false, false)) - .collect() + .collect(); + + let choices: TokenStream = self + .choices + .iter() + .map(|choice| choice.get_field_implementation(context, prefix)) + .collect(); + + quote!( + #elements + #choices + ) } } @@ -45,10 +58,21 @@ impl Sequence { context: &XsdContext, prefix: &Option, ) -> TokenStream { - self + let elements: TokenStream = self .elements .iter() - .map(|element| element.get_field_implementation(context, prefix, true, false)) - .collect() + .map(|element| element.get_field_implementation(context, prefix, false, false)) + .collect(); + + let choices: TokenStream = self + .choices + .iter() + .map(|choice| choice.get_field_implementation(context, prefix)) + .collect(); + + quote!( + #elements + #choices + ) } } From 6fbffc3f4d631b2352cb4a8570a6859b6577a412 Mon Sep 17 00:00:00 2001 From: marcelbuesing Date: Thu, 23 Dec 2021 13:07:22 +0100 Subject: [PATCH 03/14] Cleanup choice sequence example --- xml_schema/tests/choice.rs | 18 +++++++++--------- xml_schema/tests/choice_sequence.xsd | 25 +++++++++++++------------ 2 files changed, 22 insertions(+), 21 deletions(-) diff --git a/xml_schema/tests/choice.rs b/xml_schema/tests/choice.rs index 9b7bf27..ef539bc 100644 --- a/xml_schema/tests/choice.rs +++ b/xml_schema/tests/choice.rs @@ -48,21 +48,21 @@ fn choice_sequence() { let xml_1 = r#" - - Doe - John - + + Doe + John + "#; - let sample_1: Parent = from_str(xml_1).unwrap(); + let sample_1: Person = from_str(xml_1).unwrap(); - let model = Parent { + let model = Person { name: "Doe".to_string(), - x_firstname: Some(Firstname { + firstname: Some(Firstname { content: "John".to_string(), scope: None, }), - x_lastname: None, + lastname: None, }; assert_eq!(sample_1, model); @@ -70,6 +70,6 @@ fn choice_sequence() { let data = to_string(&model).unwrap(); assert_eq!( data, - r#"DoeJohn"# + r#"DoeJohn"# ); } diff --git a/xml_schema/tests/choice_sequence.xsd b/xml_schema/tests/choice_sequence.xsd index 7eabaa8..444f000 100644 --- a/xml_schema/tests/choice_sequence.xsd +++ b/xml_schema/tests/choice_sequence.xsd @@ -1,5 +1,5 @@ - + @@ -7,7 +7,7 @@ - + @@ -15,14 +15,15 @@ - - - - - - - - - - + + + + + + + + + + + \ No newline at end of file From 450c63fc2afcbddc12fd35d1a9192f7b50c9e5e2 Mon Sep 17 00:00:00 2001 From: marcelbuesing Date: Thu, 23 Dec 2021 13:50:22 +0100 Subject: [PATCH 04/14] Fix regenerating choice child element structs --- xml_schema/tests/choice.rs | 18 +++++++++--------- xml_schema/tests/choice.xsd | 12 ++++++------ xml_schema_derive/src/xsd/choice.rs | 14 ++++++++++++++ xml_schema_derive/src/xsd/complex_type.rs | 11 +++++------ xml_schema_derive/src/xsd/extension.rs | 2 ++ 5 files changed, 36 insertions(+), 21 deletions(-) diff --git a/xml_schema/tests/choice.rs b/xml_schema/tests/choice.rs index ef539bc..9aba064 100644 --- a/xml_schema/tests/choice.rs +++ b/xml_schema/tests/choice.rs @@ -16,19 +16,19 @@ fn choice() { let xml_1 = r#" - - John - + + John + "#; - let sample_1: Parent = from_str(xml_1).unwrap(); + let sample_1: Person = from_str(xml_1).unwrap(); - let model = Parent { - x_firstname: Some(Firstname { + let model = Person { + firstname: Some(Firstname { content: "John".to_string(), scope: None, }), - x_lastname: None, + lastname: None, }; assert_eq!(sample_1, model); @@ -36,7 +36,7 @@ fn choice() { let data = to_string(&model).unwrap(); assert_eq!( data, - r#"John"# + r#"John"# ); } @@ -70,6 +70,6 @@ fn choice_sequence() { let data = to_string(&model).unwrap(); assert_eq!( data, - r#"DoeJohn"# + r#"DoeJohn"# ); } diff --git a/xml_schema/tests/choice.xsd b/xml_schema/tests/choice.xsd index 9b126fd..c1a328f 100644 --- a/xml_schema/tests/choice.xsd +++ b/xml_schema/tests/choice.xsd @@ -1,5 +1,5 @@ - + @@ -7,7 +7,7 @@ - + @@ -16,10 +16,10 @@ - - - - + + + + \ No newline at end of file diff --git a/xml_schema_derive/src/xsd/choice.rs b/xml_schema_derive/src/xsd/choice.rs index 4121768..dbb56db 100644 --- a/xml_schema_derive/src/xsd/choice.rs +++ b/xml_schema_derive/src/xsd/choice.rs @@ -53,6 +53,20 @@ impl Implementation for Choice { } impl Choice { + pub fn get_sub_types_implementation( + &self, + context: &XsdContext, + namespace_definition: &TokenStream, + prefix: &Option, + ) -> TokenStream { + info!("Generate choice sub types implementation"); + self + .element + .iter() + .map(|element| element.get_subtypes_implementation(namespace_definition, prefix, context)) + .collect() + } + pub fn get_field_implementation( &self, context: &XsdContext, diff --git a/xml_schema_derive/src/xsd/complex_type.rs b/xml_schema_derive/src/xsd/complex_type.rs index 452c62b..6872a76 100644 --- a/xml_schema_derive/src/xsd/complex_type.rs +++ b/xml_schema_derive/src/xsd/complex_type.rs @@ -72,7 +72,7 @@ impl Implementation for ComplexType { .map(|attribute| attribute.implement(namespace_definition, prefix, context)) .collect(); - let sub_types_implementation = self + let sequence_sub_types = self .sequence .as_ref() .map(|sequence| sequence.get_sub_types_implementation(context, namespace_definition, prefix)) @@ -84,10 +84,10 @@ impl Implementation for ComplexType { .map(|annotation| annotation.implement(namespace_definition, prefix, context)) .unwrap_or_default(); - let choice = self + let choice_sub_types = self .choice .as_ref() - .map(|choice| choice.implement(&namespace_definition, prefix, context)) + .map(|choice| choice.get_sub_types_implementation(context, &namespace_definition, prefix)) .unwrap_or_else(TokenStream::new); let choice_field = self @@ -109,9 +109,8 @@ impl Implementation for ComplexType { #attributes } - #sub_types_implementation - - #choice + #sequence_sub_types + #choice_sub_types } } } diff --git a/xml_schema_derive/src/xsd/extension.rs b/xml_schema_derive/src/xsd/extension.rs index d662f79..163b63c 100644 --- a/xml_schema_derive/src/xsd/extension.rs +++ b/xml_schema_derive/src/xsd/extension.rs @@ -93,6 +93,7 @@ mod tests { attributes: vec![], sequences: vec![], group: None, + choices: vec![], }; let context = @@ -136,6 +137,7 @@ mod tests { ], sequences: vec![], group: None, + choices: vec![], }; let context = From 819b837aebda73575b5bfe9b2f5255bc0d006584 Mon Sep 17 00:00:00 2001 From: marcelbuesing Date: Thu, 23 Dec 2021 14:25:51 +0100 Subject: [PATCH 05/14] Handle min and maxOccurences in choice --- xml_schema/tests/choice.rs | 29 +++++++++++++++++++++++ xml_schema/tests/choice_multiple.xsd | 10 ++++++++ xml_schema_derive/src/xsd/choice.rs | 11 ++++++++- xml_schema_derive/src/xsd/complex_type.rs | 10 +++++++- 4 files changed, 58 insertions(+), 2 deletions(-) create mode 100644 xml_schema/tests/choice_multiple.xsd diff --git a/xml_schema/tests/choice.rs b/xml_schema/tests/choice.rs index 9aba064..339bdfd 100644 --- a/xml_schema/tests/choice.rs +++ b/xml_schema/tests/choice.rs @@ -73,3 +73,32 @@ fn choice_sequence() { r#"DoeJohn"# ); } + +#[test] +fn choice_multiple() { + #[derive(Debug, XmlSchema)] + #[xml_schema(source = "xml_schema/tests/choice_multiple.xsd")] + struct ChoiceTypeSchema; + + let xml_1 = r#" + + + John + + "#; + + let sample_1: Person = from_str(xml_1).unwrap(); + + let model = Person { + firstnames: vec!["John".to_string()], + lastnames: vec![], + }; + + assert_eq!(sample_1, model); + + let data = to_string(&model).unwrap(); + assert_eq!( + data, + r#"John"# + ); +} diff --git a/xml_schema/tests/choice_multiple.xsd b/xml_schema/tests/choice_multiple.xsd new file mode 100644 index 0000000..8bd03d6 --- /dev/null +++ b/xml_schema/tests/choice_multiple.xsd @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/xml_schema_derive/src/xsd/choice.rs b/xml_schema_derive/src/xsd/choice.rs index dbb56db..4f0b7ac 100644 --- a/xml_schema_derive/src/xsd/choice.rs +++ b/xml_schema_derive/src/xsd/choice.rs @@ -73,10 +73,19 @@ impl Choice { prefix: &Option, ) -> TokenStream { info!("Generate choice elements"); + + let multiple = matches!(self.min_occurences, Some(min_occurences) if min_occurences > 1) + || matches!(self.max_occurences, Some(MaxOccurences::Unbounded)) + || matches!(self.max_occurences, Some(MaxOccurences::Number{value}) if value > 1); + + // Element fields are by default declared as Option type due to the nature of the choice element. + // Since a vector can also be empty, use Vec<_>, rather than Option>. + let optional = !multiple; + self .element .iter() - .map(|element| element.get_field_implementation(context, prefix, false, true)) + .map(|element| element.get_field_implementation(context, prefix, multiple, optional)) .collect() } } diff --git a/xml_schema_derive/src/xsd/complex_type.rs b/xml_schema_derive/src/xsd/complex_type.rs index 6872a76..7ea276d 100644 --- a/xml_schema_derive/src/xsd/complex_type.rs +++ b/xml_schema_derive/src/xsd/complex_type.rs @@ -127,12 +127,20 @@ impl ComplexType { .as_ref() .map(|sequence| sequence.get_field_implementation(context, prefix)) .unwrap_or_default() - } else { + } else if self.simple_content.is_some() { self .simple_content .as_ref() .map(|simple_content| simple_content.get_field_implementation(context, prefix)) .unwrap_or_default() + } else if self.choice.is_some() { + self + .choice + .as_ref() + .map(|choice| choice.get_field_implementation(context, prefix)) + .unwrap_or_else(TokenStream::new) + } else { + TokenStream::new() } } From 8878f4dc47fd4e457e90108612bc10b11f910f4a Mon Sep 17 00:00:00 2001 From: Andrei Date: Tue, 2 Jan 2024 22:00:52 +0000 Subject: [PATCH 06/14] Clean-up imports --- xml_schema/tests/choice.rs | 3 --- xml_schema_derive/src/xsd/choice.rs | 4 +--- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/xml_schema/tests/choice.rs b/xml_schema/tests/choice.rs index 339bdfd..926eb68 100644 --- a/xml_schema/tests/choice.rs +++ b/xml_schema/tests/choice.rs @@ -1,12 +1,9 @@ #[macro_use] extern crate yaserde_derive; -use log::debug; -use std::io::prelude::*; use xml_schema_derive::XmlSchema; use yaserde::de::from_str; use yaserde::ser::to_string; -use yaserde::{YaDeserialize, YaSerialize}; #[test] fn choice() { diff --git a/xml_schema_derive/src/xsd/choice.rs b/xml_schema_derive/src/xsd/choice.rs index 4f0b7ac..7347116 100644 --- a/xml_schema_derive/src/xsd/choice.rs +++ b/xml_schema_derive/src/xsd/choice.rs @@ -7,10 +7,8 @@ use crate::xsd::{ annotation::Annotation, attribute::Attribute, element::Element, max_occurences::MaxOccurences, Implementation, XsdContext, }; -use log::{debug, info}; +use log::info; use proc_macro2::TokenStream; -use std::io::prelude::*; -use yaserde::YaDeserialize; #[derive(Clone, Default, Debug, PartialEq, YaDeserialize)] #[yaserde( From b503c4e621a13e8ca32f61cb927850dbfb0f8d37 Mon Sep 17 00:00:00 2001 From: Andrei Date: Tue, 2 Jan 2024 22:01:48 +0000 Subject: [PATCH 07/14] Remove unused macro_use --- xml_schema/tests/choice.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/xml_schema/tests/choice.rs b/xml_schema/tests/choice.rs index 926eb68..19cfd68 100644 --- a/xml_schema/tests/choice.rs +++ b/xml_schema/tests/choice.rs @@ -1,4 +1,3 @@ -#[macro_use] extern crate yaserde_derive; use xml_schema_derive::XmlSchema; From 1aa88b5e8e88b4b88607843f687b5a295b03147c Mon Sep 17 00:00:00 2001 From: Andrei Date: Tue, 2 Jan 2024 22:05:30 +0000 Subject: [PATCH 08/14] Simplify types in the test --- xml_schema/tests/choice.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/xml_schema/tests/choice.rs b/xml_schema/tests/choice.rs index 19cfd68..184845c 100644 --- a/xml_schema/tests/choice.rs +++ b/xml_schema/tests/choice.rs @@ -10,6 +10,8 @@ fn choice() { #[xml_schema(source = "xml_schema/tests/choice.xsd")] struct ChoiceTypeSchema; + use choice_type_schema::xml_schema_types::*; + let xml_1 = r#" @@ -42,6 +44,8 @@ fn choice_sequence() { #[xml_schema(source = "xml_schema/tests/choice_sequence.xsd")] struct ChoiceTypeSchema; + use choice_type_schema::xml_schema_types::*; + let xml_1 = r#" From b5bfd40d3dc40b0a08098e83eb7020bc67da5567 Mon Sep 17 00:00:00 2001 From: Andrei Date: Tue, 2 Jan 2024 22:08:52 +0000 Subject: [PATCH 09/14] Patch out the choice_multiple test --- xml_schema/tests/choice.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xml_schema/tests/choice.rs b/xml_schema/tests/choice.rs index 184845c..0a1ee23 100644 --- a/xml_schema/tests/choice.rs +++ b/xml_schema/tests/choice.rs @@ -90,8 +90,8 @@ fn choice_multiple() { let sample_1: Person = from_str(xml_1).unwrap(); let model = Person { - firstnames: vec!["John".to_string()], - lastnames: vec![], + firstname: "John".to_string(), + lastname: "".to_string(), }; assert_eq!(sample_1, model); From 3cfb3c2eab9e8be73612aa9f20a69424e74ce7f1 Mon Sep 17 00:00:00 2001 From: Andrei Date: Tue, 2 Jan 2024 22:12:50 +0000 Subject: [PATCH 10/14] Remove unused parameter --- xml_schema_derive/src/xsd/choice.rs | 2 +- xml_schema_derive/src/xsd/element.rs | 1 - xml_schema_derive/src/xsd/sequence.rs | 4 ++-- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/xml_schema_derive/src/xsd/choice.rs b/xml_schema_derive/src/xsd/choice.rs index 7347116..6957499 100644 --- a/xml_schema_derive/src/xsd/choice.rs +++ b/xml_schema_derive/src/xsd/choice.rs @@ -83,7 +83,7 @@ impl Choice { self .element .iter() - .map(|element| element.get_field_implementation(context, prefix, multiple, optional)) + .map(|element| element.get_field_implementation(context, prefix, optional)) .collect() } } diff --git a/xml_schema_derive/src/xsd/element.rs b/xml_schema_derive/src/xsd/element.rs index bdd4f72..cac2e48 100644 --- a/xml_schema_derive/src/xsd/element.rs +++ b/xml_schema_derive/src/xsd/element.rs @@ -102,7 +102,6 @@ impl Element { &self, context: &XsdContext, prefix: &Option, - multiple: bool, optional: bool, ) -> TokenStream { if self.name.is_empty() { diff --git a/xml_schema_derive/src/xsd/sequence.rs b/xml_schema_derive/src/xsd/sequence.rs index 621280d..969d4a7 100644 --- a/xml_schema_derive/src/xsd/sequence.rs +++ b/xml_schema_derive/src/xsd/sequence.rs @@ -22,7 +22,7 @@ impl Implementation for Sequence { let elements: TokenStream = self .elements .iter() - .map(|element| element.get_field_implementation(context, prefix, false, false)) + .map(|element| element.get_field_implementation(context, prefix, false)) .collect(); let choices: TokenStream = self @@ -61,7 +61,7 @@ impl Sequence { let elements: TokenStream = self .elements .iter() - .map(|element| element.get_field_implementation(context, prefix, false, false)) + .map(|element| element.get_field_implementation(context, prefix, false)) .collect(); let choices: TokenStream = self From 5495f127fdd1c0230d5127634236eceef1df5949 Mon Sep 17 00:00:00 2001 From: Andrei Date: Tue, 2 Jan 2024 22:14:12 +0000 Subject: [PATCH 11/14] Fix option type path --- xml_schema_derive/src/xsd/element.rs | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/xml_schema_derive/src/xsd/element.rs b/xml_schema_derive/src/xsd/element.rs index cac2e48..78953a8 100644 --- a/xml_schema_derive/src/xsd/element.rs +++ b/xml_schema_derive/src/xsd/element.rs @@ -147,17 +147,6 @@ impl Element { rust_type }; - let rust_type = if optional || (!multiple && self.min_occurences == Some(0)) { - quote!(Option<#rust_type>) - } else { - rust_type - }; - - let prefix_attribute = prefix - .as_ref() - .map(|prefix| quote!(, prefix=#prefix)) - .unwrap_or_default(); - let module = (!context.is_in_sub_module() && !self .kind @@ -170,9 +159,22 @@ impl Element { .then_some(quote!(xml_schema_types::)) .unwrap_or_default(); + let rust_type = quote!(#module#rust_type); + + let rust_type = if optional || (!multiple && self.min_occurences == Some(0)) { + quote!(Option<#rust_type>) + } else { + rust_type + }; + + let prefix_attribute = prefix + .as_ref() + .map(|prefix| quote!(, prefix=#prefix)) + .unwrap_or_default(); + quote! { #[yaserde(rename=#yaserde_rename #prefix_attribute)] - pub #attribute_name: #module#rust_type, + pub #attribute_name: #rust_type, } } } From 1f5ce0d96655d67c8a1456954d8df5925e5fc277 Mon Sep 17 00:00:00 2001 From: Andrei Date: Wed, 3 Jan 2024 15:40:19 +0000 Subject: [PATCH 12/14] Fix extension attribute name --- xml_schema/tests/choice.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xml_schema/tests/choice.rs b/xml_schema/tests/choice.rs index 0a1ee23..b2806f6 100644 --- a/xml_schema/tests/choice.rs +++ b/xml_schema/tests/choice.rs @@ -23,7 +23,7 @@ fn choice() { let model = Person { firstname: Some(Firstname { - content: "John".to_string(), + base: "John".to_string(), scope: None, }), lastname: None, @@ -59,7 +59,7 @@ fn choice_sequence() { let model = Person { name: "Doe".to_string(), firstname: Some(Firstname { - content: "John".to_string(), + base: "John".to_string(), scope: None, }), lastname: None, From 4e1000ca4521406a309544ce09d41ef3d4f8c8a7 Mon Sep 17 00:00:00 2001 From: Andrei Date: Wed, 3 Jan 2024 16:36:58 +0000 Subject: [PATCH 13/14] Fix test docstring parsing --- xml_schema/tests/choice.rs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/xml_schema/tests/choice.rs b/xml_schema/tests/choice.rs index b2806f6..b4d5ab4 100644 --- a/xml_schema/tests/choice.rs +++ b/xml_schema/tests/choice.rs @@ -12,8 +12,7 @@ fn choice() { use choice_type_schema::xml_schema_types::*; - let xml_1 = r#" - + let xml_1 = r#" John @@ -46,8 +45,7 @@ fn choice_sequence() { use choice_type_schema::xml_schema_types::*; - let xml_1 = r#" - + let xml_1 = r#" Doe John @@ -80,8 +78,7 @@ fn choice_multiple() { #[xml_schema(source = "xml_schema/tests/choice_multiple.xsd")] struct ChoiceTypeSchema; - let xml_1 = r#" - + let xml_1 = r#" John From 78cdeae347ff485c58ac8362d90df826268fdb6e Mon Sep 17 00:00:00 2001 From: Andrei Date: Thu, 4 Jan 2024 12:16:47 +0000 Subject: [PATCH 14/14] Implement inheritable multiple characteristic --- xml_schema/tests/choice.rs | 4 ++-- xml_schema_derive/src/xsd/choice.rs | 2 +- xml_schema_derive/src/xsd/element.rs | 8 +++++--- xml_schema_derive/src/xsd/sequence.rs | 4 ++-- 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/xml_schema/tests/choice.rs b/xml_schema/tests/choice.rs index b4d5ab4..646e0ae 100644 --- a/xml_schema/tests/choice.rs +++ b/xml_schema/tests/choice.rs @@ -87,8 +87,8 @@ fn choice_multiple() { let sample_1: Person = from_str(xml_1).unwrap(); let model = Person { - firstname: "John".to_string(), - lastname: "".to_string(), + firstname_list: vec!["John".to_string()], + lastname_list: vec![], }; assert_eq!(sample_1, model); diff --git a/xml_schema_derive/src/xsd/choice.rs b/xml_schema_derive/src/xsd/choice.rs index 6957499..7347116 100644 --- a/xml_schema_derive/src/xsd/choice.rs +++ b/xml_schema_derive/src/xsd/choice.rs @@ -83,7 +83,7 @@ impl Choice { self .element .iter() - .map(|element| element.get_field_implementation(context, prefix, optional)) + .map(|element| element.get_field_implementation(context, prefix, multiple, optional)) .collect() } } diff --git a/xml_schema_derive/src/xsd/element.rs b/xml_schema_derive/src/xsd/element.rs index 78953a8..76c84cd 100644 --- a/xml_schema_derive/src/xsd/element.rs +++ b/xml_schema_derive/src/xsd/element.rs @@ -102,14 +102,16 @@ impl Element { &self, context: &XsdContext, prefix: &Option, + inheritable_multiple: bool, optional: bool, ) -> TokenStream { if self.name.is_empty() { return quote!(); } - let multiple = self.max_occurences.is_some() - && self.max_occurences != Some(MaxOccurences::Number { value: 1 }); + let multiple = inheritable_multiple + || (self.max_occurences.is_some() + && self.max_occurences != Some(MaxOccurences::Number { value: 1 })); let name = if self.name.to_lowercase() == "type" { "kind".to_string() @@ -124,7 +126,7 @@ impl Element { } else { name }; - + let attribute_name = Ident::new(&name, Span::call_site()); let yaserde_rename = &self.name; diff --git a/xml_schema_derive/src/xsd/sequence.rs b/xml_schema_derive/src/xsd/sequence.rs index 969d4a7..621280d 100644 --- a/xml_schema_derive/src/xsd/sequence.rs +++ b/xml_schema_derive/src/xsd/sequence.rs @@ -22,7 +22,7 @@ impl Implementation for Sequence { let elements: TokenStream = self .elements .iter() - .map(|element| element.get_field_implementation(context, prefix, false)) + .map(|element| element.get_field_implementation(context, prefix, false, false)) .collect(); let choices: TokenStream = self @@ -61,7 +61,7 @@ impl Sequence { let elements: TokenStream = self .elements .iter() - .map(|element| element.get_field_implementation(context, prefix, false)) + .map(|element| element.get_field_implementation(context, prefix, false, false)) .collect(); let choices: TokenStream = self