1mod error;
4mod helper;
5mod schema;
6mod state;
7mod type_builder;
8
9use std::fmt::Debug;
10
11use crate::config::Namespace;
12use crate::schema::xs::ProcessContentsType;
13use crate::schema::{MaxOccurs, Schemas};
14use crate::types::{
15 AnyAttributeInfo, AnyInfo, BuildInInfo, ComplexInfo, GroupInfo, Ident, Module, Name,
16 ReferenceInfo, Type, Types,
17};
18
19pub use error::Error;
20use tracing::instrument;
21
22use self::helper::{NameExtend, NameFallback, NameUnwrap};
23use self::schema::SchemaInterpreter;
24use self::state::{Node, State};
25use self::type_builder::TypeBuilder;
26
27#[must_use]
33#[derive(Debug)]
34pub struct Interpreter<'a> {
35 state: State<'a>,
36 schemas: &'a Schemas,
37}
38
39impl<'a> Interpreter<'a> {
40 pub fn new(schemas: &'a Schemas) -> Self {
42 let state = State::default();
43
44 Self { state, schemas }
45 }
46
47 #[instrument(err, level = "trace", skip(self))]
54 pub fn with_type<I, T>(mut self, ident: I, type_: T) -> Result<Self, Error>
55 where
56 I: Into<Ident> + Debug,
57 T: Into<Type> + Debug,
58 {
59 self.state.add_type(ident, type_, true)?;
60
61 Ok(self)
62 }
63
64 #[instrument(err, level = "trace", skip(self))]
72 pub fn with_typedef<I, T>(mut self, ident: I, type_: T) -> Result<Self, Error>
73 where
74 I: Into<Ident> + Debug,
75 T: Into<Ident> + Debug,
76 {
77 self.state
78 .add_type(ident, ReferenceInfo::new(type_), true)?;
79
80 Ok(self)
81 }
82
83 #[instrument(err, level = "trace", skip(self))]
89 pub fn with_buildin_types(mut self) -> Result<Self, Error> {
90 macro_rules! add {
91 ($ident:ident, $type:ident) => {
92 self.state
93 .add_type(Ident::$ident, BuildInInfo::$type, true)?;
94 };
95 }
96
97 add!(U8, U8);
98 add!(U16, U16);
99 add!(U32, U32);
100 add!(U64, U64);
101 add!(U128, U128);
102 add!(USIZE, Usize);
103
104 add!(I8, I8);
105 add!(I16, I16);
106 add!(I32, I32);
107 add!(I64, I64);
108 add!(I128, I128);
109 add!(ISIZE, Isize);
110
111 add!(F32, F32);
112 add!(F64, F64);
113
114 add!(BOOL, Bool);
115 add!(STRING, String);
116
117 Ok(self)
118 }
119
120 #[instrument(err, level = "trace", skip(self))]
127 pub fn with_default_typedefs(mut self) -> Result<Self, Error> {
128 let xs = self
129 .schemas
130 .resolve_namespace(&Some(Namespace::XS))
131 .ok_or_else(|| Error::UnknownNamespace(Namespace::XS.clone()))?;
132
133 macro_rules! add {
134 ($ns:ident, $src:expr, $dst:ident) => {
135 self.state.add_type(
136 Ident::type_($src).with_ns(Some($ns)),
137 ReferenceInfo::new(Ident::$dst),
138 true,
139 )?;
140 };
141 }
142 macro_rules! add_list {
143 ($ns:ident, $src:expr, $dst:ident) => {
144 self.state.add_type(
145 Ident::type_($src).with_ns(Some($ns)),
146 ReferenceInfo::new(Ident::$dst)
147 .min_occurs(0)
148 .max_occurs(MaxOccurs::Unbounded),
149 true,
150 )?;
151 };
152 }
153
154 add!(xs, "string", STRING);
157 add!(xs, "boolean", BOOL);
158 add!(xs, "decimal", F64);
159 add!(xs, "float", F32);
160 add!(xs, "double", F64);
161
162 add!(xs, "duration", STRING);
165 add!(xs, "dateTime", STRING);
166 add!(xs, "time", STRING);
167 add!(xs, "date", STRING);
168 add!(xs, "gYearMonth", STRING);
169 add!(xs, "gYear", STRING);
170 add!(xs, "gMonthDay", STRING);
171 add!(xs, "gMonth", STRING);
172 add!(xs, "gDay", STRING);
173
174 add!(xs, "hexBinary", STRING);
177 add!(xs, "base64Binary", STRING);
178
179 add!(xs, "anyURI", STRING);
182 add!(xs, "QName", STRING);
183 add!(xs, "NOTATION", STRING);
184
185 add!(xs, "long", I64);
188 add!(xs, "int", I32);
189 add!(xs, "integer", I32);
190 add!(xs, "short", I16);
191 add!(xs, "byte", I8);
192 add!(xs, "negativeInteger", ISIZE);
193 add!(xs, "nonPositiveInteger", ISIZE);
194
195 add!(xs, "unsignedLong", U64);
196 add!(xs, "unsignedInt", U32);
197 add!(xs, "unsignedShort", U16);
198 add!(xs, "unsignedByte", U8);
199 add!(xs, "positiveInteger", USIZE);
200 add!(xs, "nonNegativeInteger", USIZE);
201
202 add!(xs, "normalizedString", STRING);
205 add!(xs, "token", STRING);
206 add!(xs, "language", STRING);
207 add!(xs, "NMTOKEN", STRING);
208 add!(xs, "Name", STRING);
209 add!(xs, "NCName", STRING);
210 add!(xs, "ID", STRING);
211 add!(xs, "IDREF", STRING);
212
213 add_list!(xs, "NMTOKENS", STRING);
214 add_list!(xs, "IDREFS", STRING);
215 add_list!(xs, "ENTITY", STRING);
216 add_list!(xs, "ENTITIES", STRING);
217
218 Ok(self)
219 }
220
221 #[instrument(err, level = "trace", skip(self))]
227 pub fn with_xs_any_type(mut self) -> Result<Self, Error> {
228 let xs = self
229 .schemas
230 .resolve_namespace(&Some(Namespace::XS))
231 .ok_or_else(|| Error::UnknownNamespace(Namespace::XS.clone()))?;
232
233 let content_name = self.state.make_unnamed();
235 let content_ident = Ident::new(content_name).with_ns(Some(xs));
236 let content_type = Type::Sequence(GroupInfo {
237 any: Some(AnyInfo {
238 process_contents: Some(ProcessContentsType::Lax),
239 ..Default::default()
240 }),
241 ..Default::default()
242 });
243 self.state
244 .add_type(content_ident.clone(), content_type, true)?;
245
246 let ident = Ident::type_("anyType").with_ns(Some(xs));
248 let type_ = Type::ComplexType(ComplexInfo {
249 content: Some(content_ident),
250 min_occurs: 0,
251 max_occurs: MaxOccurs::Unbounded,
252 any_attribute: Some(AnyAttributeInfo {
253 process_contents: Some(ProcessContentsType::Lax),
254 ..Default::default()
255 }),
256 ..Default::default()
257 });
258 self.state.add_type(ident, type_, true)?;
259
260 Ok(self)
261 }
262
263 #[instrument(err, level = "trace", skip(self))]
270 pub fn finish(mut self) -> Result<Types, Error> {
271 for (id, info) in self.schemas.namespaces() {
272 let module = Module {
273 name: info
274 .prefix
275 .as_ref()
276 .map(|prefix| Name::new(prefix.to_string())),
277 namespace: info.namespace.clone(),
278 };
279
280 self.state.types.modules.insert(*id, module);
281 }
282
283 for (_id, schema) in self.schemas.schemas() {
284 SchemaInterpreter::process(&mut self.state, schema, self.schemas)?;
285 }
286
287 Ok(self.state.types)
288 }
289}