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::{MaxOccurs, 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::de::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 self.into_module().to_token_stream()
439 }
440
441 #[instrument(level = "trace", skip(self))]
443 pub fn into_module(self) -> Module {
444 let Self {
445 config,
446 mut module,
447 state: _,
448 mut renderers,
449 } = self;
450
451 for renderer in &mut renderers {
452 renderer.finish(&config, &mut module);
453 }
454
455 module
456 }
457
458 #[instrument(err, level = "trace", skip(self))]
459 fn generate_pending(&mut self) -> Result<(), Error> {
460 while let Some(args) = self.state.pending.pop_front() {
461 self.generate_type_intern(args)?;
462 }
463
464 Ok(())
465 }
466
467 #[instrument(err, level = "trace", skip(self))]
468 fn generate_type_intern(&mut self, data: PendingType<'types>) -> Result<(), Error> {
469 let PendingType { ty, ident } = data;
470 let Self {
471 config,
472 state,
473 module,
474 renderers,
475 } = self;
476 let ty = TypeData::new(ty, &ident, config, state)?;
477 let mut ctx = Context::new(&ident, config, module);
478
479 tracing::debug!("Render type: {ident}");
480
481 for renderer in renderers {
482 renderer.render_type(&mut ctx, &ty);
483 }
484
485 Ok(())
486 }
487}
488
489impl Config<'_> {
490 fn check_flags(&self, flags: GeneratorFlags) -> bool {
491 self.flags.intersects(flags)
492 }
493}
494
495impl<'types> State<'types> {
496 #[instrument(level = "trace", skip(self, config))]
497 fn get_or_create_type_ref(
498 &mut self,
499 config: &Config<'types>,
500 ident: Ident,
501 ) -> Result<&TypeRef, Error> {
502 if !self.cache.contains_key(&ident) {
503 let ty = config
504 .types
505 .get(&ident)
506 .ok_or_else(|| Error::UnknownType(ident.clone()))?;
507 let name = make_type_name(&config.postfixes, ty, &ident);
508 let (module_ident, type_ident) = if let TypeVariant::BuildIn(x) = &ty.variant {
509 (None, format_ident!("{x}"))
510 } else {
511 let use_modules = config.flags.intersects(GeneratorFlags::USE_MODULES);
512 let module_ident =
513 format_module(config.types, use_modules.then_some(ident.ns).flatten())?;
514 let type_ident = format_type_ident(&name, ty.display_name.as_deref());
515
516 (module_ident, type_ident)
517 };
518
519 tracing::debug!("Queue new type generation: {ident}");
520
521 let boxed_elements = get_boxed_elements(&ident, ty, config.types, &self.cache);
522 self.pending.push_back(PendingType {
523 ty,
524 ident: ident.clone(),
525 });
526
527 let type_ref = TypeRef {
528 ident: ident.clone(),
529 type_ident,
530 module_ident,
531 boxed_elements,
532 };
533
534 assert!(self.cache.insert(ident.clone(), type_ref).is_none());
535 }
536
537 Ok(self.cache.get_mut(&ident).unwrap())
538 }
539}
540
541fn get_boxed_elements<'a>(
544 ident: &Ident,
545 mut ty: &'a Type,
546 types: &'a Types,
547 cache: &BTreeMap<Ident, TypeRef>,
548) -> HashSet<Ident> {
549 if let TypeVariant::ComplexType(ci) = &ty.variant {
550 if let Some(type_) = ci.content.as_ref().and_then(|ident| types.get(ident)) {
551 ty = type_;
552 }
553 }
554
555 match &ty.variant {
556 TypeVariant::All(si) | TypeVariant::Choice(si) | TypeVariant::Sequence(si) => si
557 .elements
558 .iter()
559 .filter_map(|f| {
560 if Walk::new(types, cache).is_loop(ident, &f.type_) {
561 Some(f.ident.clone())
562 } else {
563 None
564 }
565 })
566 .collect(),
567 _ => HashSet::new(),
568 }
569}
570
571fn make_type_name(postfixes: &[String], ty: &Type, ident: &Ident) -> Name {
572 if let TypeVariant::Reference(ti) = &ty.variant {
573 if ident.name.is_generated() && ti.type_.name.is_named() {
574 let s = ti.type_.name.to_type_name();
575
576 if ti.max_occurs > MaxOccurs::Bounded(1) {
577 return Name::new_generated(format!("{s}List"));
578 } else if ti.min_occurs == 0 {
579 return Name::new_generated(format!("{s}Opt"));
580 }
581 }
582 }
583
584 let postfix = postfixes
585 .get(ident.type_ as usize)
586 .map_or("", |s| s.as_str());
587
588 let s = ident.name.to_type_name();
589
590 if s.ends_with(postfix) {
591 ident.name.clone()
592 } else {
593 Name::new_generated(format!("{s}{postfix}"))
594 }
595}
596
597fn format_module(types: &Types, ns: Option<NamespaceId>) -> Result<Option<Ident2>, Error> {
598 let Some(ns) = ns else {
599 return Ok(None);
600 };
601
602 let module = types.modules.get(&ns).ok_or(Error::UnknownNamespace(ns))?;
603 let Some(name) = &module.name else {
604 return Ok(None);
605 };
606
607 Ok(Some(format_module_ident(name)))
608}