1mod error;
4mod helper;
5mod schema;
6mod state;
7mod variant_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, TypeVariant, 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::variant_builder::VariantBuilder;
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_variant = TypeVariant::Sequence(GroupInfo {
237 any: Some(AnyInfo {
238 min_occurs: Some(0),
239 max_occurs: Some(MaxOccurs::Unbounded),
240 process_contents: Some(ProcessContentsType::Lax),
241 ..Default::default()
242 }),
243 ..Default::default()
244 });
245 let content_type = Type::new(content_variant);
246 self.state
247 .add_type(content_ident.clone(), content_type, true)?;
248
249 let ident = Ident::type_("anyType").with_ns(Some(xs));
251 let variant = TypeVariant::ComplexType(ComplexInfo {
252 content: Some(content_ident),
253 min_occurs: 1,
254 max_occurs: MaxOccurs::Bounded(1),
255 any_attribute: Some(AnyAttributeInfo {
256 process_contents: Some(ProcessContentsType::Lax),
257 ..Default::default()
258 }),
259 ..Default::default()
260 });
261 let type_ = Type::new(variant);
262 self.state.add_type(ident, type_, true)?;
263
264 Ok(self)
265 }
266
267 #[instrument(err, level = "trace", skip(self))]
274 pub fn finish(mut self) -> Result<Types, Error> {
275 for (id, info) in self.schemas.namespaces() {
276 let module = Module {
277 name: info
278 .prefix
279 .as_ref()
280 .map(|prefix| Name::new(prefix.to_string())),
281 namespace: info.namespace.clone(),
282 };
283
284 self.state.types.modules.insert(*id, module);
285 }
286
287 for (_id, schema) in self.schemas.schemas() {
288 SchemaInterpreter::process(&mut self.state, schema, self.schemas)?;
289 }
290
291 Ok(self.state.types)
292 }
293}