1pub mod xs;
4
5mod namespace;
6mod namespace_prefix;
7mod occurs;
8mod qname;
9
10use std::borrow::Cow;
11use std::collections::btree_map::{BTreeMap, Entry, Iter};
12
13use self::xs::Schema;
14
15pub use namespace::Namespace;
16pub use namespace_prefix::NamespacePrefix;
17pub use occurs::{MaxOccurs, MinOccurs};
18pub use qname::QName;
19
20#[derive(Default, Debug)]
26pub struct Schemas {
27 schemas: SchemaFiles,
28 namespace_infos: NamespaceInfos,
29
30 known_prefixes: NamespacePrefixes,
31 known_namespaces: Namespaces,
32
33 next_schema_id: usize,
34 next_namespace_id: usize,
35}
36
37#[derive(Debug)]
39pub struct NamespaceInfo {
40 pub prefix: Option<NamespacePrefix>,
42
43 pub namespace: Option<Namespace>,
45
46 pub schemas: Vec<SchemaId>,
48}
49
50#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
52pub struct SchemaId(pub usize);
53
54#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
56pub struct NamespaceId(pub usize);
57
58pub type SchemaFiles = BTreeMap<SchemaId, Schema>;
60
61pub type NamespaceInfos = BTreeMap<NamespaceId, NamespaceInfo>;
63
64pub type Namespaces = BTreeMap<Option<Namespace>, NamespaceId>;
66
67pub type NamespacePrefixes = BTreeMap<NamespacePrefix, NamespaceId>;
69
70impl Schemas {
73 pub fn add_schema(
79 &mut self,
80 prefix: Option<NamespacePrefix>,
81 namespace: Option<Namespace>,
82 schema: Schema,
83 ) {
84 let schema_id = SchemaId(self.next_schema_id);
85 let schema_info = self.get_or_create_namespace_info_mut(prefix, namespace);
86 schema_info.schemas.push(schema_id);
87 self.next_schema_id = self.next_schema_id.wrapping_add(1);
88
89 match self.schemas.entry(schema_id) {
90 Entry::Vacant(e) => e.insert(schema),
91 Entry::Occupied(_) => crate::unreachable!(),
92 };
93 }
94
95 pub fn get_or_create_namespace_info_mut(
97 &mut self,
98 prefix: Option<NamespacePrefix>,
99 namespace: Option<Namespace>,
100 ) -> &mut NamespaceInfo {
101 let (ns, id) = match self.known_namespaces.entry(namespace) {
102 Entry::Occupied(e) => {
103 let id = *e.get();
104 let ns = self.namespace_infos.get_mut(&id).unwrap();
105
106 (ns, id)
107 }
108 Entry::Vacant(e) => {
109 let id = NamespaceId(self.next_namespace_id);
110 self.next_namespace_id = self.next_namespace_id.wrapping_add(1);
111
112 let namespace = e.key().clone();
113 e.insert(id);
114
115 let ns = match self.namespace_infos.entry(id) {
116 Entry::Vacant(e) => e.insert(NamespaceInfo::new(namespace)),
117 Entry::Occupied(_) => crate::unreachable!(),
118 };
119
120 (ns, id)
121 }
122 };
123
124 if let Some(mut prefix) = prefix {
125 if matches!(self.known_prefixes.get(&prefix), Some(x) if *x != id) {
126 let ext = format!("_{}", id.0);
127 let ext = ext.as_bytes();
128
129 let mut p = prefix.0.into_owned();
130 p.extend_from_slice(ext);
131
132 prefix = NamespacePrefix(Cow::Owned(p));
133 }
134
135 self.known_prefixes.insert(prefix.clone(), id);
136
137 if ns.prefix.is_none() {
138 ns.prefix = Some(prefix);
139 }
140 }
141
142 ns
143 }
144
145 pub fn schemas(&self) -> Iter<'_, SchemaId, Schema> {
147 self.schemas.iter()
148 }
149
150 pub fn namespaces(&self) -> Iter<'_, NamespaceId, NamespaceInfo> {
153 self.namespace_infos.iter()
154 }
155
156 #[must_use]
159 pub fn get_schema(&self, id: &SchemaId) -> Option<&Schema> {
160 self.schemas.get(id)
161 }
162
163 #[must_use]
166 pub fn get_namespace_info(&self, id: &NamespaceId) -> Option<&NamespaceInfo> {
167 self.namespace_infos.get(id)
168 }
169
170 #[must_use]
173 pub fn get_namespace_info_by_namespace(
174 &self,
175 ns: &Option<Namespace>,
176 ) -> Option<&NamespaceInfo> {
177 let id = self.resolve_namespace(ns)?;
178
179 self.get_namespace_info(&id)
180 }
181
182 #[must_use]
186 pub fn resolve_prefix(&self, prefix: &NamespacePrefix) -> Option<NamespaceId> {
187 Some(*self.known_prefixes.get(prefix)?)
188 }
189
190 #[must_use]
194 pub fn resolve_namespace(&self, ns: &Option<Namespace>) -> Option<NamespaceId> {
195 Some(*self.known_namespaces.get(ns)?)
196 }
197}
198
199impl NamespaceInfo {
202 #[must_use]
204 pub fn new(namespace: Option<Namespace>) -> Self {
205 Self {
206 prefix: None,
207 namespace,
208 schemas: Vec::new(),
209 }
210 }
211}