Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Schema lib #53

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 4 additions & 5 deletions xml_schema/Cargo.toml
Original file line number Diff line number Diff line change
@@ -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]
7 changes: 4 additions & 3 deletions xml_schema/src/lib.rs
Original file line number Diff line number Diff line change
@@ -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::*;
20 changes: 20 additions & 0 deletions xml_schema/src/xsd/annotation.rs
Original file line number Diff line number Diff line change
@@ -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<String>,
#[yaserde(rename = "attribute")]
pub attributes: Vec<Attribute>,
#[yaserde(
rename = "documentation"
prefix = "xs",
namespace = "xs: http://www.w3.org/2001/XMLSchema"
)]
pub documentation: Vec<String>,
}
33 changes: 33 additions & 0 deletions xml_schema/src/xsd/attribute.rs
Original file line number Diff line number Diff line change
@@ -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<String>,
#[yaserde(rename = "type", attribute)]
pub kind: Option<String>,
// #[yaserde(attribute)]
// pub default: Option<String>,
// #[yaserde(attribute)]
// pub fixed: Option<String>,
#[yaserde(rename = "use", attribute)]
pub required: Required,
#[yaserde(rename = "ref", attribute)]
pub reference: Option<String>,
#[yaserde(rename = "simpleType")]
pub simple_type: Option<SimpleType>,
}

#[derive(Clone, Debug, Default, PartialEq, YaDeserialize)]
pub enum Required {
#[default]
#[yaserde(rename = "optional")]
Optional,
#[yaserde(rename = "required")]
Required,
}
File renamed without changes.
7 changes: 7 additions & 0 deletions xml_schema/src/xsd/complex_content.rs
Original file line number Diff line number Diff line change
@@ -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<Extension>,
}
24 changes: 24 additions & 0 deletions xml_schema/src/xsd/complex_type.rs
Original file line number Diff line number Diff line change
@@ -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<Attribute>,
pub sequence: Option<Sequence>,
#[yaserde(rename = "simpleContent")]
pub simple_content: Option<SimpleContent>,
#[yaserde(rename = "complexContent")]
pub complex_content: Option<ComplexContent>,
#[yaserde(rename = "annotation")]
pub annotation: Option<Annotation>,
}
File renamed without changes.
37 changes: 37 additions & 0 deletions xml_schema/src/xsd/element.rs
Original file line number Diff line number Diff line change
@@ -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<String>,
#[yaserde(rename = "ref", attribute)]
pub refers: Option<String>,
#[yaserde(rename = "minOccurs", attribute)]
pub min_occurences: Option<u64>,
#[yaserde(rename = "maxOccurs", attribute)]
pub max_occurences: Option<MaxOccurences>,
#[yaserde(rename = "complexType")]
pub complex_type: Option<ComplexType>,
#[yaserde(rename = "simpleType")]
pub simple_type: Option<SimpleType>,
#[yaserde(rename = "annotation")]
pub annotation: Option<Annotation>,
}

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())
}
})
}
}
18 changes: 18 additions & 0 deletions xml_schema/src/xsd/extension.rs
Original file line number Diff line number Diff line change
@@ -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<Attribute>,
#[yaserde(rename = "sequence")]
pub sequences: Vec<Sequence>,
#[yaserde(rename = "group")]
pub group: Option<Group>,
}
12 changes: 12 additions & 0 deletions xml_schema/src/xsd/group.rs
Original file line number Diff line number Diff line change
@@ -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<String>,
#[yaserde(attribute, rename = "ref")]
pub reference: Option<String>,
#[yaserde()]
pub sequence: Option<Sequence>,
}
File renamed without changes.
6 changes: 6 additions & 0 deletions xml_schema/src/xsd/list.rs
Original file line number Diff line number Diff line change
@@ -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,
}
File renamed without changes.
96 changes: 96 additions & 0 deletions xml_schema/src/xsd/mod.rs
Original file line number Diff line number Diff line change
@@ -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<String, String>,
) -> Result<Self, String> {
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<String, String>,
) -> Result<Self, String> {
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)
}
}
File renamed without changes.
6 changes: 6 additions & 0 deletions xml_schema/src/xsd/restriction.rs
Original file line number Diff line number Diff line change
@@ -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<String>,
}
32 changes: 32 additions & 0 deletions xml_schema/src/xsd/schema.rs
Original file line number Diff line number Diff line change
@@ -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<String>,
#[yaserde(rename = "elementFormDefault", attribute)]
pub element_form_default: Option<qualification::Qualification>,
#[yaserde(rename = "attributeFormDefault", attribute)]
pub attribute_form_default: Option<qualification::Qualification>,
#[yaserde(rename = "import")]
pub imports: Vec<import::Import>,
#[yaserde(rename = "element")]
pub elements: Vec<element::Element>,
#[yaserde(rename = "simpleType")]
pub simple_type: Vec<simple_type::SimpleType>,
#[yaserde(rename = "complexType")]
pub complex_type: Vec<complex_type::ComplexType>,
#[yaserde(rename = "attribute")]
pub attributes: Vec<attribute::Attribute>,
#[yaserde(rename = "attributeGroup")]
pub attribute_group: Vec<attribute_group::AttributeGroup>,
#[yaserde(rename = "group")]
pub group: Vec<group::Group>,
}
8 changes: 8 additions & 0 deletions xml_schema/src/xsd/sequence.rs
Original file line number Diff line number Diff line change
@@ -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<Element>,
}
8 changes: 8 additions & 0 deletions xml_schema/src/xsd/simple_content.rs
Original file line number Diff line number Diff line change
@@ -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,
}
11 changes: 11 additions & 0 deletions xml_schema/src/xsd/simple_type.rs
Original file line number Diff line number Diff line change
@@ -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<Restriction>,
pub list: Option<List>,
pub union: Option<Union>,
}
File renamed without changes.
File renamed without changes.
1 change: 1 addition & 0 deletions xml_schema_derive/Cargo.toml
Original file line number Diff line number Diff line change
@@ -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"
7 changes: 4 additions & 3 deletions xml_schema_derive/src/expander.rs
Original file line number Diff line number Diff line change
@@ -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<TokenStream, String> {
let _ = simple_logger::init_with_level(attributes.log_level());
log::info!("{:?}", attributes);
@@ -10,11 +12,10 @@ pub fn expand_derive(attributes: &XmlSchemaAttributes) -> Result<TokenStream, St

let xsd = Xsd::new_from_file(
attributes.module_name(),
vis,
&attributes.source,
&attributes.module_namespace_mappings(),
)?;
let generated = xsd.implement(&attributes.target_prefix);
let generated = implement_xsd(&xsd, vis, &attributes.target_prefix);

if let Some(store_generated_code) = &attributes.store_generated_code {
std::fs::write(store_generated_code, generated.to_string()).map_err(|e| e.to_string())?;
2 changes: 1 addition & 1 deletion xml_schema_derive/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
extern crate proc_macro;
#[macro_use]
extern crate quote;
#[macro_use]

extern crate yaserde_derive;

use crate::attribute::XmlSchemaAttributes;
21 changes: 2 additions & 19 deletions xml_schema_derive/src/xsd/annotation.rs
Original file line number Diff line number Diff line change
@@ -1,24 +1,7 @@
use crate::xsd::{attribute::Attribute, Implementation, XsdContext};
use crate::xsd::{Implementation, XsdContext};
use proc_macro2::TokenStream;

#[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<String>,
#[yaserde(rename = "attribute")]
pub attributes: Vec<Attribute>,
#[yaserde(
rename = "documentation"
prefix = "xs",
namespace = "xs: http://www.w3.org/2001/XMLSchema"
)]
pub documentation: Vec<String>,
}
use xml_schema::Annotation;

impl Implementation for Annotation {
fn implement(
38 changes: 3 additions & 35 deletions xml_schema_derive/src/xsd/attribute.rs
Original file line number Diff line number Diff line change
@@ -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<String>,
#[yaserde(rename = "type", attribute)]
pub kind: Option<String>,
// #[yaserde(attribute)]
// pub default: Option<String>,
// #[yaserde(attribute)]
// pub fixed: Option<String>,
#[yaserde(rename = "use", attribute)]
pub required: Required,
#[yaserde(rename = "ref", attribute)]
pub reference: Option<String>,
#[yaserde(rename = "simpleType")]
pub simple_type: Option<SimpleType>,
}

#[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),
};

18 changes: 5 additions & 13 deletions xml_schema_derive/src/xsd/complex_content.rs
Original file line number Diff line number Diff line change
@@ -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<Extension>,
}
use xml_schema::{ComplexContent, XsdContext};

impl ComplexContent {
pub fn get_field_implementation(
&self,
context: &XsdContext,
prefix: &Option<String>,
) -> TokenStream {
impl Implementation for ComplexContent {
fn get_field_implementation(&self, prefix: &Option<String>, context: &XsdContext) -> TokenStream {
self
.extension
.as_ref()
.unwrap()
.get_field_implementation(context, prefix)
.get_field_implementation(prefix, context)
}
}
43 changes: 8 additions & 35 deletions xml_schema_derive/src/xsd/complex_type.rs
Original file line number Diff line number Diff line change
@@ -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<Attribute>,
pub sequence: Option<Sequence>,
#[yaserde(rename = "simpleContent")]
pub simple_content: Option<SimpleContent>,
#[yaserde(rename = "complexContent")]
pub complex_content: Option<ComplexContent>,
#[yaserde(rename = "annotation")]
pub annotation: Option<Annotation>,
}
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<String>,
) -> TokenStream {
fn get_field_implementation(&self, prefix: &Option<String>, 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);
}
56 changes: 10 additions & 46 deletions xml_schema_derive/src/xsd/element.rs
Original file line number Diff line number Diff line change
@@ -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<String>,
#[yaserde(rename = "ref", attribute)]
pub refers: Option<String>,
#[yaserde(rename = "minOccurs", attribute)]
pub min_occurences: Option<u64>,
#[yaserde(rename = "maxOccurs", attribute)]
pub max_occurences: Option<MaxOccurences>,
#[yaserde(rename = "complexType")]
pub complex_type: Option<ComplexType>,
#[yaserde(rename = "simpleType")]
pub simple_type: Option<SimpleType>,
#[yaserde(rename = "annotation")]
pub annotation: Option<Annotation>,
}
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<String>,
@@ -98,11 +74,7 @@ impl Element {
self.implement(namespace_definition, prefix, context)
}

pub fn get_field_implementation(
&self,
context: &XsdContext,
prefix: &Option<String>,
) -> TokenStream {
fn get_field_implementation(&self, prefix: &Option<String>, 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,23 +153,15 @@ 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)]
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#"<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"></xs:schema>"#)
.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 > ,"#
34 changes: 5 additions & 29 deletions xml_schema_derive/src/xsd/extension.rs
Original file line number Diff line number Diff line change
@@ -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<Attribute>,
#[yaserde(rename = "sequence")]
pub sequences: Vec<Sequence>,
#[yaserde(rename = "group")]
pub group: Option<Group>,
}
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<String>,
) -> TokenStream {
fn get_field_implementation(&self, prefix: &Option<String>, 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(),
27 changes: 5 additions & 22 deletions xml_schema_derive/src/xsd/group.rs
Original file line number Diff line number Diff line change
@@ -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<String>,
#[yaserde(attribute, rename = "ref")]
pub reference: Option<String>,
#[yaserde()]
pub sequence: Option<Sequence>,
}
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<String>,
) -> TokenStream {
fn get_type_implementation(&self, _prefix: &Option<String>, context: &XsdContext) -> TokenStream {
if let Some(reference) = &self.reference {
RustTypesMapping::get(context, reference)
} else {
@@ -101,7 +84,7 @@ pub struct Groupthing { \
XsdContext::new(r#"<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"></xs:schema>"#)
.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");
}
7 changes: 1 addition & 6 deletions xml_schema_derive/src/xsd/list.rs
Original file line number Diff line number Diff line change
@@ -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(
120 changes: 48 additions & 72 deletions xml_schema_derive/src/xsd/mod.rs
Original file line number Diff line number Diff line change
@@ -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<String, String>,
) -> Result<Self, String> {
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<String>,
_context: &XsdContext,
) -> TokenStream {
unimplemented!()
}

pub fn new_from_file(
name: String,
vis: Visibility,
source: &str,
module_namespace_mappings: &BTreeMap<String, String>,
) -> Result<Self, String> {
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<String>,
_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<String>,
_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<String>,
_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<String>) -> TokenStream {
let schema = self
.schema
.implement(&TokenStream::new(), target_prefix, &self.context);
pub fn implement_xsd(
xsd: &Xsd,
visibility: Visibility,
target_prefix: &Option<String>,
) -> 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::*;
}
}
16 changes: 4 additions & 12 deletions xml_schema_derive/src/xsd/restriction.rs
Original file line number Diff line number Diff line change
@@ -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<String>,
}
use crate::xsd::Implementation;
use xml_schema::Restriction;

impl Restriction {
pub fn get_type_implementation(
&self,
context: &XsdContext,
_prefix: &Option<String>,
) -> TokenStream {
impl Implementation for Restriction {
fn get_type_implementation(&self, _prefix: &Option<String>, context: &XsdContext) -> TokenStream {
if let Some(base) = &self.base {
RustTypesMapping::get(context, base)
} else {
34 changes: 2 additions & 32 deletions xml_schema_derive/src/xsd/schema.rs
Original file line number Diff line number Diff line change
@@ -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<String>,
#[yaserde(rename = "elementFormDefault", attribute)]
pub element_form_default: Option<qualification::Qualification>,
#[yaserde(rename = "attributeFormDefault", attribute)]
pub attribute_form_default: Option<qualification::Qualification>,
#[yaserde(rename = "import")]
pub imports: Vec<import::Import>,
#[yaserde(rename = "element")]
pub elements: Vec<element::Element>,
#[yaserde(rename = "simpleType")]
pub simple_type: Vec<simple_type::SimpleType>,
#[yaserde(rename = "complexType")]
pub complex_type: Vec<complex_type::ComplexType>,
#[yaserde(rename = "attribute")]
pub attributes: Vec<attribute::Attribute>,
#[yaserde(rename = "attributeGroup")]
pub attribute_group: Vec<attribute_group::AttributeGroup>,
#[yaserde(rename = "group")]
pub group: Vec<group::Group>,
}
use xml_schema::Schema;

impl Implementation for Schema {
fn implement(
25 changes: 7 additions & 18 deletions xml_schema_derive/src/xsd/sequence.rs
Original file line number Diff line number Diff line change
@@ -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<Element>,
}
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<String>,
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<String>,
) -> TokenStream {
fn get_field_implementation(&self, prefix: &Option<String>, context: &XsdContext) -> TokenStream {
self
.elements
.iter()
.map(|element| element.get_field_implementation(context, prefix))
.map(|element| element.get_field_implementation(prefix, context))
.collect()
}
}
19 changes: 4 additions & 15 deletions xml_schema_derive/src/xsd/simple_content.rs
Original file line number Diff line number Diff line change
@@ -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<String>,
) -> TokenStream {
self.extension.get_field_implementation(context, prefix)
fn get_field_implementation(&self, prefix: &Option<String>, context: &XsdContext) -> TokenStream {
self.extension.get_field_implementation(prefix, context)
}
}
22 changes: 4 additions & 18 deletions xml_schema_derive/src/xsd/simple_type.rs
Original file line number Diff line number Diff line change
@@ -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<Restriction>,
pub list: Option<List>,
pub union: Option<Union>,
}
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<String>,
) -> TokenStream {
fn get_type_implementation(&self, prefix: &Option<String>, 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);
}
Original file line number Diff line number Diff line change
@@ -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#"
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -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#"<?xml version="1.0" encoding="UTF-8" ?>
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -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#"
File renamed without changes.
File renamed without changes.