xsd_parser/config.rs
1//! Contains the [`Config`] structures for the [`generate`](super::generate) method.
2
3use std::path::PathBuf;
4
5use bitflags::bitflags;
6use url::Url;
7
8pub use crate::generator::{BoxFlags, GeneratorFlags, SerdeSupport, TypedefMode};
9pub use crate::schema::{Namespace, NamespacePrefix};
10pub use crate::types::{IdentType, Type};
11
12use crate::schema::Schemas;
13use crate::types::{Ident, Name};
14use crate::InterpreterError;
15
16/// Configuration structure for the [`generate`](super::generate) method.
17#[must_use]
18#[derive(Default, Debug, Clone)]
19pub struct Config {
20 /// Configuration for the schema parser.
21 pub parser: ParserConfig,
22
23 /// Configuration for the schema interpreter.
24 pub interpreter: InterpreterConfig,
25
26 /// Configuration for the type information optimizer.
27 pub optimizer: OptimizerConfig,
28
29 /// Configuration for the code generator.
30 pub generator: GeneratorConfig,
31}
32
33/// Configuration for the schema parser.
34#[derive(Debug, Clone)]
35pub struct ParserConfig {
36 /// List of resolvers to use for resolving referenced schemas.
37 pub resolver: Vec<Resolver>,
38
39 /// List of namespaces to add to the parser before the schemas are loaded.
40 ///
41 /// See [`with_namespace`](crate::Parser::with_namespace) for more details.
42 pub namespaces: Vec<(NamespacePrefix, Namespace)>,
43
44 /// List of schemas to load.
45 pub schemas: Vec<Schema>,
46
47 /// Additional flags to control the parser.
48 pub flags: ParserFlags,
49
50 /// Wether to enable the debug output and where to write it to.
51 pub debug_output: Option<PathBuf>,
52}
53
54/// Configuration for the schema interpreter.
55#[derive(Debug, Clone)]
56pub struct InterpreterConfig {
57 /// List of user defined types to add to the interpreter before the schemas
58 /// are actually interpreted.
59 ///
60 /// See [`with_type`](crate::Interpreter::with_type) for more details.
61 pub types: Vec<(IdentTriple, Type)>,
62
63 /// Additional flags to control the interpreter.
64 pub flags: InterpreterFlags,
65
66 /// Wether to enable the debug output and where to write it to.
67 pub debug_output: Option<PathBuf>,
68}
69
70/// Configuration for the type information optimizer.
71#[derive(Debug, Clone)]
72pub struct OptimizerConfig {
73 /// Additional flags to control the optimizer.
74 pub flags: OptimizerFlags,
75
76 /// Wether to enable the debug output and where to write it to.
77 pub debug_output: Option<PathBuf>,
78}
79
80/// Configuration for the code generator.
81#[derive(Debug, Clone)]
82pub struct GeneratorConfig {
83 /// Types to add to the generator before the actual code is generated.
84 ///
85 /// See [`with_type`](crate::Generator::with_type) for more details.
86 pub types: Vec<IdentTriple>,
87
88 /// Sets the traits the generated types should derive from.
89 ///
90 /// See [`derive`](crate::Generator::derive) for more details.
91 pub derive: Option<Vec<String>>,
92
93 /// Set the traits that should be implemented by dynamic types.
94 ///
95 /// See [`dyn_type_traits`](crate::Generator::dyn_type_traits) for more details.
96 pub dyn_type_traits: Option<Vec<String>>,
97
98 /// Postfixes that should be applied to the name of the different generated
99 /// types.
100 ///
101 /// See [`with_type_postfix`](crate::Generator::with_type_postfix) for more details.
102 pub type_postfix: TypePostfix,
103
104 /// Tell the generator how to deal with boxing.
105 pub box_flags: BoxFlags,
106
107 /// Tells the generator how to deal with type definitions.
108 pub typedef_mode: TypedefMode,
109
110 /// Tells the generator how to generate code for the [`serde`] crate.
111 pub serde_support: SerdeSupport,
112
113 /// Specify which types the generator should generate code for.
114 pub generate: Generate,
115
116 /// Additional flags to control the generator.
117 pub flags: GeneratorFlags,
118
119 /// Name of the `xsd-parser` crate that is used for the generated code.
120 pub xsd_parser: String,
121
122 /// Renderers to use for rendering the code.
123 pub renderers: Vec<Renderer>,
124}
125
126/// Postfixed that will be added to the different types generated by the code generator.
127#[derive(Debug, Clone)]
128pub struct TypePostfix {
129 /// Postfix added to normal types (like `xs:simpleType` or `xs:complexType`).
130 pub type_: String,
131
132 /// Postfixes added to elements (like `xs:element`).
133 pub element: String,
134
135 /// Postfixes added to inline types if elements (like `xs:element`).
136 pub element_type: String,
137}
138
139/// Configuration for the [`Resolver`](crate::parser::resolver::Resolver)s used in [`ParserConfig`].
140#[derive(Debug, Clone)]
141pub enum Resolver {
142 /// Resolver that is used to resolve ewb resources (like `http://...` or `https://...`).
143 #[cfg(feature = "web-resolver")]
144 Web,
145
146 /// Resolver that is used to resolve local resources from disk (like `./local-schema.xsd` or `file://...`).
147 File,
148}
149
150/// Configuration for the schemas to load used in [`ParserConfig`].
151#[derive(Debug, Clone)]
152pub enum Schema {
153 /// Load a schema from the provided URL.
154 Url(Url),
155
156 /// Load a schema from the provided file path.
157 File(PathBuf),
158
159 /// Load the schema from the provided string.
160 Schema(String),
161}
162
163/// Configuration which types the [`Generator`](crate::Generator) should generate
164/// code for used in [`GeneratorConfig`].
165#[derive(Debug, Clone)]
166pub enum Generate {
167 /// The generator will generate code for all types of the schemas.
168 All,
169
170 /// The generator will generate code for all types that have a name.
171 Named,
172
173 /// List of identifiers the generator will generate code for.
174 Types(Vec<IdentTriple>),
175}
176
177/// Identifier that is used inside the config.
178///
179/// Each element in a XML schema is uniquely identified by the following three
180/// values:
181/// - The namespace of the element (or no namespace at all).
182/// - The name of the element.
183/// - The type of element.
184///
185/// This struct is used to bundle these three information to a unique identifier
186/// for an element.
187#[derive(Debug, Clone)]
188pub struct IdentTriple {
189 /// Namespace where the type is defined in.
190 pub ns: Option<NamespaceIdent>,
191
192 /// Name of the type.
193 pub name: String,
194
195 /// Type of the identifier (because pure names are not unique in XSD).
196 pub type_: IdentType,
197}
198
199/// Identifies a namespace by either it's known prefix or by the namespace directly.
200#[derive(Debug, Clone)]
201pub enum NamespaceIdent {
202 /// Uses a namespace prefix to refer to a specific namespace in the schema.
203 Prefix(NamespacePrefix),
204
205 /// Uses the full namespace to refer to a specific namespace in the schema.
206 Namespace(Namespace),
207}
208
209/// Configuration for the [`Renderer`](crate::generator::renderer::Renderer)s
210/// the [`Generator`](crate::Generator) should use for rendering the code.
211#[derive(Debug, Clone, Copy, Eq, PartialEq)]
212pub enum Renderer {
213 /// Render to render the pure types.
214 Types,
215
216 /// Renderer to render associated methods that return the default values
217 /// of the different fields of a struct.
218 Defaults,
219
220 /// Renderer to add constants for the namespaces to the generated code.
221 NamespaceConstants,
222
223 /// Renderer that adds the [`WithNamespace`](crate::WithNamespace) trait to
224 /// the generated types.
225 WithNamespaceTrait,
226
227 /// Renderer that renders code for the `quick_xml` serializer of the
228 /// different types.
229 QuickXmlSerialize,
230
231 /// Renderer that renders code for the `quick_xml` deserializer of the
232 /// different types.
233 QuickXmlDeserialize {
234 /// Whether to box the deserializer or not.
235 ///
236 /// For more details have a look at [`QuickXmlDeserializeRenderer::boxed_deserializer`](crate::QuickXmlDeserializeRenderer::boxed_deserializer).
237 boxed_deserializer: bool,
238 },
239}
240
241bitflags! {
242 /// Flags to control the [`Parser`](crate::Parser).
243 #[derive(Debug, Clone)]
244 pub struct ParserFlags: u32 {
245 /// Whether the parser should resolve `xs:include` and `xs:import` elements
246 /// or not.
247 ///
248 /// See [`resolve_includes`](crate::Parser::resolve_includes) for details.
249 const RESOLVE_INCLUDES = 1 << 0;
250
251 /// Whether to add the default namespaces to the parser or not.
252 ///
253 /// See [`with_default_namespaces`](crate::Parser::with_default_namespaces) for details.
254 const DEFAULT_NAMESPACES = 1 << 1;
255 }
256}
257
258bitflags! {
259 /// Flags to control the [`Interpreter`](crate::Interpreter).
260 #[derive(Debug, Clone)]
261 pub struct InterpreterFlags: u32 {
262 /// Whether to add the build-in types to the interpreter or not.
263 ///
264 /// See [`with_buildin_types`](crate::Interpreter::with_buildin_types) for details.
265 const BUILDIN_TYPES = 1 << 0;
266
267 /// Whether to add the default types definitions to the interpreter or not.
268 ///
269 /// See [`with_default_typedefs`](crate::Interpreter::with_default_typedefs) for details.
270 const DEFAULT_TYPEDEFS = 1 << 1;
271
272 /// Whether to add a default type definitions for `xs:anyType` or not.
273 ///
274 /// See [`with_xs_any_type`](crate::Interpreter::with_xs_any_type) for details.
275 const WITH_XS_ANY_TYPE = 1 << 2;
276 }
277}
278
279bitflags! {
280 /// Flags to control the [`Optimizer`](crate::Optimizer).
281 #[derive(Debug, Clone)]
282 pub struct OptimizerFlags: u32 {
283 /// Whether to remove empty enum variants or not.
284 ///
285 /// See [`remove_empty_enum_variants`](crate::Optimizer::remove_empty_enum_variants) for details.
286 const REMOVE_EMPTY_ENUM_VARIANTS = 1 << 0;
287
288 /// Whether to remove empty enums or not.
289 ///
290 /// See [`remove_empty_enums`](crate::Optimizer::remove_empty_enums) for details.
291 const REMOVE_EMPTY_ENUMS = 1 << 1;
292
293 /// Whether to remove duplicate union variants or not.
294 ///
295 /// See [`remove_duplicate_union_variants`](crate::Optimizer::remove_duplicate_union_variants) for details.
296 const REMOVE_DUPLICATE_UNION_VARIANTS = 1 << 2;
297
298 /// Whether to remove empty unions or not.
299 ///
300 /// See [`remove_empty_unions`](crate::Optimizer::remove_empty_unions) for details.
301 const REMOVE_EMPTY_UNIONS = 1 << 3;
302
303 /// Whether to use the unrestricted base type of a type or not.
304 ///
305 /// See [`use_unrestricted_base_type`](crate::Optimizer::use_unrestricted_base_type) for details.
306 const USE_UNRESTRICTED_BASE_TYPE = 1 << 4;
307
308 /// Whether to convert dynamic types to choices or not.
309 ///
310 /// See [`convert_dynamic_to_choice`](crate::Optimizer::convert_dynamic_to_choice) for details.
311 const CONVERT_DYNAMIC_TO_CHOICE = 1 << 5;
312
313 /// Whether to flatten the content of complex types or not.
314 ///
315 /// See [`flatten_complex_types`](crate::Optimizer::flatten_complex_types) for details.
316 const FLATTEN_COMPLEX_TYPES = 1 << 6;
317
318 /// Whether to flatten unions or not.
319 ///
320 /// See [`flatten_unions`](crate::Optimizer::flatten_unions) for details.
321 const FLATTEN_UNIONS = 1 << 7;
322
323 /// Whether to merge enumerations and unions or not.
324 ///
325 /// See [`merge_enum_unions`](crate::Optimizer::merge_enum_unions) for details.
326 const MERGE_ENUM_UNIONS = 1 << 8;
327
328 /// Whether to resolve type definitions or not.
329 ///
330 /// See [`resolve_typedefs`](crate::Optimizer::resolve_typedefs) for details.
331 const RESOLVE_TYPEDEFS = 1 << 9;
332
333 /// Whether to remove duplicate types or not.
334 ///
335 /// See [`remove_duplicates`](crate::Optimizer::remove_duplicates) for details.
336 const REMOVE_DUPLICATES = 1 << 10;
337
338 /// Group that contains all necessary optimization that should be applied
339 /// if code with [`serde`] support should be rendered.
340 const SERDE = Self::FLATTEN_COMPLEX_TYPES.bits()
341 | Self::FLATTEN_UNIONS.bits()
342 | Self::MERGE_ENUM_UNIONS.bits();
343
344 /// Wether to merge the cardinality of a complex choice type or not.
345 ///
346 /// See [`merge_choice_cardinalities`](crate::Optimizer::merge_choice_cardinalities) for details.
347 const MERGE_CHOICE_CARDINALITIES = 1 << 11;
348 }
349}
350
351impl Config {
352 /// Set parser flags to the config.
353 pub fn set_parser_flags(mut self, flags: ParserFlags) -> Self {
354 self.parser.flags = flags;
355
356 self
357 }
358
359 /// Add parser flags to the config.
360 pub fn with_parser_flags(mut self, flags: ParserFlags) -> Self {
361 self.parser.flags.insert(flags);
362
363 self
364 }
365
366 /// Remove parser flags to the config.
367 pub fn without_parser_flags(mut self, flags: ParserFlags) -> Self {
368 self.parser.flags.remove(flags);
369
370 self
371 }
372
373 /// Set interpreter flags to the config.
374 pub fn set_interpreter_flags(mut self, flags: InterpreterFlags) -> Self {
375 self.interpreter.flags = flags;
376
377 self
378 }
379
380 /// Add code interpreter flags to the config.
381 pub fn with_interpreter_flags(mut self, flags: InterpreterFlags) -> Self {
382 self.interpreter.flags.insert(flags);
383
384 self
385 }
386
387 /// Remove code interpreter flags to the config.
388 pub fn without_interpreter_flags(mut self, flags: InterpreterFlags) -> Self {
389 self.interpreter.flags.remove(flags);
390
391 self
392 }
393
394 /// Set optimizer flags to the config.
395 pub fn set_optimizer_flags(mut self, flags: OptimizerFlags) -> Self {
396 self.optimizer.flags = flags;
397
398 self
399 }
400
401 /// Add optimizer flags to the config.
402 pub fn with_optimizer_flags(mut self, flags: OptimizerFlags) -> Self {
403 self.optimizer.flags.insert(flags);
404
405 self
406 }
407
408 /// Remove optimizer flags to the config.
409 pub fn without_optimizer_flags(mut self, flags: OptimizerFlags) -> Self {
410 self.optimizer.flags.remove(flags);
411
412 self
413 }
414
415 /// Set generator flags to the config.
416 pub fn set_generator_flags(mut self, flags: GeneratorFlags) -> Self {
417 self.generator.flags = flags;
418
419 self
420 }
421
422 /// Add code generator flags to the config.
423 pub fn with_generator_flags(mut self, flags: GeneratorFlags) -> Self {
424 self.generator.flags.insert(flags);
425
426 self
427 }
428
429 /// Remove code generator flags to the config.
430 pub fn without_generator_flags(mut self, flags: GeneratorFlags) -> Self {
431 self.generator.flags.remove(flags);
432
433 self
434 }
435
436 /// Set boxing flags to the code generator config.
437 pub fn set_box_flags(mut self, flags: BoxFlags) -> Self {
438 self.generator.box_flags = flags;
439
440 self
441 }
442
443 /// Add boxing flags to the code generator config.
444 pub fn with_box_flags(mut self, flags: BoxFlags) -> Self {
445 self.generator.box_flags.insert(flags);
446
447 self
448 }
449
450 /// Remove boxing flags to the code generator config.
451 pub fn without_box_flags(mut self, flags: BoxFlags) -> Self {
452 self.generator.box_flags.remove(flags);
453
454 self
455 }
456
457 /// Adds the passed `renderer` to the config.
458 ///
459 /// If the same type of renderer was already added,
460 /// it is replaced by the new one.
461 pub fn with_renderer(mut self, renderer: Renderer) -> Self {
462 if let Some(index) = self.generator.renderers.iter().position(|x| x == &renderer) {
463 self.generator.renderers[index] = renderer;
464 } else {
465 self.generator.renderers.push(renderer);
466 }
467
468 self
469 }
470
471 /// Add multiple renderers to the generator config.
472 ///
473 /// See [`with_renderer`](Self::with_renderer) for details.
474 pub fn with_renderers<I>(mut self, renderers: I) -> Self
475 where
476 I: IntoIterator<Item = Renderer>,
477 {
478 for renderer in renderers {
479 self = self.with_renderer(renderer);
480 }
481
482 self
483 }
484
485 /// Enable code generation for [`quick_xml`] serialization.
486 pub fn with_quick_xml_serialize(self) -> Self {
487 self.with_renderers([
488 Renderer::Types,
489 Renderer::Defaults,
490 Renderer::NamespaceConstants,
491 Renderer::QuickXmlSerialize,
492 ])
493 }
494
495 /// Enable code generation for [`quick_xml`] deserialization with the default settings.
496 pub fn with_quick_xml_deserialize(self) -> Self {
497 self.with_quick_xml_deserialize_config(false)
498 }
499
500 /// Enable code generation for [`quick_xml`] deserialization
501 /// with the passed configuration.
502 pub fn with_quick_xml_deserialize_config(self, boxed_deserializer: bool) -> Self {
503 self.with_renderers([
504 Renderer::Types,
505 Renderer::Defaults,
506 Renderer::NamespaceConstants,
507 Renderer::QuickXmlDeserialize { boxed_deserializer },
508 ])
509 }
510
511 /// Enable code generation for [`quick_xml`] serialization and deserialization
512 /// with the default settings.
513 pub fn with_quick_xml(self) -> Self {
514 self.with_quick_xml_serialize().with_quick_xml_deserialize()
515 }
516
517 /// Enable code generation for [`quick_xml`] serialization and deserialization
518 /// with the passed configuration.
519 pub fn with_quick_xml_config(self, boxed_deserializer: bool) -> Self {
520 self.with_quick_xml_serialize()
521 .with_quick_xml_deserialize_config(boxed_deserializer)
522 }
523
524 /// Set the [`serde`] support.
525 pub fn with_serde_support(mut self, serde_support: SerdeSupport) -> Self {
526 self.generator.serde_support = serde_support;
527
528 if self.generator.serde_support != SerdeSupport::None {
529 self.optimizer.flags |= OptimizerFlags::SERDE;
530 }
531
532 self
533 }
534
535 /// Set the types the code should be generated for.
536 pub fn with_generate<I>(mut self, types: I) -> Self
537 where
538 I: IntoIterator,
539 I::Item: Into<IdentTriple>,
540 {
541 self.generator.generate = Generate::Types(types.into_iter().map(Into::into).collect());
542
543 self
544 }
545
546 /// Set the typedef mode for the generator.
547 pub fn with_typedef_mode(mut self, mode: TypedefMode) -> Self {
548 self.generator.typedef_mode = mode;
549
550 self
551 }
552
553 /// Set the traits the generated types should derive from.
554 pub fn with_derive<I>(mut self, derive: I) -> Self
555 where
556 I: IntoIterator,
557 I::Item: Into<String>,
558 {
559 self.generator.derive = Some(
560 derive
561 .into_iter()
562 .map(Into::into)
563 .filter(|s| !s.is_empty())
564 .collect(),
565 );
566
567 self
568 }
569}
570
571impl Default for ParserConfig {
572 fn default() -> Self {
573 Self {
574 resolver: vec![Resolver::File],
575 schemas: vec![],
576 namespaces: vec![],
577 flags: ParserFlags::RESOLVE_INCLUDES | ParserFlags::DEFAULT_NAMESPACES,
578 debug_output: None,
579 }
580 }
581}
582
583impl Default for InterpreterConfig {
584 fn default() -> Self {
585 Self {
586 types: vec![],
587 debug_output: None,
588 flags: InterpreterFlags::BUILDIN_TYPES
589 | InterpreterFlags::DEFAULT_TYPEDEFS
590 | InterpreterFlags::WITH_XS_ANY_TYPE,
591 }
592 }
593}
594
595impl Default for OptimizerConfig {
596 fn default() -> Self {
597 Self {
598 debug_output: None,
599 flags: OptimizerFlags::REMOVE_EMPTY_ENUM_VARIANTS
600 | OptimizerFlags::REMOVE_EMPTY_ENUMS
601 | OptimizerFlags::REMOVE_DUPLICATE_UNION_VARIANTS
602 | OptimizerFlags::REMOVE_EMPTY_UNIONS,
603 }
604 }
605}
606
607impl Default for GeneratorConfig {
608 fn default() -> Self {
609 Self {
610 types: vec![],
611 derive: None,
612 type_postfix: TypePostfix::default(),
613 dyn_type_traits: None,
614 box_flags: BoxFlags::AUTO,
615 typedef_mode: TypedefMode::Auto,
616 serde_support: SerdeSupport::None,
617 generate: Generate::Named,
618 flags: GeneratorFlags::empty(),
619 xsd_parser: "xsd_parser".into(),
620 renderers: vec![Renderer::Types],
621 }
622 }
623}
624
625impl Default for TypePostfix {
626 fn default() -> Self {
627 Self {
628 type_: String::from("Type"),
629 element: String::new(),
630 element_type: String::from("ElementType"),
631 }
632 }
633}
634
635/* IdentTriple */
636
637impl IdentTriple {
638 /// Resolve the triple to an actual type that is available in the schema.
639 ///
640 /// # Errors
641 ///
642 /// Returns an error if the namespace or the namespace prefix could not be
643 /// resolved.
644 pub fn resolve(self, schemas: &Schemas) -> Result<Ident, InterpreterError> {
645 let ns = match self.ns {
646 None => None,
647 Some(NamespaceIdent::Prefix(prefix)) => Some(
648 schemas
649 .resolve_prefix(&prefix)
650 .ok_or(InterpreterError::UnknownNamespacePrefix(prefix))?,
651 ),
652 #[allow(clippy::unnecessary_literal_unwrap)]
653 Some(NamespaceIdent::Namespace(ns)) => {
654 let ns = Some(ns);
655 Some(
656 schemas
657 .resolve_namespace(&ns)
658 .ok_or_else(|| InterpreterError::UnknownNamespace(ns.unwrap()))?,
659 )
660 }
661 };
662
663 Ok(Ident {
664 ns,
665 name: Name::new_named(self.name),
666 type_: self.type_,
667 })
668 }
669}
670
671impl<X> From<(IdentType, X)> for IdentTriple
672where
673 X: AsRef<str>,
674{
675 fn from((type_, ident): (IdentType, X)) -> Self {
676 let ident = ident.as_ref();
677 let (prefix, name) = ident
678 .split_once(':')
679 .map_or((None, ident), |(a, b)| (Some(a), b));
680 let ns = prefix.map(|x| NamespaceIdent::prefix(x.as_bytes().to_owned()));
681 let name = name.to_owned();
682
683 Self { ns, name, type_ }
684 }
685}
686
687impl<N, X> From<(IdentType, N, X)> for IdentTriple
688where
689 N: Into<Option<NamespaceIdent>>,
690 X: Into<String>,
691{
692 fn from((type_, ns, name): (IdentType, N, X)) -> Self {
693 let ns = ns.into();
694 let name = name.into();
695
696 Self { ns, name, type_ }
697 }
698}
699
700/* NamespaceIdent */
701
702impl NamespaceIdent {
703 /// Creates a new [`NamespaceIdent::Prefix`] instance from the passed `value`.
704 pub fn prefix<X>(value: X) -> Self
705 where
706 NamespacePrefix: From<X>,
707 {
708 Self::Prefix(NamespacePrefix::from(value))
709 }
710
711 /// Creates a new [`NamespaceIdent::Namespace`] instance from the passed `value`.
712 pub fn namespace<X>(value: X) -> Self
713 where
714 Namespace: From<X>,
715 {
716 Self::Namespace(Namespace::from(value))
717 }
718}
719
720impl From<Namespace> for NamespaceIdent {
721 fn from(value: Namespace) -> Self {
722 Self::Namespace(value)
723 }
724}
725
726impl From<NamespacePrefix> for NamespaceIdent {
727 fn from(value: NamespacePrefix) -> Self {
728 Self::Prefix(value)
729 }
730}