1pub mod renderer;
4
5mod context;
6mod data;
7mod error;
8mod helper;
9mod misc;
10
11use std::collections::{BTreeMap, HashSet, VecDeque};
12use std::fmt::Display;
13use std::str::FromStr;
14
15use proc_macro2::{Ident as Ident2, TokenStream};
16use quote::{format_ident, ToTokens};
17use renderer::{Renderer, TypesRenderer};
18use smallvec::{smallvec, SmallVec};
19use tracing::instrument;
20
21use crate::code::{format_module_ident, format_type_ident, IdentPath, Module};
22use crate::schema::NamespaceId;
23use crate::types::{Ident, IdentType, Name, Type, TypeVariant, Types};
24
25pub use self::context::Context;
26pub use self::data::{
27 BuildInType, ComplexType, ComplexTypeAttribute, ComplexTypeBase, ComplexTypeContent,
28 ComplexTypeElement, ComplexTypeEnum, ComplexTypeStruct, DerivedType, DynamicType,
29 EnumerationType, EnumerationTypeVariant, ReferenceType, StructMode, TypeData, UnionType,
30 UnionTypeVariant,
31};
32pub use self::error::Error;
33pub use self::misc::{BoxFlags, GeneratorFlags, SerdeSupport, TypedefMode};
34
35use self::helper::Walk;
36use self::misc::{DynTypeTraits, PendingType, TraitInfos, TypeRef};
37
38#[must_use]
40#[derive(Debug)]
41pub struct Generator<'types> {
42 config: Config<'types>,
43 state: State<'types>,
44 renderers: Vec<Box<dyn Renderer>>,
45}
46
47#[must_use]
53#[derive(Debug)]
54pub struct GeneratorFixed<'types> {
55 config: Config<'types>,
56 state: State<'types>,
57 module: Module,
58 renderers: Vec<Box<dyn Renderer>>,
59}
60
61#[derive(Debug)]
63pub struct Config<'types> {
64 pub types: &'types Types,
66
67 pub flags: GeneratorFlags,
69
70 pub derive: Vec<Ident2>,
72
73 pub postfixes: [String; 8],
77
78 pub box_flags: BoxFlags,
80
81 pub typedef_mode: TypedefMode,
83
84 pub serde_support: SerdeSupport,
86
87 pub dyn_type_traits: DynTypeTraits,
89
90 pub xsd_parser_crate: Ident2,
92}
93
94#[derive(Debug)]
95struct State<'types> {
96 cache: BTreeMap<Ident, TypeRef>,
97 trait_infos: Option<TraitInfos>,
98 pending: VecDeque<PendingType<'types>>,
99}
100
101impl<'types> Generator<'types> {
104 pub fn new(types: &'types Types) -> Self {
106 let config = Config {
107 types,
108 flags: GeneratorFlags::empty(),
109 derive: vec![format_ident!("Debug")],
110 postfixes: [
111 String::from("Type"), String::new(), String::from("ElementType"), String::new(), String::new(), String::new(), String::new(), String::new(), ],
120 box_flags: BoxFlags::AUTO,
121 typedef_mode: TypedefMode::Auto,
122 serde_support: SerdeSupport::None,
123 dyn_type_traits: DynTypeTraits::Auto,
124 xsd_parser_crate: format_ident!("xsd_parser"),
125 };
126 let state = State {
127 cache: BTreeMap::new(),
128 trait_infos: None,
129 pending: VecDeque::new(),
130 };
131 let renderers = Vec::new();
132
133 Self {
134 config,
135 state,
136 renderers,
137 }
138 }
139
140 pub fn xsd_parser_crate<S: Display>(mut self, value: S) -> Self {
143 self.config.xsd_parser_crate = format_ident!("{value}");
144
145 self
146 }
147
148 pub fn derive<I>(mut self, value: I) -> Self
159 where
160 I: IntoIterator,
161 I::Item: Display,
162 {
163 self.config.derive = value.into_iter().map(|x| format_ident!("{x}")).collect();
164
165 self
166 }
167
168 pub fn dyn_type_traits<I>(mut self, value: I) -> Result<Self, Error>
184 where
185 I: IntoIterator,
186 I::Item: AsRef<str>,
187 {
188 let traits = value
189 .into_iter()
190 .map(|x| {
191 let s = x.as_ref();
192 IdentPath::from_str(s).map_err(|()| Error::InvalidIdentifier(s.into()))
193 })
194 .collect::<Result<Vec<_>, _>>()?;
195
196 self.config.dyn_type_traits = DynTypeTraits::Custom(traits);
197
198 Ok(self)
199 }
200
201 pub fn box_flags(mut self, value: BoxFlags) -> Self {
203 self.config.box_flags = value;
204
205 self
206 }
207
208 pub fn typedef_mode(mut self, value: TypedefMode) -> Self {
210 self.config.typedef_mode = value;
211
212 self
213 }
214
215 pub fn serde_support(mut self, value: SerdeSupport) -> Self {
217 self.config.serde_support = value;
218
219 self
220 }
221
222 pub fn flags(mut self, value: GeneratorFlags) -> Self {
224 self.config.flags = value;
225
226 self
227 }
228
229 pub fn with_flags(mut self, value: GeneratorFlags) -> Self {
231 self.config.flags |= value;
232
233 self
234 }
235
236 pub fn with_type_postfix<S: Into<String>>(mut self, type_: IdentType, postfix: S) -> Self {
240 self.config.postfixes[type_ as usize] = postfix.into();
241
242 self
243 }
244
245 pub fn with_type(mut self, ident: Ident) -> Result<Self, Error> {
263 let module_ident = format_module(self.config.types, ident.ns)?;
264 let type_ident = format_ident!("{}", ident.name.to_string());
265
266 let type_ref = TypeRef {
267 ident: ident.clone(),
268 module_ident,
269 type_ident,
270 boxed_elements: HashSet::new(),
271 };
272 self.state.cache.insert(ident, type_ref);
273
274 Ok(self)
275 }
276
277 pub fn with_renderer<X>(mut self, renderer: X) -> Self
279 where
280 X: Renderer + 'static,
281 {
282 self.renderers.push(Box::new(renderer));
283
284 self
285 }
286
287 pub fn with_default_renderers(self) -> Self {
289 self.with_renderer(TypesRenderer)
290 }
291
292 pub fn clear_renderers(mut self) -> Self {
294 self.renderers.clear();
295
296 self
297 }
298
299 #[instrument(err, level = "trace", skip(self))]
302 pub fn generate_type(self, ident: Ident) -> Result<GeneratorFixed<'types>, Error> {
303 self.into_fixed().generate_type(ident)
304 }
305
306 pub fn generate_all_types(self) -> Result<GeneratorFixed<'types>, Error> {
313 self.into_fixed().generate_all_types()
314 }
315
316 pub fn into_fixed(self) -> GeneratorFixed<'types> {
318 let Self {
319 mut config,
320 state,
321 mut renderers,
322 } = self;
323 let module = Module::default();
324
325 config.dyn_type_traits = match config.dyn_type_traits {
326 DynTypeTraits::Auto => {
327 let traits = config.derive.iter().map(|x| match x.to_string().as_ref() {
328 "Debug" => IdentPath::from_str("core::fmt::Debug").unwrap(),
329 "Hash" => IdentPath::from_str("core::hash::Hash").unwrap(),
330 _ => IdentPath::from_ident(x.clone()),
331 });
332
333 let serde: SmallVec<[IdentPath; 2]> = if config.serde_support == SerdeSupport::None
334 {
335 smallvec![]
336 } else {
337 smallvec![
338 IdentPath::from_str("serde::Serialize").unwrap(),
339 IdentPath::from_str("serde::DeserializeOwned").unwrap()
340 ]
341 };
342
343 let as_any = IdentPath::from_parts(
344 Some(config.xsd_parser_crate.clone()),
345 format_ident!("AsAny"),
346 );
347
348 DynTypeTraits::Custom(traits.chain(serde).chain(Some(as_any)).collect())
349 }
350 x => x,
351 };
352
353 for renderer in &mut renderers {
354 renderer.initialize(&mut config);
355 }
356
357 GeneratorFixed {
358 config,
359 state,
360 module,
361 renderers,
362 }
363 }
364}
365
366impl<'types> GeneratorFixed<'types> {
367 #[instrument(err, level = "trace", skip(self))]
379 pub fn generate_type(mut self, ident: Ident) -> Result<GeneratorFixed<'types>, Error> {
380 self.state.get_or_create_type_ref(&self.config, ident)?;
381 self.generate_pending()?;
382
383 Ok(self)
384 }
385
386 #[instrument(err, level = "trace", skip(self))]
398 pub fn generate_all_types(mut self) -> Result<Self, Error> {
399 for ident in self.config.types.keys() {
400 self.state
401 .get_or_create_type_ref(&self.config, ident.clone())?;
402 }
403 self.generate_pending()?;
404
405 Ok(self)
406 }
407
408 #[instrument(err, level = "trace", skip(self))]
421 pub fn generate_named_types(mut self) -> Result<Self, Error> {
422 for ident in self.config.types.keys() {
423 if ident.name.is_named() {
424 self.state
425 .get_or_create_type_ref(&self.config, ident.clone())?;
426 }
427 }
428 self.generate_pending()?;
429
430 Ok(self)
431 }
432
433 #[instrument(level = "trace", skip(self))]
437 pub fn finish(self) -> TokenStream {
438 let Self {
439 config,
440 mut module,
441 state: _,
442 mut renderers,
443 } = self;
444
445 for renderer in &mut renderers {
446 renderer.finish(&config, &mut module);
447 }
448
449 module.to_token_stream()
450 }
451
452 #[instrument(err, level = "trace", skip(self))]
453 fn generate_pending(&mut self) -> Result<(), Error> {
454 while let Some(args) = self.state.pending.pop_front() {
455 self.generate_type_intern(args)?;
456 }
457
458 Ok(())
459 }
460
461 #[instrument(err, level = "trace", skip(self))]
462 fn generate_type_intern(&mut self, data: PendingType<'types>) -> Result<(), Error> {
463 let PendingType { ty, ident } = data;
464 let Self {
465 config,
466 state,
467 module,
468 renderers,
469 } = self;
470 let ty = TypeData::new(ty, &ident, config, state)?;
471 let mut ctx = Context::new(&ident, config, module);
472
473 tracing::debug!("Render type: {ident}");
474
475 for renderer in renderers {
476 renderer.render_type(&mut ctx, &ty);
477 }
478
479 Ok(())
480 }
481}
482
483impl Config<'_> {
484 fn check_flags(&self, flags: GeneratorFlags) -> bool {
485 self.flags.intersects(flags)
486 }
487}
488
489impl<'types> State<'types> {
490 #[instrument(level = "trace", skip(self, config))]
491 fn get_or_create_type_ref(
492 &mut self,
493 config: &Config<'types>,
494 ident: Ident,
495 ) -> Result<&TypeRef, Error> {
496 if !self.cache.contains_key(&ident) {
497 let ty = config
498 .types
499 .get(&ident)
500 .ok_or_else(|| Error::UnknownType(ident.clone()))?;
501 let name = make_type_name(&config.postfixes, ty, &ident);
502 let (module_ident, type_ident) = if let TypeVariant::BuildIn(x) = &ty.variant {
503 (None, format_ident!("{x}"))
504 } else {
505 let use_modules = config.flags.intersects(GeneratorFlags::USE_MODULES);
506 let module_ident =
507 format_module(config.types, use_modules.then_some(ident.ns).flatten())?;
508 let type_ident = format_type_ident(&name, ty.display_name.as_deref());
509
510 (module_ident, type_ident)
511 };
512
513 tracing::debug!("Queue new type generation: {ident}");
514
515 let boxed_elements = get_boxed_elements(&ident, ty, config.types, &self.cache);
516 self.pending.push_back(PendingType {
517 ty,
518 ident: ident.clone(),
519 });
520
521 let type_ref = TypeRef {
522 ident: ident.clone(),
523 type_ident,
524 module_ident,
525 boxed_elements,
526 };
527
528 assert!(self.cache.insert(ident.clone(), type_ref).is_none());
529 }
530
531 Ok(self.cache.get_mut(&ident).unwrap())
532 }
533}
534
535fn get_boxed_elements<'a>(
538 ident: &Ident,
539 mut ty: &'a Type,
540 types: &'a Types,
541 cache: &BTreeMap<Ident, TypeRef>,
542) -> HashSet<Ident> {
543 if let TypeVariant::ComplexType(ci) = &ty.variant {
544 if let Some(type_) = ci.content.as_ref().and_then(|ident| types.get(ident)) {
545 ty = type_;
546 }
547 }
548
549 match &ty.variant {
550 TypeVariant::All(si) | TypeVariant::Choice(si) | TypeVariant::Sequence(si) => si
551 .elements
552 .iter()
553 .filter_map(|f| {
554 if Walk::new(types, cache).is_loop(ident, &f.type_) {
555 Some(f.ident.clone())
556 } else {
557 None
558 }
559 })
560 .collect(),
561 _ => HashSet::new(),
562 }
563}
564
565fn make_type_name(postfixes: &[String], ty: &Type, ident: &Ident) -> Name {
566 if let TypeVariant::Reference(ti) = &ty.variant {
567 if ident.name.is_generated() && ti.type_.name.is_named() {
568 if ti.min_occurs > 1 {
569 return Name::new_generated(format!("{}List", ti.type_.name.to_type_name()));
570 } else if ti.min_occurs == 0 {
571 return Name::new_generated(format!("{}Opt", ti.type_.name.to_type_name()));
572 }
573 }
574 }
575
576 let postfix = postfixes
577 .get(ident.type_ as usize)
578 .map_or("", |s| s.as_str());
579
580 let s = ident.name.to_type_name();
581
582 if s.ends_with(postfix) {
583 ident.name.clone()
584 } else {
585 Name::new_generated(format!("{s}{postfix}"))
586 }
587}
588
589fn format_module(types: &Types, ns: Option<NamespaceId>) -> Result<Option<Ident2>, Error> {
590 let Some(ns) = ns else {
591 return Ok(None);
592 };
593
594 let module = types.modules.get(&ns).ok_or(Error::UnknownNamespace(ns))?;
595 let Some(name) = &module.name else {
596 return Ok(None);
597 };
598
599 Ok(Some(format_module_ident(name)))
600}