xsd_schema/document/
type_remap.rs1use crate::ids::{AttributeKey, ElementKey, SimpleTypeKey, TypeKey};
8use crate::validation::info::ContentType;
9
10use super::error::BufferDocumentError;
11
12#[derive(Clone, Copy, Debug, PartialEq, Eq)]
16pub struct NodeSchemaBinding {
17 pub type_key: TypeKey,
18 pub element_decl: Option<ElementKey>,
19 pub attribute_decl: Option<AttributeKey>,
20 pub content_type: Option<ContentType>,
21}
22
23pub struct BindingRemapTable {
28 entries: Vec<NodeSchemaBinding>,
30}
31
32const MAX_ENTRIES: u32 = (1 << 20) - 1;
34
35impl BindingRemapTable {
36 pub fn new() -> Self {
38 use slotmap::Key;
39
40 let sentinel = NodeSchemaBinding {
42 type_key: TypeKey::Simple(SimpleTypeKey::null()),
43 element_decl: None,
44 attribute_decl: None,
45 content_type: None,
46 };
47
48 Self {
49 entries: vec![sentinel],
50 }
51 }
52
53 pub fn register(&mut self, binding: NodeSchemaBinding) -> Result<u32, BufferDocumentError> {
60 for (i, entry) in self.entries.iter().enumerate().skip(1) {
62 if *entry == binding {
63 return Ok(i as u32);
64 }
65 }
66 let idx = self.entries.len() as u32;
67 if idx > MAX_ENTRIES {
68 return Err(BufferDocumentError::Overflow);
69 }
70 self.entries.push(binding);
71 Ok(idx)
72 }
73
74 pub fn get(&self, idx: u32) -> Option<&NodeSchemaBinding> {
76 if idx == 0 {
77 return None;
78 }
79 self.entries.get(idx as usize)
80 }
81}
82
83impl Default for BindingRemapTable {
84 fn default() -> Self {
85 Self::new()
86 }
87}
88
89#[cfg(test)]
90mod tests {
91 use super::*;
92 use crate::ids::{ComplexTypeKey, SimpleTypeKey, TypeKey};
93 use slotmap::SlotMap;
94
95 fn make_simple_key() -> SimpleTypeKey {
97 let mut sm = SlotMap::with_key();
98 sm.insert(())
99 }
100
101 fn make_complex_key() -> ComplexTypeKey {
103 let mut sm = SlotMap::with_key();
104 sm.insert(())
105 }
106
107 fn binding_from_type(tk: TypeKey) -> NodeSchemaBinding {
109 NodeSchemaBinding {
110 type_key: tk,
111 element_decl: None,
112 attribute_decl: None,
113 content_type: None,
114 }
115 }
116
117 #[test]
118 fn index_zero_returns_none() {
119 let table = BindingRemapTable::new();
120 assert!(table.get(0).is_none());
121 }
122
123 #[test]
124 fn register_and_get_simple() {
125 let mut table = BindingRemapTable::new();
126 let sk = make_simple_key();
127 let binding = binding_from_type(TypeKey::Simple(sk));
128
129 let idx = table.register(binding).unwrap();
130 assert_eq!(idx, 1);
131 assert_eq!(table.get(idx), Some(&binding));
132 }
133
134 #[test]
135 fn register_and_get_complex() {
136 let mut table = BindingRemapTable::new();
137 let ck = make_complex_key();
138 let binding = binding_from_type(TypeKey::Complex(ck));
139
140 let idx = table.register(binding).unwrap();
141 assert_eq!(idx, 1);
142 assert_eq!(table.get(idx), Some(&binding));
143 }
144
145 #[test]
146 fn register_same_binding_twice_returns_same_index() {
147 let mut table = BindingRemapTable::new();
148 let sk = make_simple_key();
149 let binding = binding_from_type(TypeKey::Simple(sk));
150
151 let idx1 = table.register(binding).unwrap();
152 let idx2 = table.register(binding).unwrap();
153 assert_eq!(idx1, idx2);
154 }
155
156 #[test]
157 fn simple_vs_complex_preserved() {
158 let mut table = BindingRemapTable::new();
159 let sk = make_simple_key();
160 let ck = make_complex_key();
161 let b_s = binding_from_type(TypeKey::Simple(sk));
162 let b_c = binding_from_type(TypeKey::Complex(ck));
163
164 let idx_s = table.register(b_s).unwrap();
165 let idx_c = table.register(b_c).unwrap();
166 assert_ne!(idx_s, idx_c);
167
168 match table.get(idx_s).unwrap().type_key {
169 TypeKey::Simple(_) => {}
170 other => panic!("Expected Simple, got {other:?}"),
171 }
172 match table.get(idx_c).unwrap().type_key {
173 TypeKey::Complex(_) => {}
174 other => panic!("Expected Complex, got {other:?}"),
175 }
176 }
177
178 #[test]
179 fn multiple_distinct_bindings_distinct_indices() {
180 let mut table = BindingRemapTable::new();
181
182 let mut sm: SlotMap<SimpleTypeKey, ()> = SlotMap::with_key();
183 let mut indices = Vec::new();
184 for _ in 0..10 {
185 let sk = sm.insert(());
186 indices.push(
187 table
188 .register(binding_from_type(TypeKey::Simple(sk)))
189 .unwrap(),
190 );
191 }
192
193 let unique: std::collections::HashSet<_> = indices.iter().collect();
194 assert_eq!(unique.len(), indices.len());
195 }
196
197 #[test]
198 fn get_out_of_range_returns_none() {
199 let table = BindingRemapTable::new();
200 assert!(table.get(999).is_none());
201 }
202
203 #[test]
204 fn same_type_different_decl_are_distinct() {
205 let mut table = BindingRemapTable::new();
206 let sk = make_simple_key();
207 let tk = TypeKey::Simple(sk);
208
209 let mut sm_elem: SlotMap<ElementKey, ()> = SlotMap::with_key();
210 let ek1 = sm_elem.insert(());
211 let ek2 = sm_elem.insert(());
212
213 let b1 = NodeSchemaBinding {
214 type_key: tk,
215 element_decl: Some(ek1),
216 attribute_decl: None,
217 content_type: None,
218 };
219 let b2 = NodeSchemaBinding {
220 type_key: tk,
221 element_decl: Some(ek2),
222 attribute_decl: None,
223 content_type: None,
224 };
225
226 let idx1 = table.register(b1).unwrap();
227 let idx2 = table.register(b2).unwrap();
228 assert_ne!(
229 idx1, idx2,
230 "same type with different element_decl must get distinct indices"
231 );
232 assert_eq!(table.get(idx1), Some(&b1));
233 assert_eq!(table.get(idx2), Some(&b2));
234 }
235}