diff --git a/xsd-parser/src/parser/all.rs b/xsd-parser/src/parser/all.rs new file mode 100644 index 0000000..dbbd42b --- /dev/null +++ b/xsd-parser/src/parser/all.rs @@ -0,0 +1,39 @@ +use std::cell::RefCell; + +use roxmltree::Node; + +use crate::parser::node_parser::parse_node; +use crate::parser::types::{RsEntity, Struct, StructField, TypeModifier}; +use crate::parser::utils::{enum_to_field, get_documentation, get_parent_name}; +use crate::parser::xsd_elements::{ElementType, XsdNode}; + +pub fn parse_all(node: &Node, parent: &Node) -> RsEntity { + let name = get_parent_name(node); + RsEntity::Struct(Struct { + name: name.into(), + comment: get_documentation(parent), + subtypes: vec![], + fields: RefCell::new(elements_to_fields(node, name)), + ..Default::default() + }) +} + +fn elements_to_fields(choice: &Node, parent_name: &str) -> Vec { + choice + .children() + .filter(|n| n.is_element() && n.xsd_type() != ElementType::Annotation) + .map(|n| match parse_node(&n, choice) { + RsEntity::StructField(mut sf) => { + if sf.type_name.ends_with(parent_name) { + sf.type_modifiers.push(TypeModifier::Recursive) + } + sf + } + RsEntity::Enum(mut en) => { + en.name = format!("{}Choice", parent_name); + enum_to_field(en) + } + _ => unreachable!("\nError: {:?}\n{:?}", n, parse_node(&n, choice)), + }) + .collect() +} diff --git a/xsd-parser/src/parser/element.rs b/xsd-parser/src/parser/element.rs index 69794ab..df84031 100644 --- a/xsd-parser/src/parser/element.rs +++ b/xsd-parser/src/parser/element.rs @@ -14,6 +14,7 @@ const SUPPORTED_CONTENT_TYPES: [ElementType; 2] = pub fn parse_element(node: &Node, parent: &Node) -> RsEntity { match parent.xsd_type() { ElementType::Schema => parse_global_element(node), + ElementType::All => parse_field_of_sequence(node, parent), ElementType::Sequence => parse_field_of_sequence(node, parent), ElementType::Choice => parse_case_of_choice(node), _ => element_default(node), diff --git a/xsd-parser/src/parser/mod.rs b/xsd-parser/src/parser/mod.rs index e419218..0138dc3 100644 --- a/xsd-parser/src/parser/mod.rs +++ b/xsd-parser/src/parser/mod.rs @@ -1,3 +1,4 @@ +mod all; mod any; mod any_attribute; mod attribute; diff --git a/xsd-parser/src/parser/node_parser.rs b/xsd-parser/src/parser/node_parser.rs index f1ae89c..eab87b2 100644 --- a/xsd-parser/src/parser/node_parser.rs +++ b/xsd-parser/src/parser/node_parser.rs @@ -1,5 +1,6 @@ use roxmltree::Node; +use crate::parser::all::parse_all; use crate::parser::any::parse_any; use crate::parser::any_attribute::parse_any_attribute; use crate::parser::attribute::parse_attribute; @@ -23,6 +24,7 @@ pub fn parse_node(node: &Node, parent: &Node) -> RsEntity { use ElementType::*; match node.xsd_type() { + All => parse_all(node, parent), Any => parse_any(node), AnyAttribute => parse_any_attribute(node), Attribute => parse_attribute(node, parent), diff --git a/xsd-parser/tests/all/example.xml b/xsd-parser/tests/all/example.xml new file mode 100644 index 0000000..8b7cee2 --- /dev/null +++ b/xsd-parser/tests/all/example.xml @@ -0,0 +1,8 @@ + + + 111 + 222 + 333 + 444 + 555 + diff --git a/xsd-parser/tests/all/expected.rs b/xsd-parser/tests/all/expected.rs new file mode 100644 index 0000000..4534a17 --- /dev/null +++ b/xsd-parser/tests/all/expected.rs @@ -0,0 +1,19 @@ +#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)] +#[yaserde(prefix = "tns", namespace = "tns: http://example.com")] +pub struct FooType { + #[yaserde(prefix = "tns", rename = "Once")] + pub once: i32, + + #[yaserde(prefix = "tns", rename = "Optional")] + pub optional: Option, + + #[yaserde(prefix = "tns", rename = "OnceSpecify")] + pub once_specify: i32, + + #[yaserde(prefix = "tns", rename = "TwiceOrMore")] + pub twice_or_more: Vec, +} + +impl Validate for FooType {} + +// pub type Foo = FooType; diff --git a/xsd-parser/tests/all/input.xsd b/xsd-parser/tests/all/input.xsd new file mode 100644 index 0000000..287b105 --- /dev/null +++ b/xsd-parser/tests/all/input.xsd @@ -0,0 +1,16 @@ + + + + + + + + + + + + + diff --git a/xsd-parser/tests/all/mod.rs b/xsd-parser/tests/all/mod.rs new file mode 100644 index 0000000..dd87aa9 --- /dev/null +++ b/xsd-parser/tests/all/mod.rs @@ -0,0 +1,35 @@ +use super::utils; + +#[test] +fn deserialization_works() { + mod expected { + use xsd_parser::generator::validator::Validate; + use yaserde_derive::{YaDeserialize, YaSerialize}; + + include!("expected.rs"); + } + + let ser = include_str!("example.xml"); + + let de: expected::FooType = yaserde::de::from_str(ser).unwrap(); + + assert_eq!( + de, + expected::FooType { + once: 222, + optional: None, + once_specify: 444, + twice_or_more: vec![111, 333, 555] + } + ); +} + +#[test] +fn generator_does_not_panic() { + println!("{}", utils::generate(include_str!("input.xsd"))) +} + +#[test] +fn generator_output_has_correct_ast() { + utils::ast_test(include_str!("input.xsd"), include_str!("expected.rs")); +} diff --git a/xsd-parser/tests/mod.rs b/xsd-parser/tests/mod.rs index 6daeaa9..0b33f84 100644 --- a/xsd-parser/tests/mod.rs +++ b/xsd-parser/tests/mod.rs @@ -1,5 +1,6 @@ #[macro_use] mod utils; +mod all; mod any; mod choice; mod complex_type;