diff --git a/xml-schema/src/parser_generator.rs b/xml-schema/src/parser_generator.rs index ebed18a..bb5fba9 100644 --- a/xml-schema/src/parser_generator.rs +++ b/xml-schema/src/parser_generator.rs @@ -38,6 +38,8 @@ pub struct ParserGenerator<'ast, 'input: 'ast> { primitive_types: HashMap<&'static str, RichType<'input, Type<'input>>>, simple_restrictions: HashMap<(FullName<'input>, Facets<'input>), String>, renames: HashMap, + type_names: HashMap, // (mod_name, type_name) + simple_type_names: HashMap, // (mod_name, type_name) self_gen: bool, } @@ -67,6 +69,7 @@ impl<'ast, 'input: 'ast> ParserGenerator<'ast, 'input> { ParserGenerator { processors, renames, module_names, primitive_types, self_gen, simple_restrictions: HashMap::new(), + type_names: HashMap::new(), simple_type_names: HashMap::new(), } } @@ -86,14 +89,11 @@ impl<'ast, 'input: 'ast> ParserGenerator<'ast, 'input> { scope.raw("pub use std::collections::HashMap;"); scope.raw("pub use std::marker::PhantomData;"); self.create_modules(&mut scope); - self.gen_choices(&mut scope); - self.gen_simple_types(&mut scope); - self.gen_lists(&mut scope); - self.gen_unions(&mut scope); + self.allocate_names(); + self.gen_anonymous_types(&mut scope); self.gen_sequences(&mut scope); self.gen_elements(&mut scope); self.gen_inline_elements(&mut scope); - self.gen_groups(&mut scope); scope } @@ -113,26 +113,154 @@ impl<'ast, 'input: 'ast> ParserGenerator<'ast, 'input> { } } - fn gen_choices(&self, scope: &mut cg::Scope) { - let module = scope.new_module("enums"); - module.vis("pub"); - module.scope().raw("#[allow(unused_imports)]\nuse super::*;"); + fn allocate_names(&mut self) { let mut name_gen = NameGenerator::new(); for proc in &self.processors { - let mut choices: Vec<_> = proc.choices.iter().collect(); - choices.sort_by_key(|&(t,names)| (t, names.iter().collect::>())); - for (ref choice, ref names) in choices { - for name in names.iter() { - let enum_name = escape_keyword(&name.to_camel_case()); - let enum_name = name_gen.gen_name(enum_name); - self.gen_choice(module.scope(), &enum_name, choice, &Documentation::new()); + // Complex types + let mut types: Vec<_> = proc.anonymous_types.iter().collect(); + types.sort_by_key(|&(id,_type)| id); + for (&id, ref type_) in types { + let name = name_from_hint(&type_.name_hint).unwrap(); // TODO: handle None + let (mod_name, type_name) = match type_.type_ { + Type::Choice(_) => ("choices".to_string(), name.to_camel_case()), + _ => unimplemented!("{:?}", type_.type_), + }; + let type_name = escape_keyword(&type_name); + let type_name = name_gen.gen_name(type_name); + let type_name = self.renames.get(&type_name).unwrap_or(&type_name); + self.type_names.insert(id, (mod_name, type_name.clone())); + } + + // Simple types + let mut types: Vec<_> = proc.anonymous_simple_types.iter().collect(); + types.sort_by_key(|&(id,_type)| id); + for (&id, ref type_) in types { + let (mod_name, type_name) = match type_.type_ { + SimpleType::Alias(name) => { + if name.namespace() == Some(&SCHEMA_URI) { + let mut res = None; + for (prim_name, prim_type_name) in PRIMITIVE_TYPES { + if *prim_name == name.local_name() { + res = Some(("support".to_string(), prim_type_name.to_string())) + } + } + res.expect(&format!("Unknown primitive type in schema {}: {:?}", SCHEMA_URI, name.local_name())) + } + else { + let type_mod_name = self.get_module_name(name); + let type_mod_name = escape_keyword(&type_mod_name.to_snake_case()); + let type_name = escape_keyword(&name.local_name().to_camel_case()); + (type_mod_name, type_name) + } + }, + SimpleType::Restriction(base_name, facets) => { + let name = match &facets.enumeration { + Some(items) => { + if items.len() == 1 { + format!("{}", items[0]) + } + else { + format!("enumeration_{}", items.join("_")) + } + }, + None => format!("Restrict_{}", base_name.local_name()), + }; + ("simple_restrictions".to_string(), name) + } + SimpleType::Primitive(field_name, type_name) => { + ("support".to_string(), type_name.to_string()) + }, + SimpleType::Union(type_names) => { + let name = name_from_hint(&type_.name_hint).unwrap(); + ("unions".to_string(), name) + }, + SimpleType::List(name) => { + let name = name_from_hint(&type_.name_hint).unwrap(); + ("lists".to_string(), name) + }, + SimpleType::Empty => { + ("fixme_empty".to_string(), "FixmeEmpty".to_string()) // FIXME + }, + }; + let type_name = escape_keyword(&type_name); + let type_name = name_gen.gen_name(type_name); + let type_name = self.renames.get(&type_name).unwrap_or(&type_name); + self.simple_type_names.insert(id, (mod_name, type_name.clone())); + } + } + } + + fn gen_anonymous_types(&self, scope: &mut cg::Scope) { + let choices_module = scope.new_module("choices"); + choices_module.vis("pub"); + choices_module.scope().raw("#[allow(unused_imports)]\nuse super::*;"); + + let unions_module = scope.new_module("unions"); + unions_module.vis("pub"); + unions_module.scope().raw("#[allow(unused_imports)]\nuse super::*;"); + + let simple_restrictions_module = scope.new_module("simple_restrictions"); + simple_restrictions_module.vis("pub"); + simple_restrictions_module.scope().raw("#[allow(unused_imports)]\nuse super::*;"); + + let lists_module = scope.new_module("lists"); + lists_module.vis("pub"); + lists_module.scope().raw("#[allow(unused_imports)]\nuse super::*;"); + + for proc in &self.processors { + // Complex types + let mut types: Vec<_> = proc.anonymous_types.iter().collect(); + types.sort_by_key(|&(id,_type)| id); + for (id, ref type_) in types { + let (type_mod_name, type_name) = self.type_names.get(id).unwrap(); + match type_.type_ { + Type::Choice(items) => { + let items = items.iter().map(|id| proc.anonymous_types.get(id).unwrap()).collect(); + self.gen_choice(choices_module.scope(), &type_name, &items, &Documentation::new()); + }, + Type::Sequence(items) => { + let items = items.iter().map(|id| proc.anonymous_types.get(id).unwrap()).collect(); + self.gen_choice(choices_module.scope(), &type_name, &items, &Documentation::new()); + }, + _ => panic!("wat"), + } + } + + // Simple types + let mut types: Vec<_> = proc.anonymous_simple_types.iter().collect(); + types.sort_by_key(|&(id,_type)| id); + for (id, ref type_) in types { + let type_name = self.simple_type_names.get(id).unwrap(); + match type_.type_ { + SimpleType::Alias(name) => {}, // nothing to generate + SimpleType::Restriction(ref base_name, ref facets) => { + let base_mod_name = self.module_names.get(&base_name.namespace()).unwrap(); + let base_type_name = escape_keyword(base_name.local_name()); + self.gen_simple_restriction(simple_restrictions_module.scope(), type_name.1, (base_mod_name, &base_type_name), facets, type_.doc); + } + SimpleType::Primitive(field_name, type_name) => {}, // Nothing to generate + SimpleType::Union(variants) => { + let mut name_gen = NameGenerator::new(); + let variants: Vec<_> = variants.iter().map(|id| { + let variant_name = name_from_hint(&proc.anonymous_simple_types.get(id).unwrap().name_hint).unwrap_or("variant".to_string()); + let variant_name = escape_keyword(&variant_name.to_camel_case()); + let variant_name = name_gen.gen_name(variant_name); + (variant_name, self.simple_type_names.get(id).unwrap()) + }).collect(); + self.gen_union(unions_module.scope(), &type_name.1, &variants, &type_.doc); + }, + SimpleType::List(item_type_id) => { + let (item_type_mod_name, item_type_name) = self.simple_type_names.get(&item_type_id).unwrap(); + self.gen_list(unions_module.scope(), type_name.1, (&item_type_mod_name, &item_type_name), &type_.doc); + }, + SimpleType::Empty => {}, // Nothing to generate } } } } - fn gen_choice(&self, scope: &mut cg::Scope, enum_name: &String, items: &Vec>>, doc: &Documentation<'input>) { + + fn gen_choice(&self, scope: &mut cg::Scope, enum_name: &String, items: &Vec<&RichType<'input, Type<'input>>>, doc: &Documentation<'input>) { let mut impl_code = Vec::new(); - let enum_name = self.renames.get(enum_name).unwrap_or(enum_name); impl_code.push(format!("impl_enum!({},", enum_name)); { let enum_ = scope.new_enum(&enum_name).vis("pub").derive("Debug").derive("PartialEq").generic("'input"); @@ -198,100 +326,29 @@ impl<'ast, 'input: 'ast> ParserGenerator<'ast, 'input> { impl_code.push(");".to_string()); scope.raw(&impl_code.join("\n")); } - fn gen_unions(&self, scope: &mut cg::Scope) { - let module = scope.new_module("unions"); - module.vis("pub"); - module.scope().raw("#[allow(unused_imports)]\nuse super::*;"); - let mut name_gen = NameGenerator::new(); - for proc in &self.processors { - let mut unions: Vec<_> = proc.unions.iter().collect(); - unions.sort_by_key(|&(items, names)| (items, names.iter().collect::>())); - for (ref items, ref names) in unions { - for name in names.iter() { - let enum_name = escape_keyword(&name.to_camel_case()); - let enum_name = name_gen.gen_name(enum_name); - let mut impl_code = Vec::new(); - impl_code.push(format!("impl_union!({}, {{", enum_name)); - { - let enum_ = module.new_enum(&enum_name).vis("pub").derive("Debug").derive("PartialEq").generic("'input"); - for item in items.iter() { - let RichType { name_hint, attrs, type_, doc } = item; - let variant_name = name_from_hint(name_hint).unwrap().to_camel_case(); - if let Some((type_mod_name, type_name)) = self.get_simple_type_name(type_) { - enum_.new_variant(&variant_name).tuple(&format!("{}::{}<'input>", type_mod_name, type_name)); - impl_code.push(format!(" impl_union_variant!({}),", variant_name)); - } - } - } - impl_code.push(format!("}});")); - module.scope().raw(&impl_code.join("\n")); - } + fn gen_union(&self, module: &mut cg::Scope, enum_name: &String, items: &Vec<(String, &(String, String))>, doc: &Documentation<'input>) { + let mut impl_code = Vec::new(); + impl_code.push(format!("impl_union!({}, {{", enum_name)); + { + let enum_ = module.new_enum(&enum_name).vis("pub").derive("Debug").derive("PartialEq").generic("'input"); + for (variant_name, (variant_type_mod_name, variant_type_name)) in items.iter() { + enum_.new_variant(&variant_name).tuple(&format!("{}::{}<'input>", variant_type_mod_name, variant_type_name)); + impl_code.push(format!(" impl_union_variant!({}),", variant_name)); } } + impl_code.push(format!("}});")); + module.raw(&impl_code.join("\n")); } - fn gen_lists(&self, scope: &mut cg::Scope) { - let module = scope.new_module("lists"); - module.vis("pub"); - module.scope().raw("#[allow(unused_imports)]\nuse super::*;"); - let mut name_gen = NameGenerator::new(); - for proc in &self.processors { - let mut lists: Vec<_> = proc.lists.iter().collect(); - lists.sort_by_key(|&(item_type, names)| (item_type, names.iter().collect::>())); - for (ref item_type, ref names) in lists { - for name in names.iter() { - let name = escape_keyword(&name.to_camel_case()); - let struct_name = name_gen.gen_name(name); - if let Some((type_mod_name, type_name)) = self.get_simple_type_name(&item_type.type_) { - { - let struct_ = module.new_struct(&struct_name).vis("pub").derive("Debug").derive("PartialEq").generic("'input"); - struct_.tuple_field(&format!("pub Vec<{}::{}<'input>>", type_mod_name, type_name)); - } - module.scope().raw(&format!("impl_list!({}, {}::{});", struct_name, type_mod_name, type_name)); - } - } - } - } - } + fn gen_list(&self, module: &mut cg::Scope, struct_name: String, item_type_name: (&str, &str), doc: &Documentation<'input>) { + let (type_mod_name, type_name) = item_type_name; + let struct_ = module.new_struct(&struct_name).vis("pub").derive("Debug").derive("PartialEq").generic("'input"); + struct_.tuple_field(&format!("pub Vec<{}::{}<'input>>", type_mod_name, type_name)); - fn get_simple_type_name(&self, ty: &SimpleType<'input>) -> Option<(String, String)> { - let (type_mod_name, type_name) = match ty { - SimpleType::Alias(name) => { - if name.namespace() == Some(&SCHEMA_URI) { - for (prim_name, prim_type_name) in PRIMITIVE_TYPES { - if *prim_name == name.local_name() { - return Some(("support".to_string(), prim_type_name.to_string())); - } - } - } - let type_mod_name = self.get_module_name(*name); - let type_mod_name = escape_keyword(&type_mod_name.to_snake_case()); - let type_name = escape_keyword(&name.local_name().to_camel_case()); - (type_mod_name, type_name) - }, - SimpleType::Restriction(name, facets) => { - ("restrictions".to_string(), self.simple_restrictions.get(&(name.clone(), facets.clone())).unwrap().to_string()) - } - SimpleType::Primitive(field_name, type_name) => { - ("support".to_string(), type_name.to_string()) - }, - SimpleType::Union(type_name) => { - let type_name = escape_keyword(&type_name.to_camel_case()); - ("unions".to_string(), type_name) - }, - SimpleType::List(name) => { - let type_name = escape_keyword(&name.to_camel_case()); - ("lists".to_string(), type_name) - }, - SimpleType::Empty => { - return None - }, - }; - Some((type_mod_name, type_name)) + module.raw(&format!("impl_list!({}, {}::{});", struct_name, type_mod_name, type_name)); } - fn gen_simple_types(&mut self, scope: &mut cg::Scope) { - self.gen_simple_restrictions(scope); + /*fn gen_simple_types(&mut self, scope: &mut cg::Scope) { let mut name_gen = NameGenerator::new(); for proc in &self.processors { let mut types: Vec<_> = proc.simple_types.iter().collect(); @@ -314,65 +371,36 @@ impl<'ast, 'input: 'ast> ParserGenerator<'ast, 'input> { } } } - } - - fn gen_simple_restrictions(&mut self, scope: &mut cg::Scope) { - let mut name_gen = NameGenerator::new(); - let module = scope.new_module("restrictions"); - module.vis("pub"); - module.scope().raw("#[allow(unused_imports)]\nuse super::*;"); + }*/ - for proc in &self.processors { - let mut simple_restrictions: Vec<_> = proc.simple_restrictions.iter().collect(); - - simple_restrictions.sort(); - for (base_name, facets) in simple_restrictions { - if self.simple_restrictions.get(&(*base_name, facets.clone())).is_some() { - continue; - } - let name = match &facets.enumeration { - Some(items) => { - if items.len() == 1 { - format!("{}", items[0]) - } - else { - format!("enumeration_{}", items.join("_")) - } - }, - None => format!("Restrict_{}", base_name.local_name()), - }; - let name = name.to_camel_case(); - let name = name_gen.gen_name(name.clone()); - self.simple_restrictions.insert((base_name.clone(), facets.clone()), name.clone()); - let (base_mod_name, base_type_name) = self.get_simple_type_name(&SimpleType::Alias(*base_name)).unwrap(); // TODO - module.scope().raw(&format!("#[derive(Debug, PartialEq)] pub struct {}<'input>(pub {}::{}<'input>);", name, base_mod_name, base_type_name)); - let mut s = Vec::new(); - let f = &mut |n: &Option<_>| { - match n.as_ref() { - None => "None".to_string(), - Some(f) => format!("Some(BigFloatNotNaN::from_str(\"{}\").unwrap())", f), - } - }; - s.push(format!("min_exclusive: {},", f(&facets.min_exclusive))); - s.push(format!("min_inclusive: {},", f(&facets.min_inclusive))); - s.push(format!("max_exclusive: {},", f(&facets.max_exclusive))); - s.push(format!("max_inclusive: {},", f(&facets.max_inclusive))); - s.push(format!("total_digits: {:?},", facets.total_digits)); - s.push(format!("fraction_digits: {:?},", facets.fraction_digits)); - s.push(format!("length: {:?},", facets.length)); - s.push(format!("min_length: {:?},", facets.min_length)); - s.push(format!("max_length: {:?},", facets.max_length)); - match &facets.enumeration { - Some(items) => s.push(format!("enumeration: Some(vec![{}]),", items.iter().map(|i| format!("{:?}", i)).collect::>().join(", "))), - None => s.push("enumeration: None,".to_string()), - } - s.push(format!("white_space: {:?},", facets.white_space)); - s.push(format!("pattern: {:?},", facets.pattern)); - s.push(format!("assertion: {:?},", facets.assertion)); - s.push(format!("explicit_timezone: {:?},", facets.explicit_timezone)); - module.scope().raw(&format!("impl_simpletype_restriction!({}, Facets {{\n {}\n}});", name, s.join("\n "))); + fn gen_simple_restriction(&mut self, module: &mut cg::Scope, struct_name: String, base_name: (&str, &str), facets: &Facets<'input>, doc: Documentation<'input>) { + let (base_mod_name, base_type_name) = base_name; + module.raw(&format!("#[derive(Debug, PartialEq)] pub struct {}<'input>(pub {}::{}<'input>);", struct_name, base_mod_name, base_type_name)); + let mut s = Vec::new(); + let f = &mut |n: &Option<_>| { + match n.as_ref() { + None => "None".to_string(), + Some(f) => format!("Some(BigFloatNotNaN::from_str(\"{}\").unwrap())", f), } + }; + s.push(format!("min_exclusive: {},", f(&facets.min_exclusive))); + s.push(format!("min_inclusive: {},", f(&facets.min_inclusive))); + s.push(format!("max_exclusive: {},", f(&facets.max_exclusive))); + s.push(format!("max_inclusive: {},", f(&facets.max_inclusive))); + s.push(format!("total_digits: {:?},", facets.total_digits)); + s.push(format!("fraction_digits: {:?},", facets.fraction_digits)); + s.push(format!("length: {:?},", facets.length)); + s.push(format!("min_length: {:?},", facets.min_length)); + s.push(format!("max_length: {:?},", facets.max_length)); + match &facets.enumeration { + Some(items) => s.push(format!("enumeration: Some(vec![{}]),", items.iter().map(|i| format!("{:?}", i)).collect::>().join(", "))), + None => s.push("enumeration: None,".to_string()), } + s.push(format!("white_space: {:?},", facets.white_space)); + s.push(format!("pattern: {:?},", facets.pattern)); + s.push(format!("assertion: {:?},", facets.assertion)); + s.push(format!("explicit_timezone: {:?},", facets.explicit_timezone)); + module.raw(&format!("impl_simpletype_restriction!({}, Facets {{\n {}\n}});", struct_name, s.join("\n "))); } fn gen_sequences(&mut self, scope: &mut cg::Scope) { @@ -392,28 +420,6 @@ impl<'ast, 'input: 'ast> ParserGenerator<'ast, 'input> { } } - fn gen_groups(&mut self, scope: &mut cg::Scope) { - for proc in &self.processors { - let mut groups: Vec<_> = proc.groups.iter().collect(); - - groups.sort_by_key(|&(n,_)| n); - for (&name, group) in groups { - let mod_name = self.get_module_name(name); - let mut module = scope.get_module_mut(&mod_name).unwrap(); - let struct_name = name.local_name(); - if let Type::InlineChoice(ref items) = group.type_ { - self.gen_choice(module.scope(), &struct_name.to_string().to_camel_case(), items, &group.doc); - } - else if let Type::InlineSequence(ref items) = group.type_ { - self.gen_group_or_sequence(module, struct_name, &items.iter().collect(), &group.doc); - } - else { - self.gen_group_or_sequence(module, struct_name, &vec![group], &group.doc); - } - } - } - } - fn gen_fields(&self, empty_struct: &mut bool, struct_: &mut cg::Struct, impl_code: &mut Vec, doc: &mut Documentation<'input>, name_gen: &mut NameGenerator, type_: &Type<'input>) { let field_writer = &mut |name: String, type_mod_name: String, min_occurs, max_occurs, type_name: String| { *empty_struct = false; @@ -548,9 +554,10 @@ impl<'ast, 'input: 'ast> ParserGenerator<'ast, 'input> { if generated_attrs.contains(attr_name) { continue; } - let default_type = SimpleType::Primitive(SCHEMA_URI, "AnySimpleType"); - let type_ = attr_type.as_ref().unwrap_or(&default_type); - let (type_mod_name, type_name) = self.get_simple_type_name(&type_).unwrap(); + let default_type = ("support".to_string(), "AnySimpleType".to_string()); + let (type_mod_name, type_name) = attr_type + .map(|id| self.simple_type_names.get(&id).unwrap()) + .unwrap_or(&default_type); let use_ = if inherited { *seen_attrs.get(attr_name).unwrap_or(use_) } @@ -627,7 +634,7 @@ impl<'ast, 'input: 'ast> ParserGenerator<'ast, 'input> { if proc.target_namespace != name.namespace() { continue; } - type_ = proc.types.get(name); + type_ = proc.types.get(name).and_then(|id| proc.anonymous_types.get(id)); if type_.is_some() { break; } @@ -664,7 +671,7 @@ impl<'ast, 'input: 'ast> ParserGenerator<'ast, 'input> { Type::Element(min_occurs, max_occurs, name) => { field_writer(name.to_string(), "inline_elements".to_string(), *min_occurs, *max_occurs, name.to_string()); } - Type::Group(min_occurs, max_occurs, name) | + Type::GroupRef(min_occurs, max_occurs, name) | Type::ElementRef(min_occurs, max_occurs, name) => { let field_name = name.local_name(); let mod_name = self.get_module_name(*name); @@ -691,7 +698,7 @@ impl<'ast, 'input: 'ast> ParserGenerator<'ast, 'input> { field_writer("any".to_string(), "support".to_string(), 1, 1, "Any".to_string()) }, Type::Simple(type_) => { - let (type_mod_name, type_name) = self.get_simple_type_name(&type_).unwrap(); + let (type_mod_name, type_name) = self.simple_type_names.get(&type_).unwrap(); field_writer(type_name.clone(), type_mod_name, 1, 1, type_name); } _ => unimplemented!("writing {:?}", type_), @@ -705,12 +712,11 @@ impl<'ast, 'input: 'ast> ParserGenerator<'ast, 'input> { let target_attrs = self.compute_attrs(&target_type.type_, &target_type.attrs); self.extend_attrs(&target_attrs, own_attrs) }, - Type::InlineSequence(_) | - Type::Sequence(_, _, _) | - Type::Element(_, _, _) | - Type::Group(_, _, _) | - Type::ElementRef(_, _, _) | - Type::Choice(_, _, _) | + Type::Sequence(_) | + Type::Element(_) | + Type::GroupRef(_) | + Type::ElementRef(_) | + Type::Choice(_) | Type::Empty | Type::Any => { own_attrs.clone() diff --git a/xml-schema/src/processor.rs b/xml-schema/src/processor.rs index b433294..474424e 100644 --- a/xml-schema/src/processor.rs +++ b/xml-schema/src/processor.rs @@ -1,6 +1,7 @@ use std::fmt::Debug; use std::hash::Hash; use std::collections::{HashMap, HashSet}; +use std::sync::atomic::{AtomicUsize, Ordering}; use xmlparser::Token as XmlToken; use xmlparser::{TextUnescape, XmlSpace}; @@ -12,6 +13,37 @@ use primitives::{QName,NcName,AnyUri,NonNegativeInteger}; pub const SCHEMA_URI: &'static str = "http://www.w3.org/2001/XMLSchema"; +macro_rules! register_rich_type { + ($self:expr, $rich_type:expr) => {{ + let id = TypeId::new(); + $self.anonymous_types.insert(id, $rich_type); + id + }} +} + +macro_rules! register_rich_simple_type { + ($self:expr, $rich_type:expr) => {{ + let id = SimpleTypeId::new(); + $self.anonymous_simple_types.insert(id, $rich_type); + id + }} +} + +macro_rules! many { + ($self:expr, $min_occurs:expr, $max_occurs:expr, $id:expr) => {{ + if $min_occurs != 1 || $max_occurs != 1 { + register_rich_type!($self, RichType::new( + NameHint::new("many"), + Type::Many($min_occurs, $max_occurs, $id), + Documentation::new(), + )) + } + else { + $id + } + }} +} + fn parse_min_occurs(x: &Option) -> usize { match x { None => 1, @@ -61,7 +93,7 @@ pub enum AttrUse { #[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Attrs<'input> { - pub named: Vec<(FullName<'input>, AttrUse, Option>)>, + pub named: Vec<(FullName<'input>, AttrUse, Option)>, pub refs: Vec<(Option>, AttrUse, FullName<'input>)>, pub group_refs: Vec>, pub any_attributes: bool, @@ -79,7 +111,29 @@ impl<'input> Attrs<'input> { } } -#[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord)] +static TYPE_NEXT_ID: AtomicUsize = AtomicUsize::new(0); + +#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)] +pub struct TypeId(usize); + +impl TypeId { + pub fn new() -> TypeId { + TypeId(TYPE_NEXT_ID.fetch_add(1, Ordering::SeqCst)) + } +} + +static SIMPLE_TYPE_NEXT_ID: AtomicUsize = AtomicUsize::new(0); + +#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)] +pub struct SimpleTypeId(usize); + +impl SimpleTypeId { + pub fn new() -> SimpleTypeId { + SimpleTypeId(SIMPLE_TYPE_NEXT_ID.fetch_add(1, Ordering::SeqCst)) + } +} + +#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct RichType<'input, T: Debug + Hash + PartialEq + Eq + PartialOrd + Ord> { pub name_hint: NameHint<'input>, pub attrs: Attrs<'input>, @@ -97,7 +151,6 @@ impl<'input> RichType<'input, Type<'input>> { self } } - impl<'input> RichType<'input, SimpleType<'input>> { pub fn into_complex(self) -> RichType<'input, Type<'input>> { let RichType { name_hint, attrs, type_, doc } = self; @@ -105,20 +158,21 @@ impl<'input> RichType<'input, SimpleType<'input>> { } } -#[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord)] +#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)] pub enum Type<'input> { Any, Empty, Alias(FullName<'input>), - Extension(FullName<'input>, Box>>), - Restriction(FullName<'input>, Box>>), - ElementRef(usize, usize, FullName<'input>), - Element(usize, usize, String), - Group(usize, usize, FullName<'input>), - Choice(usize, usize, String), - InlineChoice(Vec>>), - Sequence(usize, usize, String), - InlineSequence(Vec>>), + AliasId(TypeId), + AliasSimpleId(SimpleTypeId), + Extension(FullName<'input>, TypeId), + Restriction(FullName<'input>, TypeId), + ElementRef(FullName<'input>), + Element(String), + GroupRef(FullName<'input>), + Choice(Vec), + Sequence(Vec), + Many(usize, usize, TypeId), Simple(SimpleType<'input>), } @@ -126,9 +180,10 @@ pub enum Type<'input> { pub enum SimpleType<'input> { Primitive(&'static str, &'static str), Alias(FullName<'input>), + AliasId(SimpleTypeId), Restriction(FullName<'input>, Facets<'input>), - List(String), - Union(String), + List(SimpleTypeId), + Union(Vec), Empty, } @@ -138,11 +193,10 @@ pub struct Processor<'ast, 'input: 'ast> { pub element_form_default_qualified: bool, pub attribute_form_default_qualified: bool, pub elements: HashMap, RichType<'input, Type<'input>>>, - pub types: HashMap, RichType<'input, Type<'input>>>, + pub types: HashMap, TypeId>, pub simple_types: HashMap, (RichType<'input, SimpleType<'input>>, Documentation<'input>)>, - pub choices: HashMap>>, HashSet>, pub sequences: HashMap>>, (HashSet, Documentation<'input>)>, - pub groups: HashMap, RichType<'input, Type<'input>>>, + pub groups: HashMap, TypeId>, pub attribute_groups: HashMap, Attrs<'input>>, pub inline_elements: HashMap<(Option<&'input str>, &'input str, Attrs<'input>, Type<'input>), (HashSet, Documentation<'input>)>, @@ -150,6 +204,10 @@ pub struct Processor<'ast, 'input: 'ast> { pub unions: HashMap>>, HashSet>, pub simple_restrictions: HashSet<(FullName<'input>, Facets<'input>)>, pub substitution_groups: HashMap, Vec>>, + + pub anonymous_types: HashMap>>, + pub anonymous_simple_types: HashMap>>, + _phantom: PhantomData<&'ast ()>, // Sometimes I need 'ast when prototyping } @@ -173,7 +231,6 @@ impl<'ast, 'input: 'ast> Processor<'ast, 'input> { elements: HashMap::new(), types: HashMap::new(), groups: HashMap::new(), - choices: HashMap::new(), lists: HashMap::new(), unions: HashMap::new(), sequences: HashMap::new(), @@ -182,6 +239,8 @@ impl<'ast, 'input: 'ast> Processor<'ast, 'input> { simple_types: HashMap::new(), simple_restrictions: HashSet::new(), substitution_groups: HashMap::new(), + anonymous_types: HashMap::new(), + anonymous_simple_types: HashMap::new(), _phantom: PhantomData::default(), } } @@ -234,44 +293,47 @@ impl<'ast, 'input: 'ast> Processor<'ast, 'input> { fn process_group_ref(&mut self, group_ref: &'ast inline_elements::GroupRef<'input>, - ) -> RichType<'input, Type<'input>> { + ) -> TypeId { let inline_elements::GroupRef { ref attrs, ref attr_id, ref attr_ref, ref attr_min_occurs, ref attr_max_occurs, ref annotation } = group_ref; let ref_ = attr_ref; let min_occurs = parse_min_occurs(attr_min_occurs); let max_occurs = parse_max_occurs(attr_max_occurs); let ref_ = FullName::from_qname(ref_, self.target_namespace); - RichType::new( + let id = register_rich_type!(self, RichType::new( NameHint::new(ref_.local_name()), - Type::Group(min_occurs, max_occurs, ref_), + Type::GroupRef(ref_), self.process_annotation(&annotation.iter().collect()), - ) + )); + many!(self, min_occurs, max_occurs, id) } fn process_named_group(&mut self, group: &'ast xs::Group<'input>, - ) -> RichType<'input, Type<'input>> { + ) -> TypeId { let xs::Group { ref attrs, ref attr_id, ref attr_name, ref annotation, choice_all_choice_sequence: ref content } = group; let name = attr_name; let max_occurs = 1; let min_occurs = 1; - let mut type_ = match content { + let mut id = match content { enums::ChoiceAllChoiceSequence::All(_) => unimplemented!("all"), enums::ChoiceAllChoiceSequence::Choice(e) => self.process_choice(e, true), enums::ChoiceAllChoiceSequence::Sequence(e) => self.process_sequence(e, true), }; + let type_ = self.anonymous_types.get_mut(&id).unwrap(); type_.doc.extend(&self.process_annotation(&annotation.iter().collect())); let doc = type_.doc.clone(); let name = FullName::new(self.target_namespace, name.0); - self.groups.insert(name, type_); - RichType::new( + self.groups.insert(name, id); + let id = register_rich_type!(self, RichType::new( NameHint::from_fullname(&name), - Type::Group(min_occurs, max_occurs, name), - doc, - ) + Type::GroupRef(name), + doc.clone(), + )); + many!(self, min_occurs, max_occurs, id) } fn process_attribute_group(&mut self, group: &'ast xs::AttributeGroup<'input>) { @@ -283,7 +345,7 @@ impl<'ast, 'input: 'ast> Processor<'ast, 'input> { fn process_local_simple_type(&mut self, simple_type: &'ast inline_elements::LocalSimpleType<'input>, - ) -> RichType<'input, SimpleType<'input>> { + ) -> SimpleTypeId { let inline_elements::LocalSimpleType { ref attrs, ref attr_id, ref annotation, ref simple_derivation } = simple_type; //let struct_name = self.namespaces.new_type(QName::from(name)); let annotation: Vec<_> = annotation.iter().collect(); @@ -296,13 +358,13 @@ impl<'ast, 'input: 'ast> Processor<'ast, 'input> { fn process_simple_type(&mut self, simple_type: &'ast xs::SimpleType<'input>, - ) -> RichType<'input, SimpleType<'input>> { + ) -> SimpleTypeId { let xs::SimpleType { ref attrs, ref attr_id, ref attr_name, ref attr_final, ref annotation, ref simple_derivation } = simple_type; let annotation: Vec<_> = annotation.iter().collect(); let name = attr_name; let name = FullName::new(self.target_namespace, name.0); //let struct_name = self.namespaces.new_type(QName::from(name)); - let ty = match simple_derivation { + let id = match simple_derivation { xs::SimpleDerivation::Restriction(e) => self.process_simple_restriction(e, annotation.clone()), xs::SimpleDerivation::List(ref e) => self.process_list(e, annotation.clone()), @@ -310,111 +372,101 @@ impl<'ast, 'input: 'ast> Processor<'ast, 'input> { }; let doc = self.process_annotation(&annotation); - self.simple_types.insert(name, (ty, doc.clone())); - RichType::new( - NameHint::from_fullname(&name), - SimpleType::Alias(name), - doc, - ) + self.anonymous_simple_types.get_mut(&id).unwrap().name_hint = NameHint::from_fullname(&name); // TODO: enrich the name hint instead of replacing it + id } fn process_list(&mut self, list: &'ast xs::List<'input>, annotation: Vec<&'ast xs::Annotation<'input>>, - ) -> RichType<'input, SimpleType<'input>> { + ) -> SimpleTypeId { let item_type = list.attr_item_type; let item_type = item_type.as_ref().map(|n| FullName::from_qname(n, self.target_namespace)); - let item_type = match (item_type, &list.local_simple_type) { + let (name_hint, item_type_id) = match (item_type, &list.local_simple_type) { (None, Some(st)) => { - let mut ty = self.process_local_simple_type(st); + let id: SimpleTypeId = self.process_local_simple_type(st); + let ty = self.anonymous_simple_types.get_mut(&id).unwrap(); ty.doc.extend(&self.process_annotation(&annotation)); - ty + (ty.name_hint, id) }, (Some(n), None) => { - RichType::new( - NameHint::new(n.local_name()), + let name_hint = NameHint::new(n.local_name()); + let id: SimpleTypeId = register_rich_simple_type!(self, RichType::new( + name_hint, SimpleType::Alias(n), - self.process_annotation(&annotation), - ) + Documentation::new(), + )); + (name_hint, id) }, (None, None) => panic!(" with no itemType or child type."), (Some(ref t1), Some(ref t2)) => panic!(" has both an itemType attribute ({:?}) and a child type ({:?}).", t1, t2), }; - let mut name_hint = item_type.name_hint.clone(); + let mut name_hint = name_hint.clone(); name_hint.push("list"); let doc = self.process_annotation(&annotation); - let name = name_from_hint(&name_hint).unwrap(); - self.lists.entry(item_type) - .or_insert(HashSet::new()) - .insert(name.clone()); - RichType::new( + register_rich_simple_type!(self, RichType::new( name_hint, - SimpleType::List(name), + SimpleType::List(item_type_id), doc, - ) + )) } fn process_union(&mut self, union: &'ast xs::Union<'input>, annotation: Vec<&'ast xs::Annotation<'input>>, - ) -> RichType<'input, SimpleType<'input>> { + ) -> SimpleTypeId { let default_vec = Vec::new(); let mut name_hint = NameHint::new("union"); let member_types = union.attr_member_types.as_ref().map(|l| &l.0).unwrap_or(&default_vec); - let mut member_types: Vec<_> = member_types.iter().map(|name| { + let mut member_types: Vec = member_types.iter().map(|name| { let name = FullName::from_qname(name, self.target_namespace); name_hint.push(name.local_name()); - RichType::new( - NameHint::new(name.local_name()), - SimpleType::Alias(name), - self.process_annotation(&annotation), - ) + register_rich_simple_type!(self, RichType::new( + NameHint::new(name.local_name()), + SimpleType::Alias(name), + Documentation::new(), + )) }).collect(); for t in union.local_simple_type.iter() { - let ty = self.process_local_simple_type(t); - name_hint.extend(&ty.name_hint); - member_types.push(ty) + let id = self.process_local_simple_type(t); + name_hint.extend(&self.anonymous_simple_types.get(&id).unwrap().name_hint); + member_types.push(id) } let doc = self.process_annotation(&annotation); let name = name_from_hint(&name_hint).unwrap(); - self.unions.entry(member_types) - .or_insert(HashSet::new()) - .insert(name.clone()); - RichType::new( + register_rich_simple_type!(self, RichType::new( name_hint, - SimpleType::Union(name), + SimpleType::Union(member_types), doc, - ) + )) } fn process_complex_type(&mut self, complex_type: &'ast xs::ComplexType<'input>, inlinable: bool, - ) -> RichType<'input, Type<'input>> { + ) -> TypeId { let xs::ComplexType { ref attrs, ref attr_id, ref attr_name, ref attr_mixed, ref attr_abstract, ref attr_final, ref attr_block, ref attr_default_attributes_apply, ref annotation, ref complex_type_model } = complex_type; let name = attr_name; //let struct_name = self.namespaces.new_type(QName::from(name)); - let mut ty = match complex_type_model { - xs::ComplexTypeModel::SimpleContent(_) => unimplemented!("simpleContent"), + let mut id = match complex_type_model { + xs::ComplexTypeModel::SimpleContent(ref model) => + self.process_simple_content(model), xs::ComplexTypeModel::ComplexContent(ref model) => self.process_complex_content(model, false), xs::ComplexTypeModel::CompleteContentModel { ref open_content, ref type_def_particle, ref attr_decls, ref assertions } => self.process_complete_content_model(open_content, type_def_particle, attr_decls, assertions, inlinable), }; + let ty = self.anonymous_types.get(&id).unwrap(); ty.doc.extend(&self.process_annotation(&annotation.iter().collect())); let doc = ty.doc.clone(); let name = FullName::new(self.target_namespace, name.0); - self.types.insert(name, ty); - RichType::new( - NameHint::from_fullname(&name), - Type::Alias(name), - doc, - ) + self.anonymous_types.get_mut(&id).unwrap().name_hint = NameHint::from_fullname(&name); // TODO enrich instead of replacing + id } fn process_local_complex_type(&mut self, @@ -422,32 +474,26 @@ impl<'ast, 'input: 'ast> Processor<'ast, 'input> { attr_name: Option<&'ast NcName<'input>>, annotation: Vec<&'ast xs::Annotation<'input>>, inlinable: bool, - ) -> RichType<'input, Type<'input>> { + ) -> TypeId { let inline_elements::LocalComplexType { ref attrs, ref attr_id, ref attr_mixed, ref attr_default_attributes_apply, annotation: ref annotation2, ref complex_type_model } = complex_type; let name = attr_name; //let struct_name = self.namespaces.new_type(QName::from(name)); - let mut ty = match complex_type_model { - xs::ComplexTypeModel::SimpleContent(_) => unimplemented!("simpleContent"), + let mut id = match complex_type_model { + xs::ComplexTypeModel::SimpleContent(ref model) => + self.process_simple_content(model), xs::ComplexTypeModel::ComplexContent(ref model) => self.process_complex_content(model, false), xs::ComplexTypeModel::CompleteContentModel { ref open_content, ref type_def_particle, ref attr_decls, ref assertions } => self.process_complete_content_model(open_content, type_def_particle, attr_decls, assertions, inlinable), }; + let mut ty = self.anonymous_types.get_mut(&id).unwrap(); ty.doc.extend(&self.process_annotation(&vec_concat_opt(&annotation, annotation2.as_ref()))); if let Some(name) = name { - let doc = ty.doc.clone(); let name = FullName::new(self.target_namespace, name.0); - self.types.insert(name, ty); - RichType::new( - NameHint::from_fullname(&name), - Type::Alias(name), - doc, - ) - } - else { - ty + ty.name_hint = NameHint::from_fullname(&name); // TODO enrich instead of replacing } + id } fn process_complete_content_model(&mut self, @@ -456,19 +502,26 @@ impl<'ast, 'input: 'ast> Processor<'ast, 'input> { attr_decls: &'ast xs::AttrDecls<'input>, assertions: &'ast xs::Assertions<'input>, inlinable: bool, - ) -> RichType<'input, Type<'input>> { - let ty = match type_def_particle.as_ref() { + ) -> TypeId { + let id = match type_def_particle.as_ref() { Some(type_def_particle) => self.process_type_def_particle(type_def_particle, inlinable), - None => RichType::new( + None => register_rich_type!(self, RichType::new( NameHint::new("empty_particle"), Type::Empty, Documentation::new() - ), + )), }; - ty.add_attrs(self.process_attr_decls(attr_decls)) + self.anonymous_types.get_mut(&id).unwrap().add_attrs(self.process_attr_decls(attr_decls)); + id } - fn process_complex_content(&mut self, model: &'ast xs::ComplexContent<'input>, inlinable: bool) -> RichType<'input, Type<'input>> { + fn process_simple_content(&mut self, model: &'ast xs::SimpleContent<'input>) -> TypeId { + let xs::SimpleContent { ref attrs, ref attr_id, ref annotation, ref choice_restriction_extension } = model; + + panic!("not implemented"); + } + + fn process_complex_content(&mut self, model: &'ast xs::ComplexContent<'input>, inlinable: bool) -> TypeId { let xs::ComplexContent { ref attrs, ref attr_id, ref attr_mixed, ref annotation, ref choice_restriction_extension } = model; let annotation = annotation.iter().collect(); match choice_restriction_extension { @@ -478,30 +531,32 @@ impl<'ast, 'input: 'ast> Processor<'ast, 'input> { ref sequence_open_content_type_def_particle, ref attr_decls, ref assertions } = **r; - let ty = match sequence_open_content_type_def_particle { + let id = match sequence_open_content_type_def_particle { Some(sequences::SequenceOpenContentTypeDefParticle { open_content, type_def_particle }) => self.process_complex_restriction(attr_base, type_def_particle, vec_concat_opt(&annotation, annotation2.as_ref())), None => { - RichType::new( + register_rich_type!(self, RichType::new( NameHint::new("empty_extension"), Type::Empty, self.process_annotation(&vec_concat_opt(&annotation, annotation2.as_ref())), - ) + )) }, }; - ty.add_attrs(self.process_attr_decls(attr_decls)) + self.anonymous_types.get_mut(&id).unwrap().add_attrs(self.process_attr_decls(attr_decls)); + id }, enums::ChoiceRestrictionExtension::Extension(ref e) => { let inline_elements::ExtensionType { ref attrs, ref attr_base, ref attr_id, annotation: ref annotation2, ref open_content, ref type_def_particle, ref attr_decls, ref assertions } = **e; - let ty = match type_def_particle { + let id = match type_def_particle { Some(type_def_particle) => self.process_extension(attrs, attr_base, type_def_particle, vec_concat_opt(&annotation, annotation2.as_ref()), inlinable), None => self.process_trivial_extension(attrs, attr_base, vec_concat_opt(&annotation, annotation2.as_ref())), }; - ty.add_attrs(self.process_attr_decls(attr_decls)) + self.anonymous_types.get_mut(&id).unwrap().add_attrs(self.process_attr_decls(attr_decls)); + id }, } } @@ -510,15 +565,15 @@ impl<'ast, 'input: 'ast> Processor<'ast, 'input> { attr_base: &'ast QName<'input>, type_def_particle: &'ast xs::TypeDefParticle<'input>, annotation: Vec<&'ast xs::Annotation<'input>>, - ) -> RichType<'input, Type<'input>> { + ) -> TypeId { // TODO: use the base - let ty = self.process_type_def_particle(type_def_particle, false); + let id = self.process_type_def_particle(type_def_particle, false); let base = FullName::from_qname(attr_base, self.target_namespace); - RichType::new( + register_rich_type!(self, RichType::new( NameHint::new_empty(), - Type::Restriction(base, Box::new(ty)), + Type::Restriction(base, id), self.process_annotation(&annotation), - ) + )) } fn process_facets(&mut self, facet_list: &Vec>) -> Facets<'input> { @@ -554,7 +609,7 @@ impl<'ast, 'input: 'ast> Processor<'ast, 'input> { fn process_simple_restriction(&mut self, restriction: &'ast xs::Restriction<'input>, annotation: Vec<&'ast xs::Annotation<'input>>, - ) -> RichType<'input, SimpleType<'input>> { + ) -> SimpleTypeId { let xs::Restriction { ref attrs, ref attr_id, ref attr_base, annotation: ref annotation2, ref simple_restriction_model } = restriction; let base = attr_base; let base = base.unwrap_or(QName { namespace: Some(SCHEMA_URI), local_name: "anySimpleType" }); @@ -567,23 +622,23 @@ impl<'ast, 'input: 'ast> Processor<'ast, 'input> { match local_simple_type { Some(inline_elements::LocalSimpleType { ref attrs, ref attr_id, annotation: ref annotation2, ref simple_derivation }) => { - RichType::new( + register_rich_simple_type!(self, RichType::new( NameHint::new(base.local_name()), SimpleType::Restriction(base, facets), self.process_annotation(&vec_concat_opt(&annotation, annotation2.as_ref())), - ) + )) }, None => { - RichType::new( + register_rich_simple_type!(self, RichType::new( NameHint::new(base.local_name()), SimpleType::Restriction(base, facets), self.process_annotation(&annotation), - ) + )) }, } } - fn process_type_def_particle(&mut self, particle: &'ast xs::TypeDefParticle<'input>, inlinable: bool) -> RichType<'input, Type<'input>> { + fn process_type_def_particle(&mut self, particle: &'ast xs::TypeDefParticle<'input>, inlinable: bool) -> TypeId { match particle { xs::TypeDefParticle::Group(e) => self.process_group_ref(e), xs::TypeDefParticle::All(_) => unimplemented!("all"), @@ -596,8 +651,8 @@ impl<'ast, 'input: 'ast> Processor<'ast, 'input> { particle: &'ast xs::NestedParticle<'input>, annotation: Vec<&'ast xs::Annotation<'input>>, inlinable: bool - ) -> RichType<'input, Type<'input>> { - let mut ty = match particle { + ) -> TypeId { + let mut id = match particle { xs::NestedParticle::Element(e) => self.process_local_element(e), xs::NestedParticle::Group(e) => self.process_group_ref(e), xs::NestedParticle::Choice(e) => self.process_choice(e, inlinable), @@ -605,140 +660,91 @@ impl<'ast, 'input: 'ast> Processor<'ast, 'input> { xs::NestedParticle::Any(e) => self.process_any(e, Vec::new()), }; - ty.doc.extend(&self.process_annotation(&annotation)); - ty + self.anonymous_types.get_mut(&id).unwrap().doc.extend(&self.process_annotation(&annotation)); + id } fn process_any(&mut self, any: &'ast xs::Any<'input>, annotation: Vec<&'ast xs::Annotation<'input>>, - ) -> RichType<'input, Type<'input>> { - RichType::new( + ) -> TypeId { + register_rich_type!(self, RichType::new( NameHint::new("any"), Type::Any, self.process_annotation(&annotation), - ) + )) } fn process_sequence(&mut self, seq: &'ast xs::Sequence<'input>, inlinable: bool, - ) -> RichType<'input, Type<'input>> { + ) -> TypeId { let xs::Sequence { ref attrs, ref attr_id, ref attr_min_occurs, ref attr_max_occurs, ref annotation, ref nested_particle } = seq; let particles = nested_particle; let min_occurs = parse_min_occurs(attr_min_occurs); let max_occurs = parse_max_occurs(attr_max_occurs); let mut items = Vec::new(); let mut name_hint = NameHint::new("sequence"); - if min_occurs == 1 && max_occurs == 1 && inlinable && particles.len() == 1 { + let id = if inlinable && particles.len() == 1 { self.process_nested_particle(particles.get(0).unwrap(), annotation.iter().collect(), inlinable) } else { for particle in particles.iter() { - let ty = self.process_nested_particle(particle, vec![], false); - name_hint.extend(&ty.name_hint); - items.push(ty); + let id = self.process_nested_particle(particle, vec![], false); + name_hint.extend(&self.anonymous_types.get(&id).unwrap().name_hint); + items.push(id); } let doc = self.process_annotation(&annotation.iter().collect()); - if min_occurs == 1 && max_occurs == 1 { - RichType::new( - name_hint, - Type::InlineSequence(items), - doc, - ) - } - else { - let name = name_from_hint(&name_hint).unwrap(); - let (names, docs) = self.sequences.entry(items) - .or_insert((HashSet::new(), Documentation::new())); - names.insert(name.clone()); - docs.extend(&doc); - RichType::new( - name_hint, - Type::Sequence(min_occurs, max_occurs, name), - doc, - ) - } - } + register_rich_type!(self, RichType::new( + name_hint.clone(), + Type::Sequence(items), + doc, + )) + }; + many!(self, min_occurs, max_occurs, id) } fn process_choice(&mut self, choice: &'ast xs::Choice<'input>, inlinable: bool - ) -> RichType<'input, Type<'input>> { + ) -> TypeId { let xs::Choice { ref attrs, ref attr_id, ref attr_min_occurs, ref attr_max_occurs, ref annotation, ref nested_particle } = choice; let particles = nested_particle; let min_occurs = parse_min_occurs(attr_min_occurs); let max_occurs = parse_max_occurs(attr_max_occurs); let mut items = Vec::new(); let mut name_hint = NameHint::new("choice"); - if particles.len() == 1 { + let doc = self.process_annotation(&annotation.iter().collect()); + let id = if particles.len() == 1 { let particle = particles.get(0).unwrap(); - let RichType { name_hint, attrs, type_, doc } = - self.process_nested_particle(particle, annotation.iter().collect(), inlinable); - match (min_occurs, max_occurs, type_) { - (_, _, Type::Element(1, 1, e)) => return RichType { - name_hint, attrs, type_: Type::Element(min_occurs, max_occurs, e), doc }, - (_, _, Type::Group(1, 1, e)) => return RichType { - name_hint, attrs, type_: Type::Group(min_occurs, max_occurs, e), doc }, - (_, _, Type::Choice(1, 1, e)) => return RichType { - name_hint, attrs, type_: Type::Choice(min_occurs, max_occurs, e), doc }, - (_, _, Type::Sequence(1, 1, e)) => return RichType { - name_hint, attrs, type_: Type::Sequence(min_occurs, max_occurs, e), doc }, - (1, 1, type_) => return RichType { name_hint, attrs, type_, doc }, - (_, _, type_) => { - let name = name_from_hint(&name_hint).unwrap(); - let items = vec![RichType { name_hint: name_hint.clone(), attrs: Attrs::new(), type_, doc: doc.clone() }]; - let (names, docs) = self.sequences.entry(items) - .or_insert((HashSet::new(), Documentation::new())); - names.insert(name.clone()); - docs.extend(&doc); - let type_ = Type::Sequence(min_occurs, max_occurs, name); - return RichType { name_hint, attrs, type_, doc } - }, - } + self.process_nested_particle(particle, annotation.iter().collect(), inlinable) } else { for particle in particles.iter() { - let ty = self.process_nested_particle(particle, vec![], false); - name_hint.extend(&ty.name_hint); - items.push(ty); + let id = self.process_nested_particle(particle, vec![], false); + name_hint.extend(&self.anonymous_types.get(&id).unwrap().name_hint); + items.push(id); } - } - let doc = self.process_annotation(&annotation.iter().collect()); - match (min_occurs, max_occurs, inlinable) { - (1, 1, true) => { - RichType::new( - name_hint, - Type::InlineChoice(items), - doc, - ) - }, - (_, _, _) => { - let name = name_from_hint(&name_hint).unwrap(); - self.choices.entry(items) - .or_insert(HashSet::new()) - .insert(name.clone()); - RichType::new( - name_hint, - Type::Choice(min_occurs, max_occurs, name), - doc, - ) - } - } + register_rich_type!(self, RichType::new( + name_hint, + Type::Choice(items), + doc.clone(), + )) + }; + many!(self, min_occurs, max_occurs, id) } fn process_trivial_extension(&mut self, attrs: &'ast HashMap, &'input str>, attr_base: &'ast QName<'input>, annotation: Vec<&'ast xs::Annotation<'input>>, - ) -> RichType<'input, Type<'input>> { + ) -> TypeId { let base = FullName::from_qname(&attr_base, self.target_namespace); - RichType::new( + register_rich_type!(self, RichType::new( NameHint::new_empty(), Type::Alias(base), self.process_annotation(&annotation), - ) + )) } fn process_extension(&mut self, @@ -747,13 +753,13 @@ impl<'ast, 'input: 'ast> Processor<'ast, 'input> { type_def_particle: &'ast xs::TypeDefParticle<'input>, annotation: Vec<&'ast xs::Annotation<'input>>, inlinable: bool, - ) -> RichType<'input, Type<'input>> { + ) -> TypeId { let base = FullName::from_qname(attr_base, self.target_namespace); - RichType::new( + register_rich_type!(self, RichType::new( NameHint::new_empty(), - Type::Extension(base, Box::new(self.process_type_def_particle(type_def_particle, inlinable))), + Type::Extension(base, self.process_type_def_particle(type_def_particle, inlinable)), self.process_annotation(&annotation), - ) + )) } fn process_toplevel_element(&mut self, element: &'ast xs::Element<'input>) { @@ -770,15 +776,17 @@ impl<'ast, 'input: 'ast> Processor<'ast, 'input> { .push(name.clone()); } } - let type_ = match (type_attr, &child_type) { + let ty = match (type_attr, &child_type) { (None, Some(ref c)) => match c { enums::Type::SimpleType(ref e) => { - let mut ty = self.process_local_simple_type(e); + let mut id = self.process_local_simple_type(e); + let mut ty = self.anonymous_simple_types.remove(&id).unwrap(); ty.doc.extend(&self.process_annotation(&annotation)); ty.into_complex() }, enums::Type::ComplexType(ref e) => { - self.process_local_complex_type(e, Some(attr_name), annotation, false) + let id = self.process_local_complex_type(e, Some(attr_name), annotation, false); + self.anonymous_types.remove(&id).unwrap() }, }, (Some(t), None) => { @@ -799,12 +807,12 @@ impl<'ast, 'input: 'ast> Processor<'ast, 'input> { (Some(ref t1), Some(ref t2)) => panic!("Toplevel element '{:?}' has both a type attribute ({:?}) and a child type ({:?}).", name, t1, t2), }; - self.elements.insert(name, type_); + self.elements.insert(name, ty); } fn process_local_element(&mut self, element: &'ast inline_elements::LocalElement<'input>, - ) -> RichType<'input, Type<'input>> { + ) -> TypeId { let inline_elements::LocalElement { ref attrs, ref attr_id, ref attr_name, ref attr_ref, ref attr_min_occurs, ref attr_max_occurs, ref attr_type, ref attr_default, ref attr_fixed, ref attr_nillable, ref attr_block, ref attr_form, ref attr_target_namespace, ref annotation, ref type_, ref alternative_alt_type, ref identity_constraint } = element; let annotation = annotation.iter().collect(); let name = attr_name; @@ -817,11 +825,12 @@ impl<'ast, 'input: 'ast> Processor<'ast, 'input> { panic!(" has both ref={:?} and name={:?}", ref_, name); } let ref_ = FullName::from_qname(ref_, self.target_namespace); - RichType::new( - NameHint::new(ref_.local_name()), - Type::ElementRef(min_occurs, max_occurs, ref_), - self.process_annotation(&annotation), - ) + many!(self, min_occurs, max_occurs, + register_rich_type!(self, RichType::new( + NameHint::new(ref_.local_name()), + Type::ElementRef(ref_), + self.process_annotation(&annotation), + ))) } else { let name = name.as_ref().expect(" has no name.").0; @@ -841,16 +850,18 @@ impl<'ast, 'input: 'ast> Processor<'ast, 'input> { match (type_attr, &type_) { (None, Some(ref c)) => { - let mut t = match c { + let mut id = match c { enums::Type::SimpleType(ref e) => { - let mut ty = self.process_local_simple_type(e); + let id = self.process_local_simple_type(e); + let mut ty = self.anonymous_simple_types.remove(&id).unwrap(); ty.doc.extend(&self.process_annotation(&annotation)); - ty.into_complex() + register_rich_type!(self, ty.into_complex()) }, enums::Type::ComplexType(ref e) => { self.process_local_complex_type(e, None, annotation, false) }, }; + let t = self.anonymous_types.get_mut(&id).unwrap(); let mut name_hint = NameHint::new(name); name_hint.extend(&t.name_hint); let struct_name = name_from_hint(&name_hint).unwrap(); @@ -858,11 +869,12 @@ impl<'ast, 'input: 'ast> Processor<'ast, 'input> { .or_insert((HashSet::new(), Documentation::new())); elems.insert(struct_name.clone()); t.doc.extend(doc); - RichType::new( - NameHint::new(name), - Type::Element(min_occurs, max_occurs, struct_name), - t.doc, - ) + many!(self, min_occurs, max_occurs, + register_rich_type!(self, RichType::new( + NameHint::new(name), + Type::Element(struct_name), + t.doc, + ))) }, (Some(t), None) => { let name_hint1 = NameHint::new(t.local_name); @@ -882,18 +894,20 @@ impl<'ast, 'input: 'ast> Processor<'ast, 'input> { .or_insert((HashSet::new(), Documentation::new())); elems.insert(struct_name.clone()); doc.extend(doc2); - RichType::new( - NameHint::new(name), - Type::Element(min_occurs, max_occurs, struct_name), - doc, - ) + many!(self, min_occurs, max_occurs, + register_rich_type!(self, RichType::new( + NameHint::new(name), + Type::Element(struct_name), + doc, + ))) }, (None, None) => { - RichType::new( - NameHint::new("empty"), - Type::Empty, - self.process_annotation(&annotation), - ) + many!(self, min_occurs, max_occurs, + register_rich_type!(self, RichType::new( + NameHint::new("empty"), + Type::Empty, + self.process_annotation(&annotation), + ))) }, (Some(ref t1), Some(ref t2)) => panic!("Element '{:?}' has both a type attribute ({:?}) and a child type ({:?}).", name, t1, t2), } @@ -917,11 +931,16 @@ impl<'ast, 'input: 'ast> Processor<'ast, 'input> { match (name, e.attr_ref, type_attr, &e.local_simple_type) { (Some(name), None, Some(t), None) => { let t = FullName::from_qname(&t, self.target_namespace); - attrs.named.push((name, use_, Some(SimpleType::Alias(t)))); + let id = register_rich_simple_type!(self, RichType::new( + NameHint::new(&t.local_name()), + SimpleType::Alias(t), + Documentation::new(), + )); + attrs.named.push((name, use_, Some(id))); }, (Some(name), None, None, Some(t)) => { - let t = self.process_local_simple_type(t); - attrs.named.push((name, use_, Some(t.type_))); + let id = self.process_local_simple_type(t); + attrs.named.push((name, use_, Some(id))); }, (Some(name), None, None, None) => attrs.named.push((name, use_, None)),