xsd-schema 0.1.0

XML Schema (XSD 1.0/1.1) validator with PSVI and a built-in XPath 2.0 engine
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
//! Arena storage for schema components
//!
//! All schema components are stored in arenas to avoid reference cycles.
//! Each component type has its own SlotMap with typed keys for type safety.
//!
//! Uses slotmap for O(1) insertion, lookup, and removal with generation tracking.

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;

// Forward declarations for types that will be defined later
// These are placeholders until we define the actual types

/// `src-resolve` reference miss deferred from schema compilation to
/// instance validation. The schema compiles; the error fires only if the
/// declaration carrying this payload is selected for validating an
/// instance. Used in XSD 1.0 for explicit element `type` and
/// `xs:list itemType` references whose target component does not exist.
#[derive(Debug, Clone)]
pub struct DeferredSrcResolve {
    pub message: String,
    pub source: Option<SourceRef>,
}

/// Placeholder for SimpleTypeDef (defined in types/simple.rs)
#[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>,

    // Resolved references (populated after reference resolution phase)
    /// Resolved base type key (for restriction derivation)
    pub resolved_base_type: Option<TypeKey>,
    /// Resolved item type key (for list types)
    pub resolved_item_type: Option<TypeKey>,
    /// Resolved member type keys (for union types)
    pub resolved_member_types: Vec<TypeKey>,

    /// Original simple type key before redefine (for base-type resolution)
    pub redefine_original: Option<SimpleTypeKey>,

    /// Deferred `src-resolve` error for an `xs:list itemType` whose target
    /// is missing. Reported when this list type is used for validation.
    pub deferred_item_type_error: Option<DeferredSrcResolve>,
}

/// Resolved attribute use - stores resolved keys for attribute use references
#[derive(Debug, Clone)]
pub struct ResolvedAttributeUse {
    /// Resolved type key (from type_ref or inline type)
    pub resolved_type: Option<TypeKey>,
    /// Resolved attribute reference (for attribute refs)
    pub resolved_ref: Option<AttributeKey>,
}

/// Placeholder for ComplexTypeDef (defined in types/complex.rs)
#[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>,

    // Resolved references (populated after reference resolution phase)
    /// Resolved base type key (for extension/restriction derivation)
    pub resolved_base_type: Option<TypeKey>,
    /// Resolved attribute group keys
    pub resolved_attribute_groups: Vec<AttributeGroupKey>,
    /// Resolved attribute uses (parallel to attributes vec)
    pub resolved_attributes: Vec<ResolvedAttributeUse>,
    /// Resolved inline types for content particle elements (flat depth-first element order)
    pub resolved_content_particle_types: Vec<Option<TypeKey>>,
    /// Resolved element keys for local elements in content particles (flat depth-first element order)
    pub resolved_content_particle_elements: Vec<Option<ElementKey>>,
    /// Resolved inline simpleType inside simpleContent/restriction
    /// (§3.4.2.2 clause 1.1 — the B simple type definition).
    /// Only present when simpleContent has an explicit inline `<xs:simpleType>`.
    pub resolved_simple_content_type: Option<TypeKey>,

    /// Original complex type key before redefine (for base-type resolution)
    pub redefine_original: Option<ComplexTypeKey>,
}

/// Placeholder for ElementDecl (defined in schema/decl.rs)
#[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>,
    /// XSD 1.1: pending identity constraint @ref references (resolved in resolve_all_references)
    pub pending_ic_refs: Vec<(IdentityKind, QNameRef, Option<SourceRef>)>,
    pub annotation: Option<Annotation>,
    pub source: Option<SourceRef>,

    // Resolved references (populated after reference resolution phase)
    /// Resolved type key (from type_ref or inline_type)
    pub resolved_type: Option<TypeKey>,
    /// Resolved element reference (for element refs)
    pub resolved_ref: Option<ElementKey>,
    /// Resolved substitution group head elements
    pub resolved_substitution_groups: Vec<ElementKey>,

    /// Deferred `src-resolve` error for an explicit `type` attribute whose
    /// target is missing. Reported when this element declaration is
    /// selected for validation, before any `xs:anyType` fallback.
    pub deferred_type_error: Option<DeferredSrcResolve>,
}

/// Placeholder for AttributeDecl (defined in schema/decl.rs)
#[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>,

    // Resolved references (populated after reference resolution phase)
    /// Resolved type key (from type_ref or inline_type)
    pub resolved_type: Option<TypeKey>,
    /// Resolved attribute reference (for attribute refs)
    pub resolved_ref: Option<AttributeKey>,
}

/// Placeholder for AttributeGroup (defined in schema/group.rs)
#[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>,

    // Resolved references (populated after reference resolution phase)
    /// Resolved attribute group reference (for attributeGroup refs)
    pub resolved_ref: Option<AttributeGroupKey>,
    /// Resolved nested attribute group keys
    pub resolved_attribute_groups: Vec<AttributeGroupKey>,
    /// Resolved attribute uses (parallel to attributes vec)
    pub resolved_attributes: Vec<ResolvedAttributeUse>,

    /// Original attribute group key before redefine (for self-reference resolution)
    pub redefine_original: Option<AttributeGroupKey>,
    /// When this attribute group is a zero-self-reference redefine, the
    /// deferred §src-redefine 7.2.2 restriction check must verify it is a
    /// valid restriction of `redefine_original` after reference resolution
    /// completes. `false` for every non-redefine construction site.
    pub redefine_requires_restriction_check: bool,
}

/// Resolved particle term - stores resolved keys for particle references
#[derive(Debug, Clone)]
pub enum ResolvedParticleTerm {
    /// Element with resolved type and ref
    Element {
        resolved_type: Option<TypeKey>,
        resolved_ref: Option<ElementKey>,
    },
    /// Group with resolved ref
    Group { resolved_ref: Option<ModelGroupKey> },
    /// Wildcard (no resolution needed)
    Any,
}

/// Placeholder for ModelGroup (defined in schema/group.rs)
#[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>,

    // Resolved references (populated after reference resolution phase)
    /// Resolved model group reference (for group refs)
    pub resolved_ref: Option<ModelGroupKey>,
    /// Resolved particle terms (parallel to particles vec)
    pub resolved_particles: Vec<ResolvedParticleTerm>,
    /// Flat depth-first indexed resolved types for all particles (including nested inline groups)
    pub resolved_particle_types: Vec<Option<TypeKey>>,
    /// Flat depth-first indexed resolved element keys for all particles (including nested inline groups)
    pub resolved_particle_elements: Vec<Option<ElementKey>>,

    /// Original model group key before redefine (for self-reference resolution)
    pub redefine_original: Option<ModelGroupKey>,
    /// When this model group is a zero-self-reference redefine, the deferred
    /// §src-redefine 6.2.2 restriction check must verify it is a valid
    /// restriction of `redefine_original` after reference resolution
    /// completes. `false` for every non-redefine construction site.
    pub redefine_requires_restriction_check: bool,
}

/// Placeholder for Notation (defined in schema/decl.rs)
#[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>,
}

/// Identity constraint (key, unique, keyref) stored in the arena
#[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>,
}

/// Arena storage for all schema component types
///
/// Components are stored in type-specific SlotMaps and accessed via typed keys.
/// This approach avoids reference cycles and provides O(1) access with generation tracking.
#[derive(Debug, Default)]
pub struct SchemaArenas {
    /// Simple type definitions
    pub simple_types: SlotMap<SimpleTypeKey, SimpleTypeDefData>,
    /// Complex type definitions
    pub complex_types: SlotMap<ComplexTypeKey, ComplexTypeDefData>,
    /// Element declarations
    pub elements: SlotMap<ElementKey, ElementDeclData>,
    /// Attribute declarations
    pub attributes: SlotMap<AttributeKey, AttributeDeclData>,
    /// Attribute groups
    pub attribute_groups: SlotMap<AttributeGroupKey, AttributeGroupData>,
    /// Named model groups
    pub model_groups: SlotMap<ModelGroupKey, ModelGroupData>,
    /// Notations
    pub notations: SlotMap<NotationKey, NotationData>,
    /// Identity constraints
    pub identity_constraints: SlotMap<IdentityConstraintKey, IdentityConstraintData>,
}

impl SchemaArenas {
    /// Create new empty arenas
    pub fn new() -> Self {
        Self::default()
    }

    // Simple types
    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)
    }

    // Complex types
    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)
    }

    // Elements
    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)
    }

    // Attributes
    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)
    }

    // Attribute groups
    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)
    }

    // Model groups
    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)
    }

    // Notations
    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)
    }

    // Identity constraints
    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 references
            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 references
            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)));

        // Modify through mutable reference
        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));

        // Iterate with keys
        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));
    }
}