1use bitflags::bitflags;
9use std::collections::HashMap;
10
11use crate::arenas::SchemaArenas;
12use crate::ids::*;
13use crate::namespace::table::well_known;
14use crate::namespace::NameTable;
15use crate::namespace::QualifiedName;
16use crate::parser::location::{SourceLocation, SourceMapStorage, SourceRef};
17use crate::schema::annotation::Annotation;
18use crate::schema::composition::{
19 ComponentIdentity, ComponentKind, CompositionEdge, DocumentComponentIndex, EffectiveComponent,
20};
21use crate::schema::wildcard::ElementWildcard;
22use crate::types::{BuiltinTypes, XmlTypeCode};
23
24#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
26pub enum XsdVersion {
27 #[default]
28 V1_0,
29 V1_1,
30}
31
32#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
43pub enum RegexCompat {
44 #[default]
46 Strict,
47 LenientMs,
50}
51
52bitflags! {
53 #[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
55 pub struct DerivationSet: u8 {
56 const EXTENSION = 0x01;
57 const RESTRICTION = 0x02;
58 const LIST = 0x04;
59 const UNION = 0x08;
60 const SUBSTITUTION = 0x10;
61
62 const ALL = Self::EXTENSION.bits() | Self::RESTRICTION.bits() |
64 Self::LIST.bits() | Self::UNION.bits() | Self::SUBSTITUTION.bits();
65
66 const ELEMENT_BLOCK = Self::EXTENSION.bits() | Self::RESTRICTION.bits() | Self::SUBSTITUTION.bits();
68 }
69}
70
71impl DerivationSet {
72 pub fn extension() -> Self {
74 Self::EXTENSION
75 }
76
77 pub fn restriction() -> Self {
79 Self::RESTRICTION
80 }
81
82 pub fn contains_extension(&self) -> bool {
84 self.contains(Self::EXTENSION)
85 }
86
87 pub fn contains_restriction(&self) -> bool {
89 self.contains(Self::RESTRICTION)
90 }
91
92 pub fn contains_list(&self) -> bool {
94 self.contains(Self::LIST)
95 }
96
97 pub fn contains_union(&self) -> bool {
99 self.contains(Self::UNION)
100 }
101
102 pub fn contains_substitution(&self) -> bool {
104 self.contains(Self::SUBSTITUTION)
105 }
106
107 pub fn element_block_mask(self) -> Self {
112 self & Self::ELEMENT_BLOCK
113 }
114}
115
116#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
118pub enum FormChoice {
119 #[default]
120 Unqualified,
121 Qualified,
122}
123
124#[derive(Debug)]
129pub struct SchemaSet {
130 pub name_table: NameTable,
132
133 pub source_maps: SourceMapStorage,
135
136 pub documents: Vec<SchemaDocument>,
138
139 pub namespaces: HashMap<Option<NameId>, NamespaceTable>,
141
142 pub xsd_version: XsdVersion,
144
145 pub regex_compatibility: RegexCompat,
147
148 pub arenas: SchemaArenas,
150
151 pub loaded_locations: HashMap<String, DocumentId>,
153
154 pub chameleon_cache: HashMap<(String, NameId), DocumentId>,
159
160 pub composition_edges: Vec<CompositionEdge>,
162
163 pub effective_components: HashMap<ComponentIdentity, EffectiveComponent>,
167
168 builtin_types: Option<BuiltinTypes>,
170
171 pub parsing_errors: Vec<crate::error::SchemaError>,
175}
176
177impl SchemaSet {
178 pub fn new() -> Self {
180 Self::with_version(XsdVersion::V1_0)
181 }
182
183 pub fn xsd10() -> Self {
185 Self::with_version(XsdVersion::V1_0)
186 }
187
188 pub fn xsd11() -> Self {
190 Self::with_version(XsdVersion::V1_1)
191 }
192
193 pub fn with_version(version: XsdVersion) -> Self {
195 let mut set = Self {
196 name_table: NameTable::new(),
197 source_maps: SourceMapStorage::new(),
198 documents: Vec::new(),
199 namespaces: HashMap::new(),
200 xsd_version: version,
201 regex_compatibility: RegexCompat::Strict,
202 arenas: SchemaArenas::new(),
203 loaded_locations: HashMap::new(),
204 chameleon_cache: HashMap::new(),
205 composition_edges: Vec::new(),
206 effective_components: HashMap::new(),
207 builtin_types: None,
208 parsing_errors: Vec::new(),
209 };
210
211 let builtin_types = BuiltinTypes::new(&mut set);
213 set.builtin_types = Some(builtin_types);
214
215 set
216 }
217
218 pub fn is_xsd10(&self) -> bool {
220 self.xsd_version == XsdVersion::V1_0
221 }
222
223 pub fn is_xsd11(&self) -> bool {
225 self.xsd_version == XsdVersion::V1_1
226 }
227
228 pub fn set_regex_compatibility(&mut self, compat: RegexCompat) {
234 self.regex_compatibility = compat;
235 }
236
237 pub fn regex_compatibility(&self) -> RegexCompat {
239 self.regex_compatibility
240 }
241
242 pub fn locate(&self, source: Option<&SourceRef>) -> Option<SourceLocation> {
245 source.and_then(|s| self.source_maps.locate(s))
246 }
247
248 pub fn has_parsing_errors(&self) -> bool {
250 !self.parsing_errors.is_empty()
251 }
252
253 pub fn loaded_schema_locations(&self) -> impl Iterator<Item = &str> {
258 self.loaded_locations.keys().map(|s| s.as_str())
259 }
260
261 pub fn is_loaded(&self, location: &str) -> bool {
263 self.loaded_locations.contains_key(location)
264 }
265
266 pub fn mark_loaded(&mut self, location: String, doc_id: DocumentId) {
268 self.loaded_locations.insert(location, doc_id);
269 }
270
271 pub fn get_or_create_namespace(&mut self, ns: Option<NameId>) -> &mut NamespaceTable {
273 self.namespaces.entry(ns).or_default()
274 }
275
276 pub fn lookup_type(&self, ns: Option<NameId>, name: NameId) -> Option<TypeKey> {
278 self.namespaces.get(&ns)?.types.get(&name).copied()
279 }
280
281 pub fn lookup_element(&self, ns: Option<NameId>, name: NameId) -> Option<ElementKey> {
283 self.namespaces.get(&ns)?.elements.get(&name).copied()
284 }
285
286 pub fn lookup_attribute(&self, ns: Option<NameId>, name: NameId) -> Option<AttributeKey> {
288 self.namespaces.get(&ns)?.attributes.get(&name).copied()
289 }
290
291 pub fn lookup_model_group(&self, ns: Option<NameId>, name: NameId) -> Option<ModelGroupKey> {
293 self.namespaces.get(&ns)?.model_groups.get(&name).copied()
294 }
295
296 pub fn lookup_attribute_group(
298 &self,
299 ns: Option<NameId>,
300 name: NameId,
301 ) -> Option<AttributeGroupKey> {
302 self.namespaces
303 .get(&ns)?
304 .attribute_groups
305 .get(&name)
306 .copied()
307 }
308
309 pub fn lookup_notation(&self, ns: Option<NameId>, name: NameId) -> Option<NotationKey> {
311 self.namespaces.get(&ns)?.notations.get(&name).copied()
312 }
313
314 pub fn builtin_types(&self) -> &BuiltinTypes {
322 self.builtin_types
323 .as_ref()
324 .expect("BuiltinTypes should always be initialized")
325 }
326
327 pub fn get_built_in_simple_type_by_qname(
339 &self,
340 namespace: Option<NameId>,
341 local_name: NameId,
342 ) -> Option<SimpleTypeKey> {
343 if namespace != Some(well_known::XS_NAMESPACE) {
345 return None;
346 }
347 self.builtin_types().get_by_local_name(local_name)
348 }
349
350 pub fn get_built_in_type_by_qname(
354 &self,
355 namespace: Option<NameId>,
356 local_name: NameId,
357 ) -> Option<TypeKey> {
358 if namespace != Some(well_known::XS_NAMESPACE) {
359 return None;
360 }
361
362 if let Some(any_type_name) = self.name_table.get("anyType") {
363 if local_name == any_type_name {
364 return Some(TypeKey::Complex(self.builtin_types().any_type));
365 }
366 }
367
368 self.get_built_in_simple_type_by_qname(namespace, local_name)
369 .map(TypeKey::Simple)
370 }
371
372 pub fn any_type_key(&self) -> ComplexTypeKey {
374 self.builtin_types().any_type
375 }
376
377 pub fn is_any_type(&self, type_key: TypeKey) -> bool {
379 matches!(type_key, TypeKey::Complex(key) if key == self.builtin_types().any_type)
380 }
381
382 pub fn get_built_in_simple_type_by_code(&self, code: XmlTypeCode) -> Option<SimpleTypeKey> {
387 self.builtin_types().get_by_type_code(code)
388 }
389
390 pub fn get_type_code(&self, type_id: SimpleTypeKey) -> Option<XmlTypeCode> {
394 self.builtin_types().get_type_code(type_id)
395 }
396
397 pub fn derives_from(&self, derived: SimpleTypeKey, base: SimpleTypeKey) -> bool {
407 if derived == base {
409 return true;
410 }
411
412 let builtin = self.builtin_types();
414 if builtin.is_builtin(derived) && builtin.is_builtin(base) {
415 return builtin.derives_from(derived, base);
416 }
417
418 let mut current = derived;
420 let mut visited = std::collections::HashSet::new();
421
422 while visited.insert(current) {
423 if let Some(type_def) = self.arenas.simple_types.get(current) {
425 if let Some(crate::ids::TypeKey::Simple(simple_base)) = type_def.resolved_base_type
427 {
428 if simple_base == base {
429 return true;
430 }
431 current = simple_base;
432 continue;
433 }
434 }
435
436 if builtin.is_builtin(current) {
438 if let Some(parent) = builtin.get_base_type(current) {
439 if parent == base {
440 return true;
441 }
442 current = parent;
443 continue;
444 }
445 }
446
447 break;
449 }
450
451 false
452 }
453
454 pub fn is_type_derived_from(
473 &self,
474 derived: TypeKey,
475 base: TypeKey,
476 exclude_methods: DerivationSet,
477 ) -> bool {
478 if derived == base {
480 return true;
481 }
482
483 if self.is_any_type(base) {
492 if exclude_methods.is_empty() {
493 return true;
494 }
495 if let TypeKey::Simple(d) = derived {
496 return self.is_simple_chain_to_any_type_ok(d, exclude_methods);
497 }
498 }
500
501 match (derived, base) {
502 (TypeKey::Simple(d), TypeKey::Simple(b)) => {
504 self.is_simple_type_derived_from(d, b, exclude_methods)
505 }
506
507 (TypeKey::Complex(d), TypeKey::Complex(b)) => {
509 self.is_complex_type_derived_from(d, b, exclude_methods)
510 }
511
512 (TypeKey::Simple(_), TypeKey::Complex(_)) => false,
515
516 (TypeKey::Complex(d), TypeKey::Simple(b)) => {
519 self.is_complex_derived_from_simple(d, b, exclude_methods)
520 }
521 }
522 }
523
524 fn is_simple_chain_to_any_type_ok(
529 &self,
530 derived: SimpleTypeKey,
531 exclude_methods: DerivationSet,
532 ) -> bool {
533 use crate::parser::frames::SimpleTypeVariety;
534
535 let mut current = derived;
536 let mut visited = std::collections::HashSet::new();
537
538 while visited.insert(current) {
539 if let Some(type_def) = self.arenas.simple_types.get(current) {
540 let method_flag = match type_def.variety {
541 SimpleTypeVariety::Atomic => DerivationSet::RESTRICTION,
542 SimpleTypeVariety::List => DerivationSet::LIST,
543 SimpleTypeVariety::Union => DerivationSet::UNION,
544 };
545 if exclude_methods.contains(method_flag) {
546 return false;
547 }
548 if let Some(TypeKey::Simple(simple_base)) = type_def.resolved_base_type {
549 current = simple_base;
550 continue;
551 }
552 }
553 return !exclude_methods.contains(DerivationSet::RESTRICTION);
556 }
557 false
559 }
560
561 fn is_simple_type_derived_from(
567 &self,
568 derived: SimpleTypeKey,
569 base: SimpleTypeKey,
570 exclude_methods: DerivationSet,
571 ) -> bool {
572 use crate::parser::frames::SimpleTypeVariety;
573
574 if derived == base {
576 return true;
577 }
578
579 let builtin = self.builtin_types();
581 let mut current = derived;
582 let mut visited = std::collections::HashSet::new();
583
584 while visited.insert(current) {
585 if let Some(type_def) = self.arenas.simple_types.get(current) {
587 let method_flag = match type_def.variety {
589 SimpleTypeVariety::Atomic => DerivationSet::RESTRICTION,
590 SimpleTypeVariety::List => DerivationSet::LIST,
591 SimpleTypeVariety::Union => DerivationSet::UNION,
592 };
593
594 if exclude_methods.contains(method_flag) {
596 break;
597 }
598
599 if let Some(TypeKey::Simple(simple_base)) = type_def.resolved_base_type {
601 if simple_base == base {
602 return true;
603 }
604 current = simple_base;
605 continue;
606 }
607 }
608
609 if builtin.is_builtin(current) {
611 if exclude_methods.contains(DerivationSet::RESTRICTION) {
613 break;
614 }
615 if let Some(parent) = builtin.get_base_type(current) {
616 if parent == base {
617 return true;
618 }
619 current = parent;
620 continue;
621 }
622 }
623
624 break;
625 }
626
627 if let Some(base_def) = self.arenas.simple_types.get(base) {
630 if base_def.variety == SimpleTypeVariety::Union && base_def.facets.is_empty() {
631 for &member_type_key in &base_def.resolved_member_types {
632 if let TypeKey::Simple(member_key) = member_type_key {
633 if self.is_simple_type_derived_from(derived, member_key, exclude_methods) {
634 return true;
635 }
636 }
637 }
638 }
639 }
640
641 false
642 }
643
644 fn is_complex_type_derived_from(
646 &self,
647 derived: ComplexTypeKey,
648 base: ComplexTypeKey,
649 exclude_methods: DerivationSet,
650 ) -> bool {
651 use crate::parser::frames::DerivationMethod;
652
653 if derived == base {
654 return true;
655 }
656
657 let mut current = derived;
658 let mut visited = std::collections::HashSet::new();
659
660 while visited.insert(current) {
661 if let Some(type_def) = self.arenas.complex_types.get(current) {
662 let method_flag = match type_def.derivation_method {
664 Some(DerivationMethod::Extension) => DerivationSet::EXTENSION,
665 Some(DerivationMethod::Restriction) | None => DerivationSet::RESTRICTION,
666 };
667
668 if exclude_methods.contains(method_flag) {
670 return false;
671 }
672
673 if let Some(TypeKey::Complex(complex_base)) = type_def.resolved_base_type {
675 if complex_base == base {
676 return true;
677 }
678 current = complex_base;
679 continue;
680 }
681
682 return base == self.any_type_key();
686 }
687
688 break;
689 }
690
691 false
692 }
693
694 fn is_complex_derived_from_simple(
696 &self,
697 derived: ComplexTypeKey,
698 base: SimpleTypeKey,
699 exclude_methods: DerivationSet,
700 ) -> bool {
701 use crate::parser::frames::DerivationMethod;
702
703 let mut current = derived;
707 let mut visited = std::collections::HashSet::new();
708
709 while visited.insert(current) {
710 let Some(type_def) = self.arenas.complex_types.get(current) else {
711 break;
712 };
713
714 let method_flag = match type_def.derivation_method {
715 Some(DerivationMethod::Extension) => DerivationSet::EXTENSION,
716 Some(DerivationMethod::Restriction) | None => DerivationSet::RESTRICTION,
717 };
718
719 if exclude_methods.contains(method_flag) {
720 return false;
721 }
722
723 match type_def.resolved_base_type {
724 Some(TypeKey::Simple(simple_base)) => {
725 if simple_base == base {
726 return true;
727 }
728 return self.is_simple_type_derived_from(simple_base, base, exclude_methods);
730 }
731 Some(TypeKey::Complex(complex_base)) => {
732 current = complex_base;
734 }
735 None => break,
736 }
737 }
738
739 false
740 }
741
742 pub fn format_provenance_note(
747 &self,
748 kind: ComponentKind,
749 namespace: Option<NameId>,
750 name: NameId,
751 ) -> String {
752 use crate::schema::composition::CompositionAction;
753
754 let identity = ComponentIdentity {
755 kind,
756 name,
757 namespace,
758 };
759 match self.effective_components.get(&identity) {
760 Some(eff) => match &eff.action {
761 CompositionAction::Redefined { from_doc, replaced } => {
762 let target_uri = replaced
763 .owner_doc
764 .and_then(|id| self.documents.get(id as usize))
765 .map(|d| d.base_uri.as_str())
766 .unwrap_or("unknown");
767 let from_uri = from_doc
768 .and_then(|id| self.documents.get(id as usize))
769 .map(|d| d.base_uri.as_str())
770 .unwrap_or("unknown");
771 format!(" (originally in {}, redefined by {})", target_uri, from_uri)
772 }
773 #[cfg(feature = "xsd11")]
774 CompositionAction::Overridden { from_doc, replaced } => {
775 let target_uri = replaced
776 .owner_doc
777 .and_then(|id| self.documents.get(id as usize))
778 .map(|d| d.base_uri.as_str())
779 .unwrap_or("unknown");
780 let from_uri = from_doc
781 .and_then(|id| self.documents.get(id as usize))
782 .map(|d| d.base_uri.as_str())
783 .unwrap_or("unknown");
784 format!(
785 " (originally in {}, overridden by {})",
786 target_uri, from_uri
787 )
788 }
789 CompositionAction::Included { from_doc } => {
790 let uri = self
791 .documents
792 .get(*from_doc as usize)
793 .map(|d| d.base_uri.as_str())
794 .unwrap_or("unknown");
795 format!(" (included by {})", uri)
796 }
797 CompositionAction::Declared => String::new(),
798 },
799 None => String::new(),
800 }
801 }
802
803 pub fn effective_local_element_namespace(
808 &self,
809 elem_target_namespace: Option<NameId>,
810 elem_form: Option<&str>,
811 source: Option<&SourceRef>,
812 fallback_namespace: Option<NameId>,
813 ) -> Option<NameId> {
814 self.effective_local_namespace(
815 elem_target_namespace,
816 elem_form,
817 source,
818 fallback_namespace,
819 |d| d.element_form_default,
820 )
821 }
822
823 pub fn effective_local_attribute_namespace(
828 &self,
829 attr_target_namespace: Option<NameId>,
830 attr_form: Option<&str>,
831 source: Option<&SourceRef>,
832 fallback_namespace: Option<NameId>,
833 ) -> Option<NameId> {
834 self.effective_local_namespace(
835 attr_target_namespace,
836 attr_form,
837 source,
838 fallback_namespace,
839 |d| d.attribute_form_default,
840 )
841 }
842
843 fn effective_local_namespace(
844 &self,
845 explicit_target_namespace: Option<NameId>,
846 form: Option<&str>,
847 source: Option<&SourceRef>,
848 fallback_namespace: Option<NameId>,
849 form_default: impl Fn(&SchemaDocument) -> FormChoice,
850 ) -> Option<NameId> {
851 if explicit_target_namespace.is_some() {
852 return explicit_target_namespace;
853 }
854 let doc = source.and_then(|s| self.documents.get(s.defaults_doc() as usize));
857 let default_form = doc.map(&form_default).unwrap_or(FormChoice::Unqualified);
858 let target_namespace = doc
859 .map(|d| d.target_namespace)
860 .unwrap_or(fallback_namespace);
861 let resolved_form = match form {
862 Some("qualified") => FormChoice::Qualified,
863 Some("unqualified") => FormChoice::Unqualified,
864 _ => default_form,
865 };
866 match resolved_form {
867 FormChoice::Qualified => target_namespace,
868 FormChoice::Unqualified => None,
869 }
870 }
871}
872
873impl Default for SchemaSet {
874 fn default() -> Self {
875 Self::new()
876 }
877}
878
879#[derive(Debug)]
883pub struct SchemaDocument {
884 pub id: DocumentId,
886
887 pub base_uri: String,
889
890 pub declared_target_namespace: Option<NameId>,
895
896 pub target_namespace: Option<NameId>,
900
901 pub version: Option<String>,
903 pub element_form_default: FormChoice,
904 pub attribute_form_default: FormChoice,
905 pub block_default: DerivationSet,
906 pub final_default: DerivationSet,
907 pub schema_id: Option<String>,
908 pub xml_lang: Option<String>,
909
910 pub default_attributes: Option<QualifiedName>,
912
913 pub xpath_default_namespace: Option<NameId>,
915
916 pub includes: Vec<IncludeDirective>,
918 pub imports: Vec<ImportDirective>,
919 pub redefines: Vec<RedefineDirective>,
920 pub overrides: Vec<OverrideDirective>, pub default_open_content: Option<DefaultOpenContent>,
924
925 pub annotations: Vec<Annotation>,
927
928 pub component_index: DocumentComponentIndex,
932
933 pub source: Option<SourceRef>,
935}
936
937impl SchemaDocument {
938 pub fn is_chameleon(&self) -> bool {
941 self.declared_target_namespace.is_none() && self.target_namespace.is_some()
942 }
943
944 pub fn can_see_namespace(&self, qname_ns: Option<NameId>, name_table: &NameTable) -> bool {
956 if qname_ns.is_none() {
957 return self.declared_target_namespace.is_none()
959 || self.imports.iter().any(|i| i.namespace.is_none());
960 }
961 if qname_ns == self.declared_target_namespace
963 || (self.is_chameleon() && qname_ns == self.target_namespace)
964 {
965 return true;
966 }
967 if qname_ns == Some(well_known::XS_NAMESPACE) || qname_ns == Some(well_known::XSI_NAMESPACE)
969 {
970 return true;
971 }
972 self.imports.iter().any(|i| {
976 i.namespace
977 .as_deref()
978 .and_then(|s| name_table.get(s))
979 .map(|id| Some(id) == qname_ns)
980 .unwrap_or(false)
981 })
982 }
983
984 pub fn new(id: DocumentId, base_uri: String) -> Self {
986 Self {
987 id,
988 base_uri,
989 declared_target_namespace: None,
990 target_namespace: None,
991 version: None,
992 element_form_default: FormChoice::default(),
993 attribute_form_default: FormChoice::default(),
994 block_default: DerivationSet::empty(),
995 final_default: DerivationSet::empty(),
996 schema_id: None,
997 xml_lang: None,
998 default_attributes: None,
999 xpath_default_namespace: None,
1000 includes: Vec::new(),
1001 imports: Vec::new(),
1002 redefines: Vec::new(),
1003 overrides: Vec::new(),
1004 default_open_content: None,
1005 annotations: Vec::new(),
1006 component_index: DocumentComponentIndex::new(),
1007 source: None,
1008 }
1009 }
1010}
1011
1012#[derive(Debug, Default)]
1017pub struct NamespaceTable {
1018 pub types: HashMap<NameId, TypeKey>,
1020 pub elements: HashMap<NameId, ElementKey>,
1022 pub attributes: HashMap<NameId, AttributeKey>,
1024 pub attribute_groups: HashMap<NameId, AttributeGroupKey>,
1026 pub model_groups: HashMap<NameId, ModelGroupKey>,
1028 pub notations: HashMap<NameId, NotationKey>,
1030 pub identity_constraints: HashMap<NameId, IdentityConstraintKey>,
1032}
1033
1034impl NamespaceTable {
1035 pub fn new() -> Self {
1036 Self::default()
1037 }
1038
1039 pub fn register_type(&mut self, name: NameId, key: TypeKey) -> Option<TypeKey> {
1041 self.types.insert(name, key)
1042 }
1043
1044 pub fn register_element(&mut self, name: NameId, key: ElementKey) -> Option<ElementKey> {
1046 self.elements.insert(name, key)
1047 }
1048
1049 pub fn register_attribute(&mut self, name: NameId, key: AttributeKey) -> Option<AttributeKey> {
1051 self.attributes.insert(name, key)
1052 }
1053
1054 pub fn register_model_group(
1056 &mut self,
1057 name: NameId,
1058 key: ModelGroupKey,
1059 ) -> Option<ModelGroupKey> {
1060 self.model_groups.insert(name, key)
1061 }
1062
1063 pub fn register_attribute_group(
1065 &mut self,
1066 name: NameId,
1067 key: AttributeGroupKey,
1068 ) -> Option<AttributeGroupKey> {
1069 self.attribute_groups.insert(name, key)
1070 }
1071
1072 pub fn register_notation(&mut self, name: NameId, key: NotationKey) -> Option<NotationKey> {
1074 self.notations.insert(name, key)
1075 }
1076}
1077
1078#[derive(Debug, Clone)]
1082pub struct IncludeDirective {
1083 pub source: Option<SourceRef>,
1084 pub schema_location: String,
1085 pub resolved_doc_id: Option<DocumentId>,
1086}
1087
1088#[derive(Debug, Clone)]
1090pub struct ImportDirective {
1091 pub source: Option<SourceRef>,
1092 pub namespace: Option<String>,
1093 pub schema_location: Option<String>,
1094 pub resolved_doc_id: Option<DocumentId>,
1095}
1096
1097#[derive(Debug, Clone)]
1099pub struct RedefineDirective {
1100 pub source: Option<SourceRef>,
1101 pub schema_location: String,
1102 pub resolved_doc_id: Option<DocumentId>,
1103 pub simple_types: Vec<SimpleTypeKey>,
1104 pub complex_types: Vec<ComplexTypeKey>,
1105 pub groups: Vec<ModelGroupKey>,
1106 pub attribute_groups: Vec<AttributeGroupKey>,
1107}
1108
1109#[derive(Debug, Clone)]
1111pub struct OverrideDirective {
1112 pub source: Option<SourceRef>,
1113 pub schema_location: String,
1114 pub resolved_doc_id: Option<DocumentId>,
1115 pub components: Vec<OverrideComponent>,
1116}
1117
1118#[derive(Debug, Clone)]
1120pub enum OverrideComponent {
1121 SimpleType(SimpleTypeKey),
1122 ComplexType(ComplexTypeKey),
1123 Group(ModelGroupKey),
1124 AttributeGroup(AttributeGroupKey),
1125 Element(ElementKey),
1126 Attribute(AttributeKey),
1127 Notation(NotationKey),
1128}
1129
1130#[derive(Debug, Clone)]
1132pub struct DefaultOpenContent {
1133 pub source: Option<SourceRef>,
1134 pub applies_to_empty: bool,
1135 pub mode: OpenContentMode,
1136 pub wildcard: Option<ElementWildcard>,
1137}
1138
1139#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
1141pub enum OpenContentMode {
1142 None,
1143 #[default]
1144 Interleave,
1145 Suffix,
1146}
1147
1148impl From<crate::parser::frames::OpenContentMode> for OpenContentMode {
1149 fn from(m: crate::parser::frames::OpenContentMode) -> Self {
1150 use crate::parser::frames::OpenContentMode as Src;
1151 match m {
1152 Src::None => Self::None,
1153 Src::Interleave => Self::Interleave,
1154 Src::Suffix => Self::Suffix,
1155 }
1156 }
1157}
1158
1159#[cfg(test)]
1160mod tests {
1161 use super::*;
1162 use crate::arenas::ComplexTypeDefData;
1163 use crate::parser::frames::ComplexContentResult;
1164
1165 #[test]
1166 fn test_schema_set_creation() {
1167 let set = SchemaSet::new();
1168 assert_eq!(set.xsd_version, XsdVersion::V1_0);
1169 assert!(set.documents.is_empty());
1170 assert!(set
1172 .namespaces
1173 .contains_key(&Some(crate::namespace::table::well_known::XSI_NAMESPACE)));
1174 }
1175
1176 #[test]
1177 fn test_schema_set_with_version() {
1178 let set = SchemaSet::with_version(XsdVersion::V1_1);
1179 assert_eq!(set.xsd_version, XsdVersion::V1_1);
1180 }
1181
1182 #[test]
1183 fn test_schema_set_xsd10() {
1184 let set = SchemaSet::xsd10();
1185 assert_eq!(set.xsd_version, XsdVersion::V1_0);
1186 }
1187
1188 #[test]
1189 fn test_schema_set_xsd11() {
1190 let set = SchemaSet::xsd11();
1191 assert_eq!(set.xsd_version, XsdVersion::V1_1);
1192 }
1193
1194 #[test]
1195 fn test_namespace_table_registration() {
1196 use slotmap::SlotMap;
1197 let mut table = NamespaceTable::new();
1198
1199 let mut dummy_map: SlotMap<SimpleTypeKey, ()> = SlotMap::with_key();
1201 let key1 = dummy_map.insert(());
1202 let key2 = dummy_map.insert(());
1203
1204 let old = table.register_type(NameId(1), TypeKey::Simple(key1));
1206 assert!(old.is_none());
1207
1208 let old = table.register_type(NameId(1), TypeKey::Simple(key2));
1210 assert!(old.is_some());
1211 }
1212
1213 #[test]
1214 fn test_schema_set_load_tracking() {
1215 let mut set = SchemaSet::new();
1216
1217 assert!(!set.is_loaded("test.xsd"));
1218 set.mark_loaded("test.xsd".to_string(), 0);
1219 assert!(set.is_loaded("test.xsd"));
1220 }
1221
1222 #[test]
1223 fn test_derivation_set_flags() {
1224 let mut flags = DerivationSet::empty();
1225 assert!(flags.is_empty());
1226
1227 flags |= DerivationSet::EXTENSION;
1228 assert!(flags.contains(DerivationSet::EXTENSION));
1229 assert!(!flags.contains(DerivationSet::RESTRICTION));
1230
1231 let all = DerivationSet::ALL;
1232 assert!(all.contains(DerivationSet::EXTENSION));
1233 assert!(all.contains(DerivationSet::RESTRICTION));
1234 }
1235
1236 #[test]
1237 fn test_form_choice_default() {
1238 assert_eq!(FormChoice::default(), FormChoice::Unqualified);
1239 }
1240
1241 #[test]
1246 fn test_is_type_derived_from_same_type() {
1247 let set = SchemaSet::new();
1248 let string_key = set.builtin_types().string;
1249
1250 assert!(set.is_type_derived_from(
1252 TypeKey::Simple(string_key),
1253 TypeKey::Simple(string_key),
1254 DerivationSet::empty()
1255 ));
1256 }
1257
1258 #[test]
1259 fn test_is_type_derived_from_direct_derivation() {
1260 let set = SchemaSet::new();
1261 let builtin = set.builtin_types();
1262
1263 assert!(set.is_type_derived_from(
1265 TypeKey::Simple(builtin.normalized_string),
1266 TypeKey::Simple(builtin.string),
1267 DerivationSet::empty()
1268 ));
1269
1270 assert!(set.is_type_derived_from(
1272 TypeKey::Simple(builtin.integer),
1273 TypeKey::Simple(builtin.decimal),
1274 DerivationSet::empty()
1275 ));
1276 }
1277
1278 #[test]
1279 fn test_is_type_derived_from_transitive() {
1280 let set = SchemaSet::new();
1281 let builtin = set.builtin_types();
1282
1283 assert!(set.is_type_derived_from(
1285 TypeKey::Simple(builtin.ncname),
1286 TypeKey::Simple(builtin.string),
1287 DerivationSet::empty()
1288 ));
1289
1290 assert!(set.is_type_derived_from(
1292 TypeKey::Simple(builtin.byte),
1293 TypeKey::Simple(builtin.decimal),
1294 DerivationSet::empty()
1295 ));
1296
1297 assert!(set.is_type_derived_from(
1299 TypeKey::Simple(builtin.id),
1300 TypeKey::Simple(builtin.string),
1301 DerivationSet::empty()
1302 ));
1303 }
1304
1305 #[test]
1306 fn test_is_type_derived_from_not_derived() {
1307 let set = SchemaSet::new();
1308 let builtin = set.builtin_types();
1309
1310 assert!(!set.is_type_derived_from(
1312 TypeKey::Simple(builtin.string),
1313 TypeKey::Simple(builtin.integer),
1314 DerivationSet::empty()
1315 ));
1316
1317 assert!(!set.is_type_derived_from(
1319 TypeKey::Simple(builtin.decimal),
1320 TypeKey::Simple(builtin.integer),
1321 DerivationSet::empty()
1322 ));
1323
1324 assert!(!set.is_type_derived_from(
1326 TypeKey::Simple(builtin.date),
1327 TypeKey::Simple(builtin.duration),
1328 DerivationSet::empty()
1329 ));
1330 }
1331
1332 #[test]
1333 fn test_is_type_derived_from_any_simple_type() {
1334 let set = SchemaSet::new();
1335 let builtin = set.builtin_types();
1336
1337 assert!(set.is_type_derived_from(
1339 TypeKey::Simple(builtin.string),
1340 TypeKey::Simple(builtin.any_simple_type),
1341 DerivationSet::empty()
1342 ));
1343
1344 assert!(set.is_type_derived_from(
1345 TypeKey::Simple(builtin.integer),
1346 TypeKey::Simple(builtin.any_simple_type),
1347 DerivationSet::empty()
1348 ));
1349
1350 assert!(set.is_type_derived_from(
1351 TypeKey::Simple(builtin.byte),
1352 TypeKey::Simple(builtin.any_simple_type),
1353 DerivationSet::empty()
1354 ));
1355 }
1356
1357 #[test]
1358 fn test_is_type_derived_from_any_type() {
1359 let mut set = SchemaSet::new();
1360 let any_type = set.builtin_types().any_type;
1361 let string_type = set.builtin_types().string;
1362
1363 assert!(set.is_type_derived_from(
1364 TypeKey::Simple(string_type),
1365 TypeKey::Complex(any_type),
1366 DerivationSet::empty()
1367 ));
1368
1369 let ct_key = set.arenas.alloc_complex_type(ComplexTypeDefData {
1370 name: None,
1371 target_namespace: None,
1372 base_type: None,
1373 derivation_method: None,
1374 content: ComplexContentResult::Empty,
1375 open_content: None,
1376 attributes: Vec::new(),
1377 attribute_groups: Vec::new(),
1378 attribute_wildcard: None,
1379 mixed: false,
1380 is_abstract: false,
1381 final_derivation: DerivationSet::empty(),
1382 block: DerivationSet::empty(),
1383 default_attributes_apply: true,
1384 id: None,
1385 #[cfg(feature = "xsd11")]
1386 assertions: Vec::new(),
1387 #[cfg(feature = "xsd11")]
1388 xpath_default_namespace: None,
1389 annotation: None,
1390 source: None,
1391 resolved_base_type: None,
1392 resolved_attribute_groups: Vec::new(),
1393 resolved_attributes: Vec::new(),
1394 resolved_content_particle_types: Vec::new(),
1395 resolved_content_particle_elements: Vec::new(),
1396 resolved_simple_content_type: None,
1397 redefine_original: None,
1398 });
1399
1400 assert!(set.is_type_derived_from(
1401 TypeKey::Complex(ct_key),
1402 TypeKey::Complex(any_type),
1403 DerivationSet::empty()
1404 ));
1405 }
1406
1407 #[test]
1408 fn test_is_type_derived_from_exclude_restriction() {
1409 let set = SchemaSet::new();
1410 let builtin = set.builtin_types();
1411
1412 assert!(!set.is_type_derived_from(
1414 TypeKey::Simple(builtin.normalized_string),
1415 TypeKey::Simple(builtin.string),
1416 DerivationSet::RESTRICTION
1417 ));
1418
1419 assert!(set.is_type_derived_from(
1421 TypeKey::Simple(builtin.string),
1422 TypeKey::Simple(builtin.string),
1423 DerivationSet::RESTRICTION
1424 ));
1425 }
1426
1427 #[test]
1428 fn test_is_type_derived_from_list_types() {
1429 let set = SchemaSet::new();
1430 let builtin = set.builtin_types();
1431
1432 assert!(set.is_type_derived_from(
1434 TypeKey::Simple(builtin.nmtokens),
1435 TypeKey::Simple(builtin.any_simple_type),
1436 DerivationSet::empty()
1437 ));
1438
1439 assert!(!set.is_type_derived_from(
1441 TypeKey::Simple(builtin.nmtokens),
1442 TypeKey::Simple(builtin.any_simple_type),
1443 DerivationSet::LIST
1444 ));
1445 }
1446
1447 #[test]
1450 fn test_union_member_derivation_clause_2_2_4() {
1451 use crate::pipeline::load_and_process_schema;
1452
1453 let xsd = r#"<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
1454 <xs:simpleType name="myUnion">
1455 <xs:union memberTypes="xs:float xs:integer"/>
1456 </xs:simpleType>
1457 </xs:schema>"#;
1458
1459 let mut set = SchemaSet::new();
1460 load_and_process_schema(xsd.as_bytes(), "test.xsd", &mut set, None)
1461 .expect("schema should parse");
1462
1463 let integer_key = TypeKey::Simple(set.builtin_types().integer);
1464 let float_key = TypeKey::Simple(set.builtin_types().float);
1465
1466 let union_name = set.name_table.add("myUnion");
1468 let union_key = set
1469 .namespaces
1470 .get(&None)
1471 .unwrap()
1472 .types
1473 .get(&union_name)
1474 .copied()
1475 .expect("myUnion should exist");
1476
1477 assert!(
1479 set.is_type_derived_from(integer_key, union_key, DerivationSet::empty()),
1480 "xs:integer should be derived from union(float, integer) via clause 2.2.4"
1481 );
1482
1483 assert!(
1485 set.is_type_derived_from(float_key, union_key, DerivationSet::empty()),
1486 "xs:float should be derived from union(float, integer) via clause 2.2.4"
1487 );
1488
1489 let string_key = TypeKey::Simple(set.builtin_types().string);
1491 assert!(
1492 !set.is_type_derived_from(string_key, union_key, DerivationSet::empty()),
1493 "xs:string should NOT be derived from union(float, integer)"
1494 );
1495 }
1496
1497 #[test]
1500 fn test_union_member_derivation_transitive() {
1501 use crate::pipeline::load_and_process_schema;
1502
1503 let xsd = r#"<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
1504 <xs:simpleType name="innerUnion">
1505 <xs:union memberTypes="xs:boolean xs:date"/>
1506 </xs:simpleType>
1507 <xs:simpleType name="outerUnion">
1508 <xs:union memberTypes="xs:integer innerUnion"/>
1509 </xs:simpleType>
1510 </xs:schema>"#;
1511
1512 let mut set = SchemaSet::new();
1513 load_and_process_schema(xsd.as_bytes(), "test.xsd", &mut set, None)
1514 .expect("schema should parse");
1515
1516 let outer_name = set.name_table.add("outerUnion");
1517 let outer_key = set
1518 .namespaces
1519 .get(&None)
1520 .unwrap()
1521 .types
1522 .get(&outer_name)
1523 .copied()
1524 .expect("outerUnion should exist");
1525
1526 let bool_key = TypeKey::Simple(set.builtin_types().boolean);
1528 assert!(
1529 set.is_type_derived_from(bool_key, outer_key, DerivationSet::empty()),
1530 "xs:boolean should be transitively derived from outerUnion via innerUnion"
1531 );
1532
1533 let int_key = TypeKey::Simple(set.builtin_types().integer);
1535 assert!(
1536 set.is_type_derived_from(int_key, outer_key, DerivationSet::empty()),
1537 "xs:integer should be derived from outerUnion as direct member"
1538 );
1539 }
1540}