1mod data;
4mod error;
5mod helper;
6mod misc;
7mod renderer;
8
9use std::collections::{BTreeMap, HashSet, VecDeque};
10use std::fmt::Display;
11
12use proc_macro2::{Ident as Ident2, TokenStream};
13use quote::{format_ident, quote};
14use tracing::instrument;
15
16use crate::types::{Ident, IdentType, Type, Types};
17
18pub use self::error::Error;
19pub use self::misc::{BoxFlags, ContentMode, GenerateFlags, SerdeSupport, TypedefMode};
20
21use self::data::TypeData;
22use self::helper::Walk;
23use self::misc::{
24 format_module, format_type_ident, make_type_name, DynTypeTraits, Module, Modules, PendingType,
25 StateFlags, TraitInfos, TypeRef,
26};
27
28#[must_use]
30#[derive(Debug)]
31pub struct Generator<'types> {
32 types: &'types Types,
33
34 cache: BTreeMap<Ident, TypeRef>,
36 traits: Option<TraitInfos>,
37 pending: VecDeque<PendingType<'types>>,
38
39 modules: Modules,
41
42 derive: Vec<Ident2>,
44 postfixes: [String; 8],
45 box_flags: BoxFlags,
46 content_mode: ContentMode,
47 typedef_mode: TypedefMode,
48 serde_support: SerdeSupport,
49 generate_flags: GenerateFlags,
50 dyn_type_traits: DynTypeTraits,
51 xsd_parser_crate: Ident2,
52}
53
54impl<'types> Generator<'types> {
57 pub fn new(types: &'types Types) -> Self {
59 Self {
60 types,
61
62 cache: BTreeMap::new(),
63 traits: None,
64 pending: VecDeque::new(),
65 modules: Modules::default(),
66
67 derive: vec![format_ident!("Debug"), format_ident!("Clone")],
68 postfixes: [
69 String::from("Type"), String::new(), String::from("ElementType"), String::new(), String::new(), String::new(), String::new(), String::new(), ],
78 box_flags: BoxFlags::AUTO,
79 content_mode: ContentMode::Auto,
80 typedef_mode: TypedefMode::Auto,
81 serde_support: SerdeSupport::None,
82 generate_flags: GenerateFlags::empty(),
83 dyn_type_traits: DynTypeTraits::Auto,
84 xsd_parser_crate: format_ident!("xsd_parser"),
85 }
86 }
87
88 pub fn xsd_parser_crate<S: Display>(mut self, value: S) -> Self {
91 self.xsd_parser_crate = format_ident!("{value}");
92
93 self
94 }
95
96 pub fn derive<I>(mut self, value: I) -> Self
107 where
108 I: IntoIterator,
109 I::Item: Display,
110 {
111 self.derive = value.into_iter().map(|x| format_ident!("{x}")).collect();
112
113 self
114 }
115
116 pub fn dyn_type_traits<I>(mut self, value: I) -> Self
127 where
128 I: IntoIterator,
129 I::Item: Into<String>,
130 {
131 fn parse_path(s: &str) -> TokenStream {
132 let parts = s.split("::").map(|x| format_ident!("{x}"));
133
134 quote! {
135 #( #parts )*
136 }
137 }
138
139 self.dyn_type_traits =
140 DynTypeTraits::Custom(value.into_iter().map(|x| parse_path(&x.into())).collect());
141
142 self
143 }
144
145 pub fn box_flags(mut self, value: BoxFlags) -> Self {
147 self.box_flags = value;
148
149 self
150 }
151
152 pub fn content_mode(mut self, value: ContentMode) -> Self {
154 self.content_mode = value;
155
156 self
157 }
158
159 pub fn typedef_mode(mut self, value: TypedefMode) -> Self {
161 self.typedef_mode = value;
162
163 self
164 }
165
166 pub fn serde_support(mut self, value: SerdeSupport) -> Self {
168 self.serde_support = value;
169
170 self
171 }
172
173 pub fn generate_flags(mut self, value: GenerateFlags) -> Self {
175 self.generate_flags = value;
176
177 self
178 }
179
180 pub fn with_generate_flags(mut self, value: GenerateFlags) -> Self {
182 self.generate_flags |= value;
183
184 self
185 }
186
187 pub fn with_type_postfix<S: Into<String>>(mut self, type_: IdentType, postfix: S) -> Self {
191 self.postfixes[type_ as usize] = postfix.into();
192
193 self
194 }
195
196 pub fn with_type(mut self, ident: Ident) -> Result<Self, Error> {
214 let module_ident = format_module(self.types, ident.ns)?;
215 let type_ident = format_ident!("{}", ident.name.to_string());
216
217 let type_ref = TypeRef {
218 ns: ident.ns,
219 module_ident,
220 type_ident,
221 flags: StateFlags::empty(),
222 boxed_elements: HashSet::new(),
223 };
224 self.cache.insert(ident, type_ref);
225
226 Ok(self)
227 }
228
229 #[instrument(err, level = "trace", skip(self))]
241 pub fn generate_type(mut self, ident: Ident) -> Result<Self, Error> {
242 self.get_or_create_type_ref(ident)?;
243 self.generate_pending()?;
244
245 Ok(self)
246 }
247
248 #[instrument(err, level = "trace", skip(self))]
260 pub fn generate_all_types(mut self) -> Result<Self, Error> {
261 for ident in self.types.keys() {
262 self.get_or_create_type_ref(ident.clone())?;
263 }
264 self.generate_pending()?;
265
266 Ok(self)
267 }
268
269 #[instrument(level = "trace", skip(self))]
273 pub fn finish(self) -> TokenStream {
274 let Self {
275 modules,
276 types,
277 serde_support,
278 ..
279 } = self;
280
281 let serde = serde_includes(serde_support);
282
283 let modules = modules.0.into_iter().map(|(ns, module)| {
284 let Module {
285 code,
286 quick_xml_serialize,
287 quick_xml_deserialize,
288 } = module;
289
290 let quick_xml_serialize = quick_xml_serialize.map(|code| {
291 quote! {
292 pub mod quick_xml_serialize {
293 use super::*;
294
295 #code
296 }
297 }
298 });
299
300 let quick_xml_deserialize = quick_xml_deserialize.map(|code| {
301 quote! {
302 pub mod quick_xml_deserialize {
303 use super::*;
304
305 #code
306 }
307 }
308 });
309
310 let code = quote! {
311 #code
312 #quick_xml_serialize
313 #quick_xml_deserialize
314 };
315
316 if let Some(ns) = ns {
317 let name = format_module(types, Some(ns)).unwrap();
318
319 quote! {
320 pub mod #name {
321 use super::*;
322
323 #code
324 }
325 }
326 } else {
327 code
328 }
329 });
330
331 quote! {
332 #serde
333
334 #( #modules )*
335 }
336 }
337
338 fn get_traits(&mut self) -> &TraitInfos {
339 self.traits
340 .get_or_insert_with(|| TraitInfos::new(self.types))
341 }
342
343 #[instrument(level = "trace", skip(self))]
344 fn get_or_create_type_ref(&mut self, ident: Ident) -> Result<&TypeRef, Error> {
345 let Self {
346 types,
347 cache,
348 pending,
349 postfixes,
350 generate_flags,
351 ..
352 } = self;
353
354 if !cache.contains_key(&ident) {
355 let ty = types
356 .get(&ident)
357 .ok_or_else(|| Error::UnknownType(ident.clone()))?;
358 let name = make_type_name(postfixes, ty, &ident);
359 let (module_ident, type_ident) = if let Type::BuildIn(x) = ty {
360 (None, format_ident!("{x}"))
361 } else {
362 let use_modules = generate_flags.intersects(GenerateFlags::USE_MODULES);
363 let module_ident = format_module(types, use_modules.then_some(ident.ns).flatten())?;
364 let type_ident = format_type_ident(&name, None);
365
366 (module_ident, type_ident)
367 };
368
369 tracing::debug!("Queue new type generation: {ident}");
370
371 let boxed_elements = get_boxed_elements(&ident, ty, types, cache);
372 pending.push_back(PendingType {
373 ty,
374 ident: ident.clone(),
375 });
376
377 let type_ref = TypeRef {
378 module_ident,
379 ns: ident.ns,
380 type_ident,
381 flags: StateFlags::empty(),
382 boxed_elements,
383 };
384
385 assert!(cache.insert(ident.clone(), type_ref).is_none());
386 }
387
388 Ok(cache.get_mut(&ident).unwrap())
389 }
390
391 #[instrument(err, level = "trace", skip(self))]
392 fn generate_pending(&mut self) -> Result<(), Error> {
393 while let Some(args) = self.pending.pop_front() {
394 self.generate_type_intern(args)?;
395 }
396
397 Ok(())
398 }
399
400 #[instrument(err, level = "trace", skip(self))]
401 fn generate_type_intern(&mut self, data: PendingType<'types>) -> Result<(), Error> {
402 let PendingType { ty, ident } = data;
403
404 tracing::debug!("Render type: {ident}");
405
406 let data = TypeData {
407 ty,
408 ident,
409 generator: self,
410 };
411
412 match data.ty {
413 Type::BuildIn(_) => Ok(()),
414 Type::Union(x) => data.generate_union(x),
415 Type::Dynamic(x) => data.generate_dynamic(x),
416 Type::Reference(x) => data.generate_reference(x),
417 Type::Enumeration(x) => data.generate_enumeration(x),
418 Type::ComplexType(x) => data.generate_complex_type(x),
419 Type::All(x) => data.generate_all(x),
420 Type::Choice(x) => data.generate_choice(x),
421 Type::Sequence(x) => data.generate_sequence(x),
422 }
423 }
424}
425
426impl TypeRef {
429 fn add_flag_checked(&mut self, flag: StateFlags) -> bool {
430 let ret = self.flags.intersects(flag);
431
432 self.flags |= flag;
433
434 ret
435 }
436}
437
438fn serde_includes(serde_support: SerdeSupport) -> Option<TokenStream> {
441 let serde = matches!(
442 serde_support,
443 SerdeSupport::QuickXml | SerdeSupport::SerdeXmlRs
444 );
445
446 serde.then(|| {
447 quote!(
448 use serde::{Serialize, Deserialize};
449 )
450 })
451}
452
453fn get_boxed_elements<'a>(
454 ident: &Ident,
455 mut ty: &'a Type,
456 types: &'a Types,
457 cache: &BTreeMap<Ident, TypeRef>,
458) -> HashSet<Ident> {
459 if let Type::ComplexType(ci) = ty {
460 if let Some(type_) = ci.content.as_ref().and_then(|ident| types.get(ident)) {
461 ty = type_;
462 }
463 }
464
465 match ty {
466 Type::All(si) | Type::Choice(si) | Type::Sequence(si) => si
467 .elements
468 .iter()
469 .filter_map(|f| {
470 if Walk::new(types, cache).is_loop(ident, &f.type_) {
471 Some(f.ident.clone())
472 } else {
473 None
474 }
475 })
476 .collect(),
477 _ => HashSet::new(),
478 }
479}