xsd_parser/models/schema/
mod.rs1pub mod xs;
10
11mod namespace;
12mod namespace_prefix;
13mod occurs;
14mod qname;
15
16use std::borrow::Cow;
17use std::collections::btree_map::{BTreeMap, Entry, Iter, IterMut};
18
19use self::xs::Schema;
20
21pub use namespace::Namespace;
22pub use namespace_prefix::NamespacePrefix;
23pub use occurs::{MaxOccurs, MinOccurs};
24pub use qname::QName;
25use url::Url;
26
27#[derive(Default, Debug)]
40pub struct Schemas {
41 schemas: SchemaFiles,
42 namespace_infos: NamespaceInfos,
43
44 known_prefixes: NamespacePrefixes,
45 known_namespaces: Namespaces,
46
47 next_schema_id: usize,
48 next_namespace_id: usize,
49}
50
51#[derive(Debug)]
53pub struct NamespaceInfo {
54 pub prefix: Option<NamespacePrefix>,
56
57 pub namespace: Option<Namespace>,
59
60 pub schemas: Vec<SchemaId>,
62
63 pub module_name: Option<String>,
65}
66
67#[derive(Debug)]
69pub struct SchemaInfo {
70 pub name: Option<String>,
72
73 pub schema: Schema,
75
76 pub location: Option<Url>,
78
79 namespace_id: NamespaceId,
81}
82
83#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
85pub struct SchemaId(pub usize);
86
87#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
89pub struct NamespaceId(pub usize);
90
91pub type SchemaFiles = BTreeMap<SchemaId, SchemaInfo>;
93
94pub type NamespaceInfos = BTreeMap<NamespaceId, NamespaceInfo>;
96
97pub type Namespaces = BTreeMap<Option<Namespace>, NamespaceId>;
99
100pub type NamespacePrefixes = BTreeMap<NamespacePrefix, NamespaceId>;
102
103impl Schemas {
106 pub fn add_schema(
112 &mut self,
113 prefix: Option<NamespacePrefix>,
114 namespace: Option<Namespace>,
115 name: Option<String>,
116 schema: Schema,
117 location: Option<Url>,
118 ) {
119 let schema_id = SchemaId(self.next_schema_id);
120 let (namespace_id, namespace_info) =
121 self.get_or_create_namespace_info_mut(prefix, namespace);
122 namespace_info.schemas.push(schema_id);
123 self.next_schema_id = self.next_schema_id.wrapping_add(1);
124
125 match self.schemas.entry(schema_id) {
126 Entry::Vacant(e) => e.insert(SchemaInfo {
127 name,
128 schema,
129 location,
130 namespace_id,
131 }),
132 Entry::Occupied(_) => crate::unreachable!(),
133 };
134 }
135
136 pub fn get_or_create_namespace_info_mut(
138 &mut self,
139 prefix: Option<NamespacePrefix>,
140 namespace: Option<Namespace>,
141 ) -> (NamespaceId, &mut NamespaceInfo) {
142 let (ns, id) = match self.known_namespaces.entry(namespace) {
143 Entry::Occupied(e) => {
144 let id = *e.get();
145 let ns = self.namespace_infos.get_mut(&id).unwrap();
146
147 (ns, id)
148 }
149 Entry::Vacant(e) => {
150 let id = NamespaceId(self.next_namespace_id);
151 self.next_namespace_id = self.next_namespace_id.wrapping_add(1);
152
153 let namespace = e.key().clone();
154 e.insert(id);
155
156 let ns = match self.namespace_infos.entry(id) {
157 Entry::Vacant(e) => e.insert(NamespaceInfo::new(namespace)),
158 Entry::Occupied(_) => crate::unreachable!(),
159 };
160
161 (ns, id)
162 }
163 };
164
165 if let Some(mut prefix) = prefix {
166 if matches!(self.known_prefixes.get(&prefix), Some(x) if *x != id) {
167 let ext = format!("_{}", id.0);
168 let ext = ext.as_bytes();
169
170 let mut p = prefix.0.into_owned();
171 p.extend_from_slice(ext);
172
173 prefix = NamespacePrefix(Cow::Owned(p));
174 }
175
176 self.known_prefixes.insert(prefix.clone(), id);
177
178 if ns.prefix.is_none() {
179 ns.prefix = Some(prefix);
180 }
181 }
182
183 (id, ns)
184 }
185
186 pub fn schemas(&self) -> Iter<'_, SchemaId, SchemaInfo> {
188 self.schemas.iter()
189 }
190
191 pub fn schemas_mut(&mut self) -> IterMut<'_, SchemaId, SchemaInfo> {
193 self.schemas.iter_mut()
194 }
195
196 pub fn namespaces(&self) -> Iter<'_, NamespaceId, NamespaceInfo> {
199 self.namespace_infos.iter()
200 }
201
202 #[must_use]
205 pub fn get_schema(&self, id: &SchemaId) -> Option<&SchemaInfo> {
206 self.schemas.get(id)
207 }
208
209 #[must_use]
212 pub fn get_schema_mut(&mut self, id: &SchemaId) -> Option<&mut SchemaInfo> {
213 self.schemas.get_mut(id)
214 }
215
216 #[must_use]
219 pub fn get_namespace_info(&self, id: &NamespaceId) -> Option<&NamespaceInfo> {
220 self.namespace_infos.get(id)
221 }
222
223 #[must_use]
226 pub fn get_namespace_info_mut(&mut self, id: &NamespaceId) -> Option<&mut NamespaceInfo> {
227 self.namespace_infos.get_mut(id)
228 }
229
230 #[must_use]
233 pub fn get_namespace_info_by_namespace(
234 &self,
235 ns: &Option<Namespace>,
236 ) -> Option<&NamespaceInfo> {
237 let id = self.resolve_namespace(ns)?;
238
239 self.get_namespace_info(&id)
240 }
241
242 #[must_use]
246 pub fn resolve_prefix(&self, prefix: &NamespacePrefix) -> Option<NamespaceId> {
247 Some(*self.known_prefixes.get(prefix)?)
248 }
249
250 #[must_use]
254 pub fn resolve_namespace(&self, ns: &Option<Namespace>) -> Option<NamespaceId> {
255 Some(*self.known_namespaces.get(ns)?)
256 }
257}
258
259impl NamespaceInfo {
262 #[must_use]
264 pub fn new(namespace: Option<Namespace>) -> Self {
265 Self {
266 prefix: None,
267 namespace,
268 schemas: Vec::new(),
269 module_name: None,
270 }
271 }
272}
273
274impl SchemaInfo {
277 #[must_use]
279 pub fn namespace_id(&self) -> NamespaceId {
280 self.namespace_id
281 }
282}