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