diff --git a/xml_schema/Cargo.toml b/xml_schema/Cargo.toml index c7f31a8..274f772 100644 --- a/xml_schema/Cargo.toml +++ b/xml_schema/Cargo.toml @@ -13,11 +13,10 @@ readme = "../README.md" exclude = ["/tests"] [dependencies] -xml-schema-derive = { version = "0.3.0", path = "../xml_schema_derive", optional = true } - -[dev-dependencies] -log = "0.4" xml-rs = "0.8" -xml-schema-derive = { version = "0.3.0", path = "../xml_schema_derive" } yaserde_derive = { version = "0.9" } yaserde = { version = "0.9" } +log = "0.4" +reqwest = { version = "0.11", default-features = false, features = ["blocking"] } + +[dev-dependencies] diff --git a/xml_schema/src/lib.rs b/xml_schema/src/lib.rs index 9f422f1..ab7f37d 100644 --- a/xml_schema/src/lib.rs +++ b/xml_schema/src/lib.rs @@ -1,4 +1,5 @@ -#[cfg(feature = "xml_schema_derive")] -#[allow(unused_imports)] #[macro_use] -extern crate xml_schema_derive; +extern crate yaserde_derive; + +mod xsd; +pub use xsd::*; diff --git a/xml_schema/src/xsd/annotation.rs b/xml_schema/src/xsd/annotation.rs new file mode 100644 index 0000000..c61fc3e --- /dev/null +++ b/xml_schema/src/xsd/annotation.rs @@ -0,0 +1,20 @@ +use crate::xsd::attribute::Attribute; + +#[derive(Clone, Default, Debug, PartialEq, YaDeserialize)] +#[yaserde( + rename = "annotation" + prefix = "xs", + namespace = "xs: http://www.w3.org/2001/XMLSchema" + )] +pub struct Annotation { + #[yaserde(attribute)] + pub id: Option, + #[yaserde(rename = "attribute")] + pub attributes: Vec, + #[yaserde( + rename = "documentation" + prefix = "xs", + namespace = "xs: http://www.w3.org/2001/XMLSchema" + )] + pub documentation: Vec, +} diff --git a/xml_schema/src/xsd/attribute.rs b/xml_schema/src/xsd/attribute.rs new file mode 100644 index 0000000..1afa1cf --- /dev/null +++ b/xml_schema/src/xsd/attribute.rs @@ -0,0 +1,33 @@ +use crate::xsd::simple_type::SimpleType; + +#[derive(Clone, Default, Debug, PartialEq, YaDeserialize)] +#[yaserde( + rename = "attribute", + prefix = "xs", + namespace = "xs: http://www.w3.org/2001/XMLSchema" +)] +pub struct Attribute { + #[yaserde(prefix = "xs", attribute)] + pub name: Option, + #[yaserde(rename = "type", attribute)] + pub kind: Option, + // #[yaserde(attribute)] + // pub default: Option, + // #[yaserde(attribute)] + // pub fixed: Option, + #[yaserde(rename = "use", attribute)] + pub required: Required, + #[yaserde(rename = "ref", attribute)] + pub reference: Option, + #[yaserde(rename = "simpleType")] + pub simple_type: Option, +} + +#[derive(Clone, Debug, Default, PartialEq, YaDeserialize)] +pub enum Required { + #[default] + #[yaserde(rename = "optional")] + Optional, + #[yaserde(rename = "required")] + Required, +} diff --git a/xml_schema_derive/src/xsd/attribute_group.rs b/xml_schema/src/xsd/attribute_group.rs similarity index 100% rename from xml_schema_derive/src/xsd/attribute_group.rs rename to xml_schema/src/xsd/attribute_group.rs diff --git a/xml_schema/src/xsd/complex_content.rs b/xml_schema/src/xsd/complex_content.rs new file mode 100644 index 0000000..2ce9e7e --- /dev/null +++ b/xml_schema/src/xsd/complex_content.rs @@ -0,0 +1,7 @@ +use crate::xsd::extension::Extension; + +#[derive(Clone, Default, Debug, PartialEq, YaDeserialize)] +#[yaserde(prefix = "xs", namespace = "xs: http://www.w3.org/2001/XMLSchema")] +pub struct ComplexContent { + pub extension: Option, +} diff --git a/xml_schema/src/xsd/complex_type.rs b/xml_schema/src/xsd/complex_type.rs new file mode 100644 index 0000000..acbd782 --- /dev/null +++ b/xml_schema/src/xsd/complex_type.rs @@ -0,0 +1,24 @@ +use crate::xsd::{ + annotation::Annotation, attribute::Attribute, complex_content::ComplexContent, + sequence::Sequence, simple_content::SimpleContent, +}; + +#[derive(Clone, Default, Debug, PartialEq, YaDeserialize)] +#[yaserde( + rename = "complexType" + prefix = "xs", + namespace = "xs: http://www.w3.org/2001/XMLSchema" +)] +pub struct ComplexType { + #[yaserde(attribute)] + pub name: String, + #[yaserde(rename = "attribute")] + pub attributes: Vec, + pub sequence: Option, + #[yaserde(rename = "simpleContent")] + pub simple_content: Option, + #[yaserde(rename = "complexContent")] + pub complex_content: Option, + #[yaserde(rename = "annotation")] + pub annotation: Option, +} diff --git a/xml_schema_derive/src/xsd/context.rs b/xml_schema/src/xsd/context.rs similarity index 100% rename from xml_schema_derive/src/xsd/context.rs rename to xml_schema/src/xsd/context.rs diff --git a/xml_schema/src/xsd/element.rs b/xml_schema/src/xsd/element.rs new file mode 100644 index 0000000..dc26f2c --- /dev/null +++ b/xml_schema/src/xsd/element.rs @@ -0,0 +1,37 @@ +use crate::xsd::{ + annotation::Annotation, complex_type::ComplexType, max_occurences::MaxOccurences, + simple_type::SimpleType, +}; + +#[derive(Clone, Default, Debug, PartialEq, YaDeserialize)] +#[yaserde(prefix = "xs", namespace = "xs: http://www.w3.org/2001/XMLSchema")] +pub struct Element { + #[yaserde(attribute)] + pub name: String, + #[yaserde(rename = "type", attribute)] + pub kind: Option, + #[yaserde(rename = "ref", attribute)] + pub refers: Option, + #[yaserde(rename = "minOccurs", attribute)] + pub min_occurences: Option, + #[yaserde(rename = "maxOccurs", attribute)] + pub max_occurences: Option, + #[yaserde(rename = "complexType")] + pub complex_type: Option, + #[yaserde(rename = "simpleType")] + pub simple_type: Option, + #[yaserde(rename = "annotation")] + pub annotation: Option, +} + +impl Element { + pub fn get_refers(&self) -> Option<&str> { + self.refers.as_ref().and_then(|refers| { + if refers.is_empty() { + None + } else { + Some(refers.as_str()) + } + }) + } +} diff --git a/xml_schema/src/xsd/extension.rs b/xml_schema/src/xsd/extension.rs new file mode 100644 index 0000000..7f6f670 --- /dev/null +++ b/xml_schema/src/xsd/extension.rs @@ -0,0 +1,18 @@ +use crate::xsd::{attribute::Attribute, group::Group, sequence::Sequence}; + +#[derive(Clone, Default, Debug, PartialEq, YaDeserialize)] +#[yaserde( + root = "extension", + prefix = "xs", + namespace = "xs: http://www.w3.org/2001/XMLSchema" +)] +pub struct Extension { + #[yaserde(attribute)] + pub base: String, + #[yaserde(rename = "attribute")] + pub attributes: Vec, + #[yaserde(rename = "sequence")] + pub sequences: Vec, + #[yaserde(rename = "group")] + pub group: Option, +} diff --git a/xml_schema/src/xsd/group.rs b/xml_schema/src/xsd/group.rs new file mode 100644 index 0000000..108e296 --- /dev/null +++ b/xml_schema/src/xsd/group.rs @@ -0,0 +1,12 @@ +use crate::xsd::sequence::Sequence; + +#[derive(Clone, Default, Debug, PartialEq, YaDeserialize)] +#[yaserde(prefix = "xs", namespace = "xs: http://www.w3.org/2001/XMLSchema")] +pub struct Group { + #[yaserde(attribute)] + pub name: Option, + #[yaserde(attribute, rename = "ref")] + pub reference: Option, + #[yaserde()] + pub sequence: Option, +} diff --git a/xml_schema_derive/src/xsd/import.rs b/xml_schema/src/xsd/import.rs similarity index 100% rename from xml_schema_derive/src/xsd/import.rs rename to xml_schema/src/xsd/import.rs diff --git a/xml_schema/src/xsd/list.rs b/xml_schema/src/xsd/list.rs new file mode 100644 index 0000000..90fc6b6 --- /dev/null +++ b/xml_schema/src/xsd/list.rs @@ -0,0 +1,6 @@ +#[derive(Clone, Default, Debug, PartialEq, YaDeserialize)] +#[yaserde(prefix = "xs", namespace = "xs: http://www.w3.org/2001/XMLSchema")] +pub struct List { + #[yaserde(rename = "itemType", attribute)] + pub item_type: String, +} diff --git a/xml_schema_derive/src/xsd/max_occurences.rs b/xml_schema/src/xsd/max_occurences.rs similarity index 100% rename from xml_schema_derive/src/xsd/max_occurences.rs rename to xml_schema/src/xsd/max_occurences.rs diff --git a/xml_schema/src/xsd/mod.rs b/xml_schema/src/xsd/mod.rs new file mode 100644 index 0000000..ea0b1a0 --- /dev/null +++ b/xml_schema/src/xsd/mod.rs @@ -0,0 +1,96 @@ +mod annotation; +mod attribute; +mod attribute_group; +mod complex_content; +mod complex_type; +mod element; +mod extension; +mod group; +mod import; +mod list; +mod max_occurences; +mod qualification; +mod restriction; +mod schema; +mod sequence; +mod simple_content; +mod simple_type; +mod union; +mod xsd_context; + +pub use annotation::*; +pub use attribute::*; +pub use attribute_group::*; +pub use complex_content::*; +pub use complex_type::*; +pub use element::*; +pub use extension::*; +pub use group::*; +pub use import::*; +pub use list::*; +pub use max_occurences::*; +pub use qualification::*; +pub use restriction::*; +pub use schema::*; +pub use sequence::*; +pub use simple_content::*; +pub use simple_type::*; +pub use union::*; +pub use xsd_context::*; + +use std::collections::BTreeMap; +use std::fs; +use yaserde::de::from_str; + +#[derive(Clone, Debug)] +pub struct Xsd { + pub name: String, + pub context: XsdContext, + pub schema: schema::Schema, +} + +impl Xsd { + pub fn new( + name: String, + content: &str, + module_namespace_mappings: &BTreeMap, + ) -> Result { + let context = XsdContext::new(content)?; + let context = context.with_module_namespace_mappings(module_namespace_mappings); + let schema: schema::Schema = from_str(content)?; + + Ok(Xsd { + name, + context, + schema, + }) + } + + pub fn new_from_file( + name: String, + source: &str, + module_namespace_mappings: &BTreeMap, + ) -> Result { + let content = if source.starts_with("http://") || source.starts_with("https://") { + log::info!("Load HTTP schema {}", source); + reqwest::blocking::get(source) + .map_err(|e| e.to_string())? + .text() + .map_err(|e| e.to_string())? + } else { + let path = std::env::current_dir().unwrap(); + log::info!("The current directory is {}", path.display()); + + fs::read_to_string(source).map_err(|e| e.to_string())? + }; + + // skip BOM header, can be present on some files + let content = if content.as_bytes()[0..3] == [0xef, 0xbb, 0xbf] { + content[3..].to_owned() + } else { + content + }; + + Xsd::new(name, &content, module_namespace_mappings) + } +} diff --git a/xml_schema_derive/src/xsd/qualification.rs b/xml_schema/src/xsd/qualification.rs similarity index 100% rename from xml_schema_derive/src/xsd/qualification.rs rename to xml_schema/src/xsd/qualification.rs diff --git a/xml_schema/src/xsd/restriction.rs b/xml_schema/src/xsd/restriction.rs new file mode 100644 index 0000000..5ee0037 --- /dev/null +++ b/xml_schema/src/xsd/restriction.rs @@ -0,0 +1,6 @@ +#[derive(Clone, Default, Debug, PartialEq, YaDeserialize)] +#[yaserde(prefix = "xs", namespace = "xs: http://www.w3.org/2001/XMLSchema")] +pub struct Restriction { + #[yaserde(rename = "base", attribute)] + pub base: Option, +} diff --git a/xml_schema/src/xsd/schema.rs b/xml_schema/src/xsd/schema.rs new file mode 100644 index 0000000..911455d --- /dev/null +++ b/xml_schema/src/xsd/schema.rs @@ -0,0 +1,32 @@ +use crate::xsd::{ + attribute, attribute_group, complex_type, element, group, import, qualification, simple_type, +}; + +#[derive(Clone, Default, Debug, PartialEq, YaDeserialize)] +#[yaserde( + root="schema" + prefix="xs", + namespace="xs: http://www.w3.org/2001/XMLSchema", +)] +pub struct Schema { + #[yaserde(rename = "targetNamespace", attribute)] + pub target_namespace: Option, + #[yaserde(rename = "elementFormDefault", attribute)] + pub element_form_default: Option, + #[yaserde(rename = "attributeFormDefault", attribute)] + pub attribute_form_default: Option, + #[yaserde(rename = "import")] + pub imports: Vec, + #[yaserde(rename = "element")] + pub elements: Vec, + #[yaserde(rename = "simpleType")] + pub simple_type: Vec, + #[yaserde(rename = "complexType")] + pub complex_type: Vec, + #[yaserde(rename = "attribute")] + pub attributes: Vec, + #[yaserde(rename = "attributeGroup")] + pub attribute_group: Vec, + #[yaserde(rename = "group")] + pub group: Vec, +} diff --git a/xml_schema/src/xsd/sequence.rs b/xml_schema/src/xsd/sequence.rs new file mode 100644 index 0000000..244ae85 --- /dev/null +++ b/xml_schema/src/xsd/sequence.rs @@ -0,0 +1,8 @@ +use crate::xsd::element::Element; + +#[derive(Clone, Default, Debug, PartialEq, YaDeserialize)] +#[yaserde(prefix = "xs", namespace = "xs: http://www.w3.org/2001/XMLSchema")] +pub struct Sequence { + #[yaserde(rename = "element")] + pub elements: Vec, +} diff --git a/xml_schema/src/xsd/simple_content.rs b/xml_schema/src/xsd/simple_content.rs new file mode 100644 index 0000000..ec48fcb --- /dev/null +++ b/xml_schema/src/xsd/simple_content.rs @@ -0,0 +1,8 @@ +use crate::xsd::extension::Extension; + +#[derive(Clone, Default, Debug, PartialEq, YaDeserialize)] +#[yaserde(prefix = "xs", namespace = "xs: http://www.w3.org/2001/XMLSchema")] +pub struct SimpleContent { + #[yaserde(prefix = "xs", rename = "extension")] + pub extension: Extension, +} diff --git a/xml_schema/src/xsd/simple_type.rs b/xml_schema/src/xsd/simple_type.rs new file mode 100644 index 0000000..5399bea --- /dev/null +++ b/xml_schema/src/xsd/simple_type.rs @@ -0,0 +1,11 @@ +use crate::xsd::{list::List, restriction::Restriction, union::Union}; + +#[derive(Clone, Default, Debug, PartialEq, YaDeserialize)] +#[yaserde(prefix = "xs", namespace = "xs: http://www.w3.org/2001/XMLSchema")] +pub struct SimpleType { + #[yaserde(attribute)] + pub name: String, + pub restriction: Option, + pub list: Option, + pub union: Option, +} diff --git a/xml_schema_derive/src/xsd/union.rs b/xml_schema/src/xsd/union.rs similarity index 100% rename from xml_schema_derive/src/xsd/union.rs rename to xml_schema/src/xsd/union.rs diff --git a/xml_schema_derive/src/xsd/xsd_context.rs b/xml_schema/src/xsd/xsd_context.rs similarity index 100% rename from xml_schema_derive/src/xsd/xsd_context.rs rename to xml_schema/src/xsd/xsd_context.rs diff --git a/xml_schema_derive/Cargo.toml b/xml_schema_derive/Cargo.toml index 7b626d3..a9edecb 100644 --- a/xml_schema_derive/Cargo.toml +++ b/xml_schema_derive/Cargo.toml @@ -19,6 +19,7 @@ proc-macro = true default = ["reqwest/default-tls"] [dependencies] +xml-schema = { path = "../xml_schema"} darling = "0.20.3" heck = "0.4" log = "0.4" diff --git a/xml_schema_derive/src/expander.rs b/xml_schema_derive/src/expander.rs index 13bbbff..2475008 100644 --- a/xml_schema_derive/src/expander.rs +++ b/xml_schema_derive/src/expander.rs @@ -1,7 +1,9 @@ -use crate::{attribute::XmlSchemaAttributes, xsd::Xsd}; +use crate::{attribute::XmlSchemaAttributes, xsd::implement_xsd}; use proc_macro2::TokenStream; use syn::{token::Pub, Visibility}; +use xml_schema::Xsd; + pub fn expand_derive(attributes: &XmlSchemaAttributes) -> Result { let _ = simple_logger::init_with_level(attributes.log_level()); log::info!("{:?}", attributes); @@ -10,11 +12,10 @@ pub fn expand_derive(attributes: &XmlSchemaAttributes) -> Result, - #[yaserde(rename = "attribute")] - pub attributes: Vec, - #[yaserde( - rename = "documentation" - prefix = "xs", - namespace = "xs: http://www.w3.org/2001/XMLSchema" - )] - pub documentation: Vec, -} +use xml_schema::Annotation; impl Implementation for Annotation { fn implement( diff --git a/xml_schema_derive/src/xsd/attribute.rs b/xml_schema_derive/src/xsd/attribute.rs index 522915e..291a305 100644 --- a/xml_schema_derive/src/xsd/attribute.rs +++ b/xml_schema_derive/src/xsd/attribute.rs @@ -1,41 +1,9 @@ -use crate::xsd::{ - rust_types_mapping::RustTypesMapping, simple_type::SimpleType, Implementation, XsdContext, -}; +use crate::xsd::{rust_types_mapping::RustTypesMapping, Implementation, XsdContext}; use heck::ToSnakeCase; use proc_macro2::{Span, TokenStream}; use syn::Ident; -#[derive(Clone, Default, Debug, PartialEq, YaDeserialize)] -#[yaserde( - rename = "attribute", - prefix = "xs", - namespace = "xs: http://www.w3.org/2001/XMLSchema" -)] -pub struct Attribute { - #[yaserde(prefix = "xs", attribute)] - pub name: Option, - #[yaserde(rename = "type", attribute)] - pub kind: Option, - // #[yaserde(attribute)] - // pub default: Option, - // #[yaserde(attribute)] - // pub fixed: Option, - #[yaserde(rename = "use", attribute)] - pub required: Required, - #[yaserde(rename = "ref", attribute)] - pub reference: Option, - #[yaserde(rename = "simpleType")] - pub simple_type: Option, -} - -#[derive(Clone, Debug, Default, PartialEq, YaDeserialize)] -pub enum Required { - #[default] - #[yaserde(rename = "optional")] - Optional, - #[yaserde(rename = "required")] - Required, -} +use xml_schema::{Attribute, Required}; impl Implementation for Attribute { fn implement( @@ -65,7 +33,7 @@ impl Implementation for Attribute { ) { (None, Some(kind), None) => RustTypesMapping::get(context, kind), (Some(reference), None, None) => RustTypesMapping::get(context, reference), - (None, None, Some(simple_type)) => simple_type.get_type_implementation(context, prefix), + (None, None, Some(simple_type)) => simple_type.get_type_implementation(prefix, context), (_, _, _) => panic!("Not implemented Rust type for: {:?}", self), }; diff --git a/xml_schema_derive/src/xsd/complex_content.rs b/xml_schema_derive/src/xsd/complex_content.rs index 3e3d67a..799b4c5 100644 --- a/xml_schema_derive/src/xsd/complex_content.rs +++ b/xml_schema_derive/src/xsd/complex_content.rs @@ -1,22 +1,14 @@ -use crate::xsd::{extension::Extension, xsd_context::XsdContext}; +use crate::xsd::Implementation; use proc_macro2::TokenStream; -#[derive(Clone, Default, Debug, PartialEq, YaDeserialize)] -#[yaserde(prefix = "xs", namespace = "xs: http://www.w3.org/2001/XMLSchema")] -pub struct ComplexContent { - pub extension: Option, -} +use xml_schema::{ComplexContent, XsdContext}; -impl ComplexContent { - pub fn get_field_implementation( - &self, - context: &XsdContext, - prefix: &Option, - ) -> TokenStream { +impl Implementation for ComplexContent { + fn get_field_implementation(&self, prefix: &Option, context: &XsdContext) -> TokenStream { self .extension .as_ref() .unwrap() - .get_field_implementation(context, prefix) + .get_field_implementation(prefix, context) } } diff --git a/xml_schema_derive/src/xsd/complex_type.rs b/xml_schema_derive/src/xsd/complex_type.rs index d531559..6d7b48c 100644 --- a/xml_schema_derive/src/xsd/complex_type.rs +++ b/xml_schema_derive/src/xsd/complex_type.rs @@ -1,30 +1,9 @@ -use crate::xsd::{ - annotation::Annotation, attribute::Attribute, complex_content::ComplexContent, - sequence::Sequence, simple_content::SimpleContent, Implementation, XsdContext, -}; +use crate::xsd::{Implementation, XsdContext}; use heck::ToUpperCamelCase; use proc_macro2::{Span, TokenStream}; use syn::Ident; -#[derive(Clone, Default, Debug, PartialEq, YaDeserialize)] -#[yaserde( - rename = "complexType" - prefix = "xs", - namespace = "xs: http://www.w3.org/2001/XMLSchema" -)] -pub struct ComplexType { - #[yaserde(attribute)] - pub name: String, - #[yaserde(rename = "attribute")] - pub attributes: Vec, - pub sequence: Option, - #[yaserde(rename = "simpleContent")] - pub simple_content: Option, - #[yaserde(rename = "complexContent")] - pub complex_content: Option, - #[yaserde(rename = "annotation")] - pub annotation: Option, -} +use xml_schema::ComplexType; impl Implementation for ComplexType { fn implement( @@ -55,7 +34,7 @@ impl Implementation for ComplexType { .complex_content .as_ref() .map(|complex_content| { - let complex_content_type = complex_content.get_field_implementation(context, prefix); + let complex_content_type = complex_content.get_field_implementation(prefix, context); quote!( #[yaserde(flatten)] #complex_content_type, @@ -72,7 +51,7 @@ impl Implementation for ComplexType { let sub_types_implementation = self .sequence .as_ref() - .map(|sequence| sequence.get_sub_types_implementation(context, namespace_definition, prefix)) + .map(|sequence| sequence.get_sub_types_implementation(namespace_definition, prefix, context)) .unwrap_or_default(); let docs = self @@ -96,30 +75,24 @@ impl Implementation for ComplexType { #sub_types_implementation } } -} -impl ComplexType { - pub fn get_field_implementation( - &self, - context: &XsdContext, - prefix: &Option, - ) -> TokenStream { + fn get_field_implementation(&self, prefix: &Option, context: &XsdContext) -> TokenStream { if self.sequence.is_some() { self .sequence .as_ref() - .map(|sequence| sequence.get_field_implementation(context, prefix)) + .map(|sequence| sequence.get_field_implementation(prefix, context)) .unwrap_or_default() } else { self .simple_content .as_ref() - .map(|simple_content| simple_content.get_field_implementation(context, prefix)) + .map(|simple_content| simple_content.get_field_implementation(prefix, context)) .unwrap_or_default() } } - pub fn get_integrated_implementation(&self, parent_name: &str) -> TokenStream { + fn get_integrated_implementation(&self, parent_name: &str) -> TokenStream { if self.simple_content.is_some() { return quote!(String); } diff --git a/xml_schema_derive/src/xsd/element.rs b/xml_schema_derive/src/xsd/element.rs index d3775de..12a80a0 100644 --- a/xml_schema_derive/src/xsd/element.rs +++ b/xml_schema_derive/src/xsd/element.rs @@ -1,31 +1,9 @@ -use crate::xsd::{ - annotation::Annotation, complex_type::ComplexType, max_occurences::MaxOccurences, - rust_types_mapping::RustTypesMapping, simple_type::SimpleType, Implementation, XsdContext, -}; +use crate::xsd::{rust_types_mapping::RustTypesMapping, Implementation, XsdContext}; use heck::{ToSnakeCase, 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")] -pub struct Element { - #[yaserde(attribute)] - pub name: String, - #[yaserde(rename = "type", attribute)] - pub kind: Option, - #[yaserde(rename = "ref", attribute)] - pub refers: Option, - #[yaserde(rename = "minOccurs", attribute)] - pub min_occurences: Option, - #[yaserde(rename = "maxOccurs", attribute)] - pub max_occurences: Option, - #[yaserde(rename = "complexType")] - pub complex_type: Option, - #[yaserde(rename = "simpleType")] - pub simple_type: Option, - #[yaserde(rename = "annotation")] - pub annotation: Option, -} +use xml_schema::{Element, MaxOccurences}; impl Implementation for Element { fn implement( @@ -59,7 +37,7 @@ impl Implementation for Element { let fields_definition = self .complex_type .iter() - .map(|complex_type| complex_type.get_field_implementation(context, prefix)) + .map(|complex_type| complex_type.get_field_implementation(prefix, context)) .collect(); (fields_definition, quote!()) @@ -82,10 +60,8 @@ impl Implementation for Element { #extra_structs } } -} -impl Element { - pub fn get_subtypes_implementation( + fn get_subtypes_implementation( &self, namespace_definition: &TokenStream, prefix: &Option, @@ -98,11 +74,7 @@ impl Element { self.implement(namespace_definition, prefix, context) } - pub fn get_field_implementation( - &self, - context: &XsdContext, - prefix: &Option, - ) -> TokenStream { + fn get_field_implementation(&self, prefix: &Option, context: &XsdContext) -> TokenStream { let refers = self.get_refers(); if self.name.is_empty() && refers.is_none() { return quote!(); @@ -139,7 +111,7 @@ impl Element { let rust_type = if let Some(complex_type) = &self.complex_type { complex_type.get_integrated_implementation(&self.name) } else if let Some(simple_type) = &self.simple_type { - simple_type.get_type_implementation(context, &Some(self.name.to_owned())) + simple_type.get_type_implementation(&Some(self.name.to_owned()), context) } else if let Some(kind) = &self.kind { RustTypesMapping::get(context, kind) } else if let Some(refers) = refers { @@ -181,16 +153,6 @@ impl Element { pub #attribute_name: #rust_type, } } - - fn get_refers(&self) -> Option<&str> { - self.refers.as_ref().and_then(|refers| { - if refers.is_empty() { - None - } else { - Some(refers.as_str()) - } - }) - } } #[cfg(test)] @@ -198,6 +160,8 @@ mod tests { use super::*; use std::str::FromStr; + use xml_schema::Annotation; + static DERIVES: &str = "#[derive(Clone, Debug, Default, PartialEq, yaserde_derive::YaDeserialize, yaserde_derive::YaSerialize)]"; @@ -295,7 +259,7 @@ mod tests { XsdContext::new(r#""#) .unwrap(); - let implementation = element.get_field_implementation(&context, &None); + let implementation = element.get_field_implementation(&None, &context); let expected = TokenStream::from_str( r#"#[yaserde(rename = "OwnedType")] pub owned_type : xml_schema_types :: OwnedType ,"#, @@ -316,7 +280,7 @@ mod tests { annotation: None, }; - let implementation = element.get_field_implementation(&context, &None); + let implementation = element.get_field_implementation(&None, &context); let expected = TokenStream::from_str( r#"#[yaserde(rename = "OwnedType")] pub owned_type_list : Vec < xml_schema_types :: OwnedType > ,"# diff --git a/xml_schema_derive/src/xsd/extension.rs b/xml_schema_derive/src/xsd/extension.rs index 7a3c5b8..a1037d3 100644 --- a/xml_schema_derive/src/xsd/extension.rs +++ b/xml_schema_derive/src/xsd/extension.rs @@ -1,25 +1,7 @@ -use crate::xsd::{ - attribute::Attribute, group::Group, rust_types_mapping::RustTypesMapping, sequence::Sequence, - Implementation, XsdContext, -}; +use crate::xsd::{rust_types_mapping::RustTypesMapping, Implementation, XsdContext}; use proc_macro2::TokenStream; -#[derive(Clone, Default, Debug, PartialEq, YaDeserialize)] -#[yaserde( - root = "extension", - prefix = "xs", - namespace = "xs: http://www.w3.org/2001/XMLSchema" -)] -pub struct Extension { - #[yaserde(attribute)] - pub base: String, - #[yaserde(rename = "attribute")] - pub attributes: Vec, - #[yaserde(rename = "sequence")] - pub sequences: Vec, - #[yaserde(rename = "group")] - pub group: Option, -} +use xml_schema::Extension; impl Implementation for Extension { fn implement( @@ -48,21 +30,15 @@ impl Implementation for Extension { #attributes ) } -} -impl Extension { - pub fn get_field_implementation( - &self, - context: &XsdContext, - prefix: &Option, - ) -> TokenStream { + fn get_field_implementation(&self, prefix: &Option, context: &XsdContext) -> TokenStream { let rust_type = RustTypesMapping::get(context, &self.base); let group_content = self .group .as_ref() .map(|group| { - let group_type = group.get_type_implementation(context, prefix); + let group_type = group.get_type_implementation(prefix, context); quote!( , @@ -112,7 +88,7 @@ mod tests { #[test] fn extension_with_attributes() { - use crate::xsd::attribute::Required; + use xml_schema::{Attribute, Required}; let st = Extension { base: "xs:string".to_string(), diff --git a/xml_schema_derive/src/xsd/group.rs b/xml_schema_derive/src/xsd/group.rs index e0eec34..1efe4cb 100644 --- a/xml_schema_derive/src/xsd/group.rs +++ b/xml_schema_derive/src/xsd/group.rs @@ -1,20 +1,9 @@ -use crate::xsd::{ - rust_types_mapping::RustTypesMapping, sequence::Sequence, Implementation, XsdContext, -}; +use crate::xsd::{rust_types_mapping::RustTypesMapping, 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")] -pub struct Group { - #[yaserde(attribute)] - pub name: Option, - #[yaserde(attribute, rename = "ref")] - pub reference: Option, - #[yaserde()] - pub sequence: Option, -} +use xml_schema::Group; impl Implementation for Group { fn implement( @@ -33,7 +22,7 @@ impl Implementation for Group { let fields = self .sequence .as_ref() - .map(|sequence| sequence.get_field_implementation(context, prefix)) + .map(|sequence| sequence.get_field_implementation(prefix, context)) .unwrap_or_default(); quote!( @@ -44,14 +33,8 @@ impl Implementation for Group { } ) } -} -impl Group { - pub fn get_type_implementation( - &self, - context: &XsdContext, - _prefix: &Option, - ) -> TokenStream { + fn get_type_implementation(&self, _prefix: &Option, context: &XsdContext) -> TokenStream { if let Some(reference) = &self.reference { RustTypesMapping::get(context, reference) } else { @@ -101,7 +84,7 @@ pub struct Groupthing { \ XsdContext::new(r#""#) .unwrap(); - let type_implementation = format!("{}", group.get_type_implementation(&context, &None)); + let type_implementation = format!("{}", group.get_type_implementation(&None, &context)); assert_eq!(type_implementation, "Groupthing"); } diff --git a/xml_schema_derive/src/xsd/list.rs b/xml_schema_derive/src/xsd/list.rs index c64aae6..826b313 100644 --- a/xml_schema_derive/src/xsd/list.rs +++ b/xml_schema_derive/src/xsd/list.rs @@ -1,12 +1,7 @@ use crate::xsd::{rust_types_mapping::RustTypesMapping, Implementation, XsdContext}; use proc_macro2::{Ident, TokenStream}; -#[derive(Clone, Default, Debug, PartialEq, YaDeserialize)] -#[yaserde(prefix = "xs", namespace = "xs: http://www.w3.org/2001/XMLSchema")] -pub struct List { - #[yaserde(rename = "itemType", attribute)] - pub item_type: String, -} +use xml_schema::List; impl Implementation for List { fn implement_childs( diff --git a/xml_schema_derive/src/xsd/mod.rs b/xml_schema_derive/src/xsd/mod.rs index 43811b4..07bb10d 100644 --- a/xml_schema_derive/src/xsd/mod.rs +++ b/xml_schema_derive/src/xsd/mod.rs @@ -1,31 +1,23 @@ mod annotation; mod attribute; -mod attribute_group; mod complex_content; mod complex_type; mod element; mod extension; mod group; -mod import; mod list; -mod max_occurences; -mod qualification; mod restriction; mod rust_types_mapping; mod schema; mod sequence; mod simple_content; mod simple_type; -mod union; -mod xsd_context; use heck::ToSnakeCase; use proc_macro2::{Ident, TokenStream}; -use std::collections::BTreeMap; -use std::fs; use syn::Visibility; -use xsd_context::XsdContext; -use yaserde::de::from_str; + +use xml_schema::{Xsd, XsdContext}; trait Implementation { fn implement( @@ -46,78 +38,62 @@ trait Implementation { ) -> TokenStream { unimplemented!() } -} - -#[derive(Clone, Debug)] -pub struct Xsd { - name: String, - vis: Visibility, - context: XsdContext, - schema: schema::Schema, -} -impl Xsd { - pub fn new( - name: String, - vis: Visibility, - content: &str, - module_namespace_mappings: &BTreeMap, - ) -> Result { - let context = XsdContext::new(content)?; - let context = context.with_module_namespace_mappings(module_namespace_mappings); - let schema: schema::Schema = from_str(content)?; - - Ok(Xsd { - name, - vis, - context, - schema, - }) + fn get_type_implementation( + &self, + _prefix: &Option, + _context: &XsdContext, + ) -> TokenStream { + unimplemented!() } - pub fn new_from_file( - name: String, - vis: Visibility, - source: &str, - module_namespace_mappings: &BTreeMap, - ) -> Result { - let content = if source.starts_with("http://") || source.starts_with("https://") { - log::info!("Load HTTP schema {}", source); - reqwest::blocking::get(source) - .map_err(|e| e.to_string())? - .text() - .map_err(|e| e.to_string())? - } else { - let path = std::env::current_dir().unwrap(); - log::info!("The current directory is {}", path.display()); + fn get_subtypes_implementation( + &self, + _namespace_definition: &TokenStream, + _prefix: &Option, + _context: &XsdContext, + ) -> TokenStream { + unimplemented!() + } - fs::read_to_string(source).map_err(|e| e.to_string())? - }; + fn get_sub_types_implementation( + &self, + _namespace_definition: &TokenStream, + _prefix: &Option, + _context: &XsdContext, + ) -> TokenStream { + unimplemented!() + } - // skip BOM header, can be present on some files - let content = if content.as_bytes()[0..3] == [0xef, 0xbb, 0xbf] { - content[3..].to_owned() - } else { - content - }; + fn get_field_implementation( + &self, + _prefix: &Option, + _context: &XsdContext, + ) -> TokenStream { + unimplemented!() + } - Xsd::new(name, vis, &content, module_namespace_mappings) + fn get_integrated_implementation(&self, _parent_name: &str) -> TokenStream { + unimplemented!() } +} - pub fn implement(&self, target_prefix: &Option) -> TokenStream { - let schema = self - .schema - .implement(&TokenStream::new(), target_prefix, &self.context); +pub fn implement_xsd( + xsd: &Xsd, + visibility: Visibility, + target_prefix: &Option, +) -> TokenStream { + let schema = xsd + .schema + .implement(&TokenStream::new(), target_prefix, &xsd.context); - let mod_name = format_ident!("{}", self.name.to_snake_case()); - let vis = &self.vis; + let mod_name = format_ident!("{}", xsd.name.to_snake_case()); - quote! { - mod #mod_name { - #schema - } + quote! { + mod #mod_name { + #schema + } - #vis use #mod_name::*; - } + #visibility use #mod_name::*; } } diff --git a/xml_schema_derive/src/xsd/restriction.rs b/xml_schema_derive/src/xsd/restriction.rs index 5915e81..d8ea155 100644 --- a/xml_schema_derive/src/xsd/restriction.rs +++ b/xml_schema_derive/src/xsd/restriction.rs @@ -1,19 +1,11 @@ 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 Restriction { - #[yaserde(rename = "base", attribute)] - pub base: Option, -} +use crate::xsd::Implementation; +use xml_schema::Restriction; -impl Restriction { - pub fn get_type_implementation( - &self, - context: &XsdContext, - _prefix: &Option, - ) -> TokenStream { +impl Implementation for Restriction { + fn get_type_implementation(&self, _prefix: &Option, context: &XsdContext) -> TokenStream { if let Some(base) = &self.base { RustTypesMapping::get(context, base) } else { diff --git a/xml_schema_derive/src/xsd/schema.rs b/xml_schema_derive/src/xsd/schema.rs index 09345b2..cdb2990 100644 --- a/xml_schema_derive/src/xsd/schema.rs +++ b/xml_schema_derive/src/xsd/schema.rs @@ -1,37 +1,7 @@ -use crate::xsd::{ - attribute, attribute_group, complex_type, element, group, import, qualification, simple_type, - Implementation, XsdContext, -}; +use crate::xsd::{Implementation, XsdContext}; use proc_macro2::TokenStream; -#[derive(Clone, Default, Debug, PartialEq, YaDeserialize)] -#[yaserde( - root="schema" - prefix="xs", - namespace="xs: http://www.w3.org/2001/XMLSchema", -)] -pub struct Schema { - #[yaserde(rename = "targetNamespace", attribute)] - pub target_namespace: Option, - #[yaserde(rename = "elementFormDefault", attribute)] - pub element_form_default: Option, - #[yaserde(rename = "attributeFormDefault", attribute)] - pub attribute_form_default: Option, - #[yaserde(rename = "import")] - pub imports: Vec, - #[yaserde(rename = "element")] - pub elements: Vec, - #[yaserde(rename = "simpleType")] - pub simple_type: Vec, - #[yaserde(rename = "complexType")] - pub complex_type: Vec, - #[yaserde(rename = "attribute")] - pub attributes: Vec, - #[yaserde(rename = "attributeGroup")] - pub attribute_group: Vec, - #[yaserde(rename = "group")] - pub group: Vec, -} +use xml_schema::Schema; impl Implementation for Schema { fn implement( diff --git a/xml_schema_derive/src/xsd/sequence.rs b/xml_schema_derive/src/xsd/sequence.rs index a39d2f1..9056d65 100644 --- a/xml_schema_derive/src/xsd/sequence.rs +++ b/xml_schema_derive/src/xsd/sequence.rs @@ -1,13 +1,8 @@ -use crate::xsd::{element::Element, Implementation, XsdContext}; +use crate::xsd::{Implementation, XsdContext}; use log::info; use proc_macro2::TokenStream; -#[derive(Clone, Default, Debug, PartialEq, YaDeserialize)] -#[yaserde(prefix = "xs", namespace = "xs: http://www.w3.org/2001/XMLSchema")] -pub struct Sequence { - #[yaserde(rename = "element")] - pub elements: Vec, -} +use xml_schema::Sequence; impl Implementation for Sequence { fn implement( @@ -20,17 +15,15 @@ impl Implementation for Sequence { self .elements .iter() - .map(|element| element.get_field_implementation(context, prefix)) + .map(|element| element.get_field_implementation(prefix, context)) .collect() } -} -impl Sequence { - pub fn get_sub_types_implementation( + fn get_sub_types_implementation( &self, - context: &XsdContext, namespace_definition: &TokenStream, prefix: &Option, + context: &XsdContext, ) -> TokenStream { info!("Generate sub types implementation"); self @@ -40,15 +33,11 @@ impl Sequence { .collect() } - pub fn get_field_implementation( - &self, - context: &XsdContext, - prefix: &Option, - ) -> TokenStream { + fn get_field_implementation(&self, prefix: &Option, context: &XsdContext) -> TokenStream { self .elements .iter() - .map(|element| element.get_field_implementation(context, prefix)) + .map(|element| element.get_field_implementation(prefix, context)) .collect() } } diff --git a/xml_schema_derive/src/xsd/simple_content.rs b/xml_schema_derive/src/xsd/simple_content.rs index 738fab1..39457a6 100644 --- a/xml_schema_derive/src/xsd/simple_content.rs +++ b/xml_schema_derive/src/xsd/simple_content.rs @@ -1,12 +1,7 @@ -use crate::xsd::{extension::Extension, Implementation, XsdContext}; +use crate::xsd::{Implementation, XsdContext}; use proc_macro2::TokenStream; -#[derive(Clone, Default, Debug, PartialEq, YaDeserialize)] -#[yaserde(prefix = "xs", namespace = "xs: http://www.w3.org/2001/XMLSchema")] -pub struct SimpleContent { - #[yaserde(prefix = "xs", rename = "extension")] - pub extension: Extension, -} +use xml_schema::SimpleContent; impl Implementation for SimpleContent { fn implement( @@ -19,14 +14,8 @@ impl Implementation for SimpleContent { .extension .implement(namespace_definition, prefix, context) } -} -impl SimpleContent { - pub fn get_field_implementation( - &self, - context: &XsdContext, - prefix: &Option, - ) -> TokenStream { - self.extension.get_field_implementation(context, prefix) + fn get_field_implementation(&self, prefix: &Option, context: &XsdContext) -> TokenStream { + self.extension.get_field_implementation(prefix, context) } } diff --git a/xml_schema_derive/src/xsd/simple_type.rs b/xml_schema_derive/src/xsd/simple_type.rs index dc184aa..0fa8b6e 100644 --- a/xml_schema_derive/src/xsd/simple_type.rs +++ b/xml_schema_derive/src/xsd/simple_type.rs @@ -1,17 +1,9 @@ -use crate::xsd::{list::List, restriction::Restriction, union::Union, Implementation, XsdContext}; +use crate::xsd::{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")] -pub struct SimpleType { - #[yaserde(attribute)] - pub name: String, - pub restriction: Option, - pub list: Option, - pub union: Option, -} +use xml_schema::SimpleType; impl Implementation for SimpleType { fn implement( @@ -35,16 +27,10 @@ impl Implementation for SimpleType { } ) } -} -impl SimpleType { - pub fn get_type_implementation( - &self, - context: &XsdContext, - prefix: &Option, - ) -> TokenStream { + fn get_type_implementation(&self, prefix: &Option, context: &XsdContext) -> TokenStream { if let Some(restriction) = &self.restriction { - restriction.get_type_implementation(context, prefix) + restriction.get_type_implementation(prefix, context) } else { panic!("No restriction for this simple type {:?}", self); } diff --git a/xml_schema/tests/complex_type.rs b/xml_schema_derive/tests/complex_type.rs similarity index 92% rename from xml_schema/tests/complex_type.rs rename to xml_schema_derive/tests/complex_type.rs index 320bd3a..ff7fabb 100644 --- a/xml_schema/tests/complex_type.rs +++ b/xml_schema_derive/tests/complex_type.rs @@ -5,7 +5,7 @@ use yaserde::ser::to_string; #[test] fn complex_type_string() { #[derive(Debug, XmlSchema)] - #[xml_schema(source = "xml_schema/tests/complex_type.xsd")] + #[xml_schema(source = "xml_schema_derive/tests/complex_type.xsd")] struct ComplexTypeSchema; let xml_1 = r#" diff --git a/xml_schema/tests/complex_type.xsd b/xml_schema_derive/tests/complex_type.xsd similarity index 100% rename from xml_schema/tests/complex_type.xsd rename to xml_schema_derive/tests/complex_type.xsd diff --git a/xml_schema/tests/dmarc_rua.rs b/xml_schema_derive/tests/dmarc_rua.rs similarity index 93% rename from xml_schema/tests/dmarc_rua.rs rename to xml_schema_derive/tests/dmarc_rua.rs index 718f136..66bfb18 100644 --- a/xml_schema/tests/dmarc_rua.rs +++ b/xml_schema_derive/tests/dmarc_rua.rs @@ -4,7 +4,10 @@ use yaserde::de::from_str; #[test] fn dmarc_rua_string() { #[derive(Debug, XmlSchema)] - #[xml_schema(source = "xml_schema/tests/dmarc_rua.xsd", target_prefix = "dmarc")] + #[xml_schema( + source = "xml_schema_derive/tests/dmarc_rua.xsd", + target_prefix = "dmarc" + )] struct DmarcRuaSchema; let xml_1 = r#" diff --git a/xml_schema/tests/dmarc_rua.xsd b/xml_schema_derive/tests/dmarc_rua.xsd similarity index 100% rename from xml_schema/tests/dmarc_rua.xsd rename to xml_schema_derive/tests/dmarc_rua.xsd diff --git a/xml_schema/tests/simple_type.rs b/xml_schema_derive/tests/simple_type.rs similarity index 90% rename from xml_schema/tests/simple_type.rs rename to xml_schema_derive/tests/simple_type.rs index 2ca893e..83f7d65 100644 --- a/xml_schema/tests/simple_type.rs +++ b/xml_schema_derive/tests/simple_type.rs @@ -6,7 +6,7 @@ use yaserde::ser::to_string; fn simple_type_string() { #[derive(Debug, XmlSchema)] #[xml_schema( - source = "xml_schema/tests/simple_type_string.xsd", + source = "xml_schema_derive/tests/simple_type_string.xsd", target_prefix = "st" )] struct SimpleTypeSchema; @@ -29,7 +29,7 @@ fn simple_type_string() { #[test] fn simple_type_list() { #[derive(Debug, XmlSchema)] - #[xml_schema(source = "xml_schema/tests/simple_type_list.xsd")] + #[xml_schema(source = "xml_schema_derive/tests/simple_type_list.xsd")] struct SimpleTypeSchema; let xml_1 = r#" diff --git a/xml_schema/tests/simple_type_list.xsd b/xml_schema_derive/tests/simple_type_list.xsd similarity index 100% rename from xml_schema/tests/simple_type_list.xsd rename to xml_schema_derive/tests/simple_type_list.xsd diff --git a/xml_schema/tests/simple_type_string.xsd b/xml_schema_derive/tests/simple_type_string.xsd similarity index 100% rename from xml_schema/tests/simple_type_string.xsd rename to xml_schema_derive/tests/simple_type_string.xsd