From 8a16d872f6ef37b9d3a6d6f083246e392a3f662b Mon Sep 17 00:00:00 2001 From: Andrei Date: Sat, 23 Dec 2023 23:13:51 +0000 Subject: [PATCH 1/5] Add extension group support --- xml_schema_derive/src/xsd/extension.rs | 34 +++++++++++++++++++++----- xml_schema_derive/src/xsd/group.rs | 19 ++++++++++++++ xml_schema_derive/src/xsd/mod.rs | 1 + 3 files changed, 48 insertions(+), 6 deletions(-) create mode 100644 xml_schema_derive/src/xsd/group.rs diff --git a/xml_schema_derive/src/xsd/extension.rs b/xml_schema_derive/src/xsd/extension.rs index 27d2b47..536787f 100644 --- a/xml_schema_derive/src/xsd/extension.rs +++ b/xml_schema_derive/src/xsd/extension.rs @@ -1,6 +1,6 @@ use crate::xsd::{ - attribute::Attribute, rust_types_mapping::RustTypesMapping, sequence::Sequence, Implementation, - XsdContext, + attribute::Attribute, group::Group, rust_types_mapping::RustTypesMapping, sequence::Sequence, + Implementation, XsdContext, }; use proc_macro2::TokenStream; @@ -17,6 +17,8 @@ pub struct Extension { pub attributes: Vec, #[yaserde(rename = "sequence")] pub sequences: Vec, + #[yaserde(rename = "group")] + pub group: Option, } impl Implementation for Extension { @@ -34,7 +36,7 @@ impl Implementation for Extension { .map(|attribute| attribute.implement(namespace_definition, prefix, context)) .collect(); - let inner_attribute = if format!("{rust_type}") == "String" { +let inner_attribute = if format!("{rust_type}") == "String" { quote!(#[yaserde(text)]) } else { TokenStream::new() @@ -42,7 +44,7 @@ impl Implementation for Extension { quote!( #inner_attribute - pub content: #rust_type, + pub base: #rust_type, #attributes ) } @@ -52,10 +54,28 @@ impl Extension { pub fn get_field_implementation( &self, context: &XsdContext, - _prefix: &Option, + prefix: &Option, ) -> TokenStream { let rust_type = RustTypesMapping::get(context, &self.base); - quote!(pub content : #rust_type) + + let group_content = self + .group + .as_ref() + .map(|group| { + let group_type = group.get_type_implementation(context, prefix); + + quote!( + , + #[serde(flatten)] + pub extension : #group_type + ) + }) + .unwrap_or_default(); + + quote!( + pub base : #rust_type + #group_content + ) } } @@ -70,6 +90,7 @@ mod tests { base: "xs:string".to_string(), attributes: vec![], sequences: vec![], + group: None, }; let context = @@ -112,6 +133,7 @@ mod tests { }, ], sequences: vec![], + group: None, }; let context = diff --git a/xml_schema_derive/src/xsd/group.rs b/xml_schema_derive/src/xsd/group.rs new file mode 100644 index 0000000..037d3d0 --- /dev/null +++ b/xml_schema_derive/src/xsd/group.rs @@ -0,0 +1,19 @@ +use crate::xsd::{rust_types_mapping::RustTypesMapping, XsdContext}; +use proc_macro2::TokenStream; + +#[derive(Clone, Default, Debug, PartialEq, YaDeserialize)] +#[yaserde(prefix = "xs", namespace = "xs: http://www.w3.org/2001/XMLSchema")] +pub struct Group { + #[yaserde(attribute)] + pub r#ref: String, +} + +impl Group { + pub fn get_type_implementation( + &self, + context: &XsdContext, + _prefix: &Option, + ) -> TokenStream { + RustTypesMapping::get(context, &self.r#ref) + } +} diff --git a/xml_schema_derive/src/xsd/mod.rs b/xml_schema_derive/src/xsd/mod.rs index a3eb8e1..43811b4 100644 --- a/xml_schema_derive/src/xsd/mod.rs +++ b/xml_schema_derive/src/xsd/mod.rs @@ -5,6 +5,7 @@ mod complex_content; mod complex_type; mod element; mod extension; +mod group; mod import; mod list; mod max_occurences; From 9f403d07bcf0dac15ae480ac4035f71b48341aca Mon Sep 17 00:00:00 2001 From: Andrei Date: Sun, 24 Dec 2023 00:04:19 +0000 Subject: [PATCH 2/5] Generate group structs --- xml_schema_derive/src/xsd/group.rs | 44 +++++++++++++++++++++++++++-- xml_schema_derive/src/xsd/schema.rs | 17 ++++++++++- 2 files changed, 57 insertions(+), 4 deletions(-) diff --git a/xml_schema_derive/src/xsd/group.rs b/xml_schema_derive/src/xsd/group.rs index 037d3d0..cdf0de9 100644 --- a/xml_schema_derive/src/xsd/group.rs +++ b/xml_schema_derive/src/xsd/group.rs @@ -5,7 +5,41 @@ use proc_macro2::TokenStream; #[yaserde(prefix = "xs", namespace = "xs: http://www.w3.org/2001/XMLSchema")] pub struct Group { #[yaserde(attribute)] - pub r#ref: String, + pub name: Option, + #[yaserde(attribute, rename = "ref")] + pub reference: Option, + #[yaserde()] + pub sequence: Option, +} + +impl Implementation for Group { + fn implement( + &self, + namespace_definition: &TokenStream, + prefix: &Option, + context: &XsdContext, + ) -> TokenStream { + if self.name.is_none() { + return quote!(); + } + let raw_name = self.name.clone().unwrap(); + + let struct_name = Ident::new(&raw_name.to_upper_camel_case(), Span::call_site()); + + let fields = self + .sequence + .as_ref() + .map(|sequence| sequence.get_field_implementation(context, prefix)) + .unwrap_or_default(); + + quote!( + #[derive(Clone, Debug, Default, PartialEq, serde::Deserialize, serde::Serialize)] + #namespace_definition + pub struct #struct_name { + #fields + } + ) + } } impl Group { @@ -14,6 +48,10 @@ impl Group { context: &XsdContext, _prefix: &Option, ) -> TokenStream { - RustTypesMapping::get(context, &self.r#ref) + if let Some(reference) = &self.reference { + RustTypesMapping::get(context, reference) + } else { + panic!("Missing reference for group"); + } } -} +} \ No newline at end of file diff --git a/xml_schema_derive/src/xsd/schema.rs b/xml_schema_derive/src/xsd/schema.rs index 8966828..c22bdc3 100644 --- a/xml_schema_derive/src/xsd/schema.rs +++ b/xml_schema_derive/src/xsd/schema.rs @@ -1,4 +1,4 @@ -use crate::xsd::{ + use crate::xsd::{ attribute, attribute_group, complex_type, element, import, qualification, simple_type, Implementation, XsdContext, }; @@ -29,6 +29,8 @@ pub struct Schema { pub attributes: Vec, #[yaserde(rename = "attributeGroup")] pub attribute_group: Vec, + #[yaserde(rename = "group")] + pub group: Vec, } impl Implementation for Schema { @@ -71,10 +73,23 @@ impl Implementation for Schema { .collect() }; + log::info!("Generate groups"); + let groups: TokenStream = { + let mut context = context.clone(); + context.set_is_in_sub_module(true); + + self + .group + .iter() + .map(|group| group.implement(&namespace_definition, target_prefix, &context)) + .collect() + }; + quote!( pub mod xml_schema_types { #simple_types #complex_types + #groups } #elements From aece7cbda5021c3a19724e24733f38bdbcf8a009 Mon Sep 17 00:00:00 2001 From: Andrei Date: Sun, 24 Dec 2023 21:55:10 +0000 Subject: [PATCH 3/5] Add missing import for group --- xml_schema_derive/src/xsd/schema.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xml_schema_derive/src/xsd/schema.rs b/xml_schema_derive/src/xsd/schema.rs index c22bdc3..e14ec5f 100644 --- a/xml_schema_derive/src/xsd/schema.rs +++ b/xml_schema_derive/src/xsd/schema.rs @@ -1,5 +1,5 @@ use crate::xsd::{ - attribute, attribute_group, complex_type, element, import, qualification, simple_type, + attribute, attribute_group, complex_type, element, group, import, qualification, simple_type, Implementation, XsdContext, }; use proc_macro2::TokenStream; From 0202e52fcf611bb8e245f90f2b3a39c715a9b167 Mon Sep 17 00:00:00 2001 From: Andrei Date: Sun, 24 Dec 2023 21:56:03 +0000 Subject: [PATCH 4/5] Fix import for group module --- xml_schema_derive/src/xsd/group.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/xml_schema_derive/src/xsd/group.rs b/xml_schema_derive/src/xsd/group.rs index cdf0de9..29c6d2d 100644 --- a/xml_schema_derive/src/xsd/group.rs +++ b/xml_schema_derive/src/xsd/group.rs @@ -1,5 +1,9 @@ -use crate::xsd::{rust_types_mapping::RustTypesMapping, XsdContext}; -use proc_macro2::TokenStream; +use crate::xsd::{ + rust_types_mapping::RustTypesMapping, sequence::Sequence, Implementation, XsdContext, +}; +use heck::ToUpperCamelCase; +use proc_macro2::{Span, TokenStream}; +use syn::Ident; #[derive(Clone, Default, Debug, PartialEq, YaDeserialize)] #[yaserde(prefix = "xs", namespace = "xs: http://www.w3.org/2001/XMLSchema")] From 6623691f7eddbd2e0b65d67d2015e66584988e67 Mon Sep 17 00:00:00 2001 From: Andrei Date: Sun, 24 Dec 2023 21:57:32 +0000 Subject: [PATCH 5/5] Add tests for group --- xml_schema_derive/src/xsd/group.rs | 49 +++++++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) diff --git a/xml_schema_derive/src/xsd/group.rs b/xml_schema_derive/src/xsd/group.rs index 29c6d2d..e0eec34 100644 --- a/xml_schema_derive/src/xsd/group.rs +++ b/xml_schema_derive/src/xsd/group.rs @@ -58,4 +58,51 @@ impl Group { panic!("Missing reference for group"); } } -} \ No newline at end of file +} + +#[cfg(test)] +mod tests { + use super::*; + + use yaserde::de::from_str; + + #[test] + fn check_group_implementation() { + let xml = r#" + + + + + + + "#; + + let group: Group = from_str(xml).unwrap(); + + let context = + XsdContext::new(r#""#) + .unwrap(); + + let implementation = format!("{}", group.implement(&TokenStream::new(), &None, &context)); + + assert_eq!(implementation, "# [derive (Clone , Debug , Default , PartialEq , serde :: Deserialize , serde :: Serialize)] \ +pub struct Groupthing { \ +# [yaserde (rename = \"CX_X\")] pub cx_x : xml_schema_types :: Asdfg , \ +# [yaserde (rename = \"CY_X\")] pub cy_x : xml_schema_types :: Asdfg , }"); + } + + #[test] + fn check_group_ref() { + let xml = r#""#; + + let group: Group = from_str(xml).unwrap(); + + let context = + XsdContext::new(r#""#) + .unwrap(); + + let type_implementation = format!("{}", group.get_type_implementation(&context, &None)); + + assert_eq!(type_implementation, "Groupthing"); + } +}