use slotmap::SlotMap;
use crate::ids::*;
#[cfg(feature = "xsd11")]
use crate::parser::frames::AssertResult;
use crate::parser::frames::{
AlternativeResult, AttributeUseResult, ComplexContentResult, Compositor, DerivationMethod,
FieldResult, IdentityKind, OpenContentResult, ParticleResult, QNameRef, SelectorResult,
SimpleTypeResult, SimpleTypeVariety, TypeFrameResult, TypeRefResult, WildcardResult,
};
use crate::parser::location::SourceRef;
use crate::schema::annotation::Annotation;
use crate::schema::model::DerivationSet;
use crate::types::facets::FacetSet;
#[derive(Debug, Clone)]
pub struct DeferredSrcResolve {
pub message: String,
pub source: Option<SourceRef>,
}
#[derive(Debug)]
pub struct SimpleTypeDefData {
pub name: Option<NameId>,
pub target_namespace: Option<NameId>,
pub variety: SimpleTypeVariety,
pub base_type: Option<TypeRefResult>,
pub item_type: Option<TypeRefResult>,
pub member_types: Vec<TypeRefResult>,
pub facets: FacetSet,
pub final_derivation: DerivationSet,
pub id: Option<String>,
pub derivation_id: Option<String>,
pub annotation: Option<Annotation>,
pub source: Option<SourceRef>,
pub resolved_base_type: Option<TypeKey>,
pub resolved_item_type: Option<TypeKey>,
pub resolved_member_types: Vec<TypeKey>,
pub redefine_original: Option<SimpleTypeKey>,
pub deferred_item_type_error: Option<DeferredSrcResolve>,
}
#[derive(Debug, Clone)]
pub struct ResolvedAttributeUse {
pub resolved_type: Option<TypeKey>,
pub resolved_ref: Option<AttributeKey>,
}
#[derive(Debug)]
pub struct ComplexTypeDefData {
pub name: Option<NameId>,
pub target_namespace: Option<NameId>,
pub base_type: Option<TypeRefResult>,
pub derivation_method: Option<DerivationMethod>,
pub content: ComplexContentResult,
pub open_content: Option<OpenContentResult>,
pub attributes: Vec<AttributeUseResult>,
pub attribute_groups: Vec<QNameRef>,
pub attribute_wildcard: Option<WildcardResult>,
pub mixed: bool,
pub is_abstract: bool,
pub final_derivation: DerivationSet,
pub block: DerivationSet,
pub default_attributes_apply: bool,
pub id: Option<String>,
#[cfg(feature = "xsd11")]
pub assertions: Vec<AssertResult>,
#[cfg(feature = "xsd11")]
pub xpath_default_namespace: Option<String>,
pub annotation: Option<Annotation>,
pub source: Option<SourceRef>,
pub resolved_base_type: Option<TypeKey>,
pub resolved_attribute_groups: Vec<AttributeGroupKey>,
pub resolved_attributes: Vec<ResolvedAttributeUse>,
pub resolved_content_particle_types: Vec<Option<TypeKey>>,
pub resolved_content_particle_elements: Vec<Option<ElementKey>>,
pub resolved_simple_content_type: Option<TypeKey>,
pub redefine_original: Option<ComplexTypeKey>,
}
#[derive(Debug)]
pub struct ElementDeclData {
pub name: Option<NameId>,
pub target_namespace: Option<NameId>,
pub ref_name: Option<QNameRef>,
pub type_ref: Option<TypeRefResult>,
pub inline_type: Option<Box<TypeFrameResult>>,
pub substitution_group: Vec<QNameRef>,
pub default_value: Option<String>,
pub fixed_value: Option<String>,
pub nillable: bool,
pub is_abstract: bool,
pub min_occurs: u32,
pub max_occurs: Option<u32>,
pub block: DerivationSet,
pub final_derivation: DerivationSet,
pub form: Option<String>,
pub id: Option<String>,
pub alternatives: Vec<AlternativeResult>,
pub identity_constraints: Vec<IdentityConstraintKey>,
pub pending_ic_refs: Vec<(IdentityKind, QNameRef, Option<SourceRef>)>,
pub annotation: Option<Annotation>,
pub source: Option<SourceRef>,
pub resolved_type: Option<TypeKey>,
pub resolved_ref: Option<ElementKey>,
pub resolved_substitution_groups: Vec<ElementKey>,
pub deferred_type_error: Option<DeferredSrcResolve>,
}
#[derive(Debug)]
pub struct AttributeDeclData {
pub name: Option<NameId>,
pub target_namespace: Option<NameId>,
pub ref_name: Option<QNameRef>,
pub type_ref: Option<TypeRefResult>,
pub inline_type: Option<Box<SimpleTypeResult>>,
pub default_value: Option<String>,
pub fixed_value: Option<String>,
pub use_kind: Option<String>,
pub form: Option<String>,
pub inheritable: bool,
pub id: Option<String>,
pub annotation: Option<Annotation>,
pub source: Option<SourceRef>,
pub resolved_type: Option<TypeKey>,
pub resolved_ref: Option<AttributeKey>,
}
#[derive(Debug)]
pub struct AttributeGroupData {
pub name: Option<NameId>,
pub target_namespace: Option<NameId>,
pub ref_name: Option<QNameRef>,
pub attributes: Vec<AttributeUseResult>,
pub attribute_groups: Vec<QNameRef>,
pub attribute_wildcard: Option<WildcardResult>,
pub id: Option<String>,
pub annotation: Option<Annotation>,
pub source: Option<SourceRef>,
pub resolved_ref: Option<AttributeGroupKey>,
pub resolved_attribute_groups: Vec<AttributeGroupKey>,
pub resolved_attributes: Vec<ResolvedAttributeUse>,
pub redefine_original: Option<AttributeGroupKey>,
pub redefine_requires_restriction_check: bool,
}
#[derive(Debug, Clone)]
pub enum ResolvedParticleTerm {
Element {
resolved_type: Option<TypeKey>,
resolved_ref: Option<ElementKey>,
},
Group { resolved_ref: Option<ModelGroupKey> },
Any,
}
#[derive(Debug)]
pub struct ModelGroupData {
pub name: Option<NameId>,
pub target_namespace: Option<NameId>,
pub ref_name: Option<QNameRef>,
pub compositor: Option<Compositor>,
pub particles: Vec<ParticleResult>,
pub min_occurs: u32,
pub max_occurs: Option<u32>,
pub id: Option<String>,
pub annotation: Option<Annotation>,
pub source: Option<SourceRef>,
pub resolved_ref: Option<ModelGroupKey>,
pub resolved_particles: Vec<ResolvedParticleTerm>,
pub resolved_particle_types: Vec<Option<TypeKey>>,
pub resolved_particle_elements: Vec<Option<ElementKey>>,
pub redefine_original: Option<ModelGroupKey>,
pub redefine_requires_restriction_check: bool,
}
#[derive(Debug)]
pub struct NotationData {
pub name: NameId,
pub target_namespace: Option<NameId>,
pub public: Option<String>,
pub system: Option<String>,
pub id: Option<String>,
pub annotation: Option<Annotation>,
pub source: Option<SourceRef>,
}
#[derive(Debug)]
pub struct IdentityConstraintData {
pub kind: IdentityKind,
pub name: NameId,
pub ref_name: Option<QNameRef>,
pub refer: Option<QNameRef>,
pub selector: SelectorResult,
pub fields: Vec<FieldResult>,
pub id: Option<String>,
pub annotation: Option<Annotation>,
pub source: Option<SourceRef>,
}
#[derive(Debug, Default)]
pub struct SchemaArenas {
pub simple_types: SlotMap<SimpleTypeKey, SimpleTypeDefData>,
pub complex_types: SlotMap<ComplexTypeKey, ComplexTypeDefData>,
pub elements: SlotMap<ElementKey, ElementDeclData>,
pub attributes: SlotMap<AttributeKey, AttributeDeclData>,
pub attribute_groups: SlotMap<AttributeGroupKey, AttributeGroupData>,
pub model_groups: SlotMap<ModelGroupKey, ModelGroupData>,
pub notations: SlotMap<NotationKey, NotationData>,
pub identity_constraints: SlotMap<IdentityConstraintKey, IdentityConstraintData>,
}
impl SchemaArenas {
pub fn new() -> Self {
Self::default()
}
pub fn alloc_simple_type(&mut self, data: SimpleTypeDefData) -> SimpleTypeKey {
self.simple_types.insert(data)
}
pub fn get_simple_type(&self, key: SimpleTypeKey) -> Option<&SimpleTypeDefData> {
self.simple_types.get(key)
}
pub fn get_simple_type_mut(&mut self, key: SimpleTypeKey) -> Option<&mut SimpleTypeDefData> {
self.simple_types.get_mut(key)
}
pub fn alloc_complex_type(&mut self, data: ComplexTypeDefData) -> ComplexTypeKey {
self.complex_types.insert(data)
}
pub fn get_complex_type(&self, key: ComplexTypeKey) -> Option<&ComplexTypeDefData> {
self.complex_types.get(key)
}
pub fn get_complex_type_mut(&mut self, key: ComplexTypeKey) -> Option<&mut ComplexTypeDefData> {
self.complex_types.get_mut(key)
}
pub fn alloc_element(&mut self, data: ElementDeclData) -> ElementKey {
self.elements.insert(data)
}
pub fn get_element(&self, key: ElementKey) -> Option<&ElementDeclData> {
self.elements.get(key)
}
pub fn get_element_mut(&mut self, key: ElementKey) -> Option<&mut ElementDeclData> {
self.elements.get_mut(key)
}
pub fn alloc_attribute(&mut self, data: AttributeDeclData) -> AttributeKey {
self.attributes.insert(data)
}
pub fn get_attribute(&self, key: AttributeKey) -> Option<&AttributeDeclData> {
self.attributes.get(key)
}
pub fn get_attribute_mut(&mut self, key: AttributeKey) -> Option<&mut AttributeDeclData> {
self.attributes.get_mut(key)
}
pub fn alloc_attribute_group(&mut self, data: AttributeGroupData) -> AttributeGroupKey {
self.attribute_groups.insert(data)
}
pub fn get_attribute_group(&self, key: AttributeGroupKey) -> Option<&AttributeGroupData> {
self.attribute_groups.get(key)
}
pub fn get_attribute_group_mut(
&mut self,
key: AttributeGroupKey,
) -> Option<&mut AttributeGroupData> {
self.attribute_groups.get_mut(key)
}
pub fn alloc_model_group(&mut self, data: ModelGroupData) -> ModelGroupKey {
self.model_groups.insert(data)
}
pub fn get_model_group(&self, key: ModelGroupKey) -> Option<&ModelGroupData> {
self.model_groups.get(key)
}
pub fn get_model_group_mut(&mut self, key: ModelGroupKey) -> Option<&mut ModelGroupData> {
self.model_groups.get_mut(key)
}
pub fn alloc_notation(&mut self, data: NotationData) -> NotationKey {
self.notations.insert(data)
}
pub fn get_notation(&self, key: NotationKey) -> Option<&NotationData> {
self.notations.get(key)
}
pub fn get_notation_mut(&mut self, key: NotationKey) -> Option<&mut NotationData> {
self.notations.get_mut(key)
}
pub fn alloc_identity_constraint(
&mut self,
data: IdentityConstraintData,
) -> IdentityConstraintKey {
self.identity_constraints.insert(data)
}
pub fn get_identity_constraint(
&self,
key: IdentityConstraintKey,
) -> Option<&IdentityConstraintData> {
self.identity_constraints.get(key)
}
pub fn get_identity_constraint_mut(
&mut self,
key: IdentityConstraintKey,
) -> Option<&mut IdentityConstraintData> {
self.identity_constraints.get_mut(key)
}
}
#[cfg(test)]
mod tests {
use super::*;
fn simple_type_data(name: NameId) -> SimpleTypeDefData {
SimpleTypeDefData {
name: Some(name),
target_namespace: None,
variety: SimpleTypeVariety::Atomic,
base_type: None,
item_type: None,
member_types: Vec::new(),
facets: FacetSet::new(),
final_derivation: DerivationSet::empty(),
id: None,
derivation_id: None,
annotation: None,
source: None,
resolved_base_type: None,
resolved_item_type: None,
resolved_member_types: Vec::new(),
redefine_original: None,
deferred_item_type_error: None,
}
}
fn element_data(name: NameId, target_namespace: Option<NameId>) -> ElementDeclData {
ElementDeclData {
name: Some(name),
target_namespace,
ref_name: None,
type_ref: None,
inline_type: None,
substitution_group: Vec::new(),
default_value: None,
fixed_value: None,
nillable: false,
is_abstract: false,
min_occurs: 1,
max_occurs: Some(1),
block: DerivationSet::empty(),
final_derivation: DerivationSet::empty(),
form: None,
id: None,
alternatives: Vec::new(),
identity_constraints: Vec::new(),
pending_ic_refs: vec![],
annotation: None,
source: None,
resolved_type: None,
resolved_ref: None,
resolved_substitution_groups: Vec::new(),
deferred_type_error: None,
}
}
#[test]
fn test_alloc_and_get_simple_type() {
let mut arenas = SchemaArenas::new();
let data = simple_type_data(NameId(1));
let key = arenas.alloc_simple_type(data);
let retrieved = arenas.get_simple_type(key).unwrap();
assert_eq!(retrieved.name, Some(NameId(1)));
}
#[test]
fn test_alloc_and_get_element() {
let mut arenas = SchemaArenas::new();
let data = element_data(NameId(2), Some(NameId(3)));
let key = arenas.alloc_element(data);
let retrieved = arenas.get_element(key).unwrap();
assert_eq!(retrieved.name, Some(NameId(2)));
assert_eq!(retrieved.target_namespace, Some(NameId(3)));
}
#[test]
fn test_multiple_allocations() {
let mut arenas = SchemaArenas::new();
let key1 = arenas.alloc_simple_type(simple_type_data(NameId(1)));
let key2 = arenas.alloc_simple_type(simple_type_data(NameId(2)));
assert_ne!(key1, key2);
assert_eq!(arenas.get_simple_type(key1).unwrap().name, Some(NameId(1)));
assert_eq!(arenas.get_simple_type(key2).unwrap().name, Some(NameId(2)));
}
#[test]
fn test_mutable_access() {
let mut arenas = SchemaArenas::new();
let key = arenas.alloc_simple_type(simple_type_data(NameId(1)));
if let Some(data) = arenas.get_simple_type_mut(key) {
data.name = Some(NameId(99));
}
assert_eq!(arenas.get_simple_type(key).unwrap().name, Some(NameId(99)));
}
#[test]
fn test_slotmap_iteration() {
let mut arenas = SchemaArenas::new();
arenas.alloc_simple_type(simple_type_data(NameId(10)));
arenas.alloc_simple_type(simple_type_data(NameId(20)));
arenas.alloc_simple_type(simple_type_data(NameId(30)));
let names: Vec<_> = arenas
.simple_types
.values()
.filter_map(|d| d.name)
.map(|n| n.0)
.collect();
assert_eq!(names.len(), 3);
assert!(names.contains(&10));
assert!(names.contains(&20));
assert!(names.contains(&30));
}
#[test]
fn test_key_with_values() {
let mut arenas = SchemaArenas::new();
let key1 = arenas.alloc_element(element_data(NameId(1), None));
let key2 = arenas.alloc_element(element_data(NameId(2), None));
let pairs: Vec<_> = arenas
.elements
.iter()
.map(|(k, v)| (k, v.name.unwrap().0))
.collect();
assert_eq!(pairs.len(), 2);
assert!(pairs.iter().any(|(k, _)| *k == key1));
assert!(pairs.iter().any(|(k, _)| *k == key2));
}
}