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#[derive(Debug, Clone)]
179pub struct IdentTriple {
180 /// Namespace the type is defined in.
181 pub ns: Option<NamespaceIdent>,
182
183 /// Name of the type.
184 pub name: String,
185
186 /// Type of the identifier (because pure names are not unique in XSD).
187 pub type_: IdentType,
188}
189
190/// Identifies a namespace by either it's known prefix or by the namespace directly.
191#[derive(Debug, Clone)]
192pub enum NamespaceIdent {
193 /// Uses a namespace prefix to refer to a specific namespace in the schema.
194 Prefix(NamespacePrefix),
195
196 /// Uses the full namespace to refer to a specific namespace in the schema.
197 Namespace(Namespace),
198}
199
200/// Configuration for the [`Renderer`](crate::generator::renderer::Renderer)s
201/// the [`Generator`](crate::Generator) should use for rendering the code.
202#[derive(Debug, Clone, Copy, Eq, PartialEq)]
203pub enum Renderer {
204 /// Render to render the pure types.
205 Types,
206
207 /// Renderer to render associated methods that return the default values
208 /// of the different fields of a struct.
209 Defaults,
210
211 /// Renderer to add constants for the namespaces to the generated code.
212 NamespaceConstants,
213
214 /// Renderer that adds the [`WithNamespace`](crate::WithNamespace) trait to
215 /// the generated types.
216 WithNamespaceTrait,
217
218 /// Renderer that renders code for the the `quick_xml` serializer of the
219 /// different types.
220 QuickXmlSerialize,
221
222 /// Renderer that renders code for the the `quick_xml` deserializer of the
223 /// different types.
224 QuickXmlDeserialize,
225}
226
227bitflags! {
228 /// Flags to control the [`Parser`](crate::Parser).
229 #[derive(Debug, Clone)]
230 pub struct ParserFlags: u32 {
231 /// Whether the parser should resolve `xs:include` and `xs:import` elements
232 /// or not.
233 ///
234 /// See [`resolve_includes`](crate::Parser::resolve_includes) for details.
235 const RESOLVE_INCLUDES = 1 << 0;
236
237 /// Whether to add the default namespaces to the parser or not.
238 ///
239 /// See [`with_default_namespaces`](crate::Parser::with_default_namespaces) for details.
240 const DEFAULT_NAMESPACES = 1 << 1;
241 }
242}
243
244bitflags! {
245 /// Flags to control the [`Interpreter`](crate::Interpreter).
246 #[derive(Debug, Clone)]
247 pub struct InterpreterFlags: u32 {
248 /// Whether to add the build-in types to the interpreter or not.
249 ///
250 /// See [`with_buildin_types`](crate::Interpreter::with_buildin_types) for details.
251 const BUILDIN_TYPES = 1 << 0;
252
253 /// Whether to add the default types definitions to the interpreter or not.
254 ///
255 /// See [`with_default_typedefs`](crate::Interpreter::with_default_typedefs) for details.
256 const DEFAULT_TYPEDEFS = 1 << 1;
257
258 /// Whether to add a default type definitions for `xs:anyType` or not.
259 ///
260 /// See [`with_xs_any_type`](crate::Interpreter::with_xs_any_type) for details.
261 const WITH_XS_ANY_TYPE = 1 << 2;
262 }
263}
264
265bitflags! {
266 /// Flags to control the [`Optimizer`](crate::Optimizer).
267 #[derive(Debug, Clone)]
268 pub struct OptimizerFlags: u32 {
269 /// Whether to remove empty enum variants or not.
270 ///
271 /// See [`remove_empty_enum_variants`](crate::Optimizer::remove_empty_enum_variants) for details.
272 const REMOVE_EMPTY_ENUM_VARIANTS = 1 << 0;
273
274 /// Whether to remove empty enums or not.
275 ///
276 /// See [`remove_empty_enums`](crate::Optimizer::remove_empty_enums) for details.
277 const REMOVE_EMPTY_ENUMS = 1 << 1;
278
279 /// Whether to remove duplicate union variants or not.
280 ///
281 /// See [`remove_duplicate_union_variants`](crate::Optimizer::remove_duplicate_union_variants) for details.
282 const REMOVE_DUPLICATE_UNION_VARIANTS = 1 << 2;
283
284 /// Whether to remove empty unions or not.
285 ///
286 /// See [`remove_empty_unions`](crate::Optimizer::remove_empty_unions) for details.
287 const REMOVE_EMPTY_UNIONS = 1 << 3;
288
289 /// Whether to use the unrestricted base type of a type or not.
290 ///
291 /// See [`use_unrestricted_base_type`](crate::Optimizer::use_unrestricted_base_type) for details.
292 const USE_UNRESTRICTED_BASE_TYPE = 1 << 4;
293
294 /// Whether to convert dynamic types to choices or not.
295 ///
296 /// See [`convert_dynamic_to_choice`](crate::Optimizer::convert_dynamic_to_choice) for details.
297 const CONVERT_DYNAMIC_TO_CHOICE = 1 << 5;
298
299 /// Whether to flatten the content of complex types or not.
300 ///
301 /// See [`flatten_complex_types`](crate::Optimizer::flatten_complex_types) for details.
302 const FLATTEN_COMPLEX_TYPES = 1 << 6;
303
304 /// Whether to flatten unions or not.
305 ///
306 /// See [`flatten_unions`](crate::Optimizer::flatten_unions) for details.
307 const FLATTEN_UNIONS = 1 << 7;
308
309 /// Whether to merge enumerations and unions or not.
310 ///
311 /// See [`merge_enum_unions`](crate::Optimizer::merge_enum_unions) for details.
312 const MERGE_ENUM_UNIONS = 1 << 8;
313
314 /// Whether to resolve type definitions or not.
315 ///
316 /// See [`resolve_typedefs`](crate::Optimizer::resolve_typedefs) for details.
317 const RESOLVE_TYPEDEFS = 1 << 9;
318
319 /// Whether to remove duplicate types or not.
320 ///
321 /// See [`remove_duplicates`](crate::Optimizer::remove_duplicates) for details.
322 const REMOVE_DUPLICATES = 1 << 10;
323
324 /// Group that contains all necessary optimization that should be applied
325 /// if code with [`serde`] support should be rendered.
326 const SERDE = Self::FLATTEN_COMPLEX_TYPES.bits()
327 | Self::FLATTEN_UNIONS.bits()
328 | Self::MERGE_ENUM_UNIONS.bits();
329
330 /// Wether to merge the cardinality of a complex choice type or not.
331 ///
332 /// See [`merge_choice_cardinalities`](crate::Optimizer::merge_choice_cardinalities) for details.
333 const MERGE_CHOICE_CARDINALITIES = 1 << 11;
334 }
335}
336
337impl Config {
338 /// Set parser flags to the config.
339 pub fn set_parser_flags(mut self, flags: ParserFlags) -> Self {
340 self.parser.flags = flags;
341
342 self
343 }
344
345 /// Add parser flags to the config.
346 pub fn with_parser_flags(mut self, flags: ParserFlags) -> Self {
347 self.parser.flags.insert(flags);
348
349 self
350 }
351
352 /// Remove parser flags to the config.
353 pub fn without_parser_flags(mut self, flags: ParserFlags) -> Self {
354 self.parser.flags.remove(flags);
355
356 self
357 }
358
359 /// Set interpreter flags to the config.
360 pub fn set_interpreter_flags(mut self, flags: InterpreterFlags) -> Self {
361 self.interpreter.flags = flags;
362
363 self
364 }
365
366 /// Add code interpreter flags to the config.
367 pub fn with_interpreter_flags(mut self, flags: InterpreterFlags) -> Self {
368 self.interpreter.flags.insert(flags);
369
370 self
371 }
372
373 /// Remove code interpreter flags to the config.
374 pub fn without_interpreter_flags(mut self, flags: InterpreterFlags) -> Self {
375 self.interpreter.flags.remove(flags);
376
377 self
378 }
379
380 /// Set optimizer flags to the config.
381 pub fn set_optimizer_flags(mut self, flags: OptimizerFlags) -> Self {
382 self.optimizer.flags = flags;
383
384 self
385 }
386
387 /// Add optimizer flags to the config.
388 pub fn with_optimizer_flags(mut self, flags: OptimizerFlags) -> Self {
389 self.optimizer.flags.insert(flags);
390
391 self
392 }
393
394 /// Remove optimizer flags to the config.
395 pub fn without_optimizer_flags(mut self, flags: OptimizerFlags) -> Self {
396 self.optimizer.flags.remove(flags);
397
398 self
399 }
400
401 /// Set generator flags to the config.
402 pub fn set_generator_flags(mut self, flags: GeneratorFlags) -> Self {
403 self.generator.flags = flags;
404
405 self
406 }
407
408 /// Add code generator flags to the config.
409 pub fn with_generator_flags(mut self, flags: GeneratorFlags) -> Self {
410 self.generator.flags.insert(flags);
411
412 self
413 }
414
415 /// Remove code generator flags to the config.
416 pub fn without_generator_flags(mut self, flags: GeneratorFlags) -> Self {
417 self.generator.flags.remove(flags);
418
419 self
420 }
421
422 /// Set boxing flags to the code generator config.
423 pub fn set_box_flags(mut self, flags: BoxFlags) -> Self {
424 self.generator.box_flags = flags;
425
426 self
427 }
428
429 /// Add boxing flags to the code generator config.
430 pub fn with_box_flags(mut self, flags: BoxFlags) -> Self {
431 self.generator.box_flags.insert(flags);
432
433 self
434 }
435
436 /// Remove boxing flags to the code generator config.
437 pub fn without_box_flags(mut self, flags: BoxFlags) -> Self {
438 self.generator.box_flags.remove(flags);
439
440 self
441 }
442
443 /// Adds the passed `renderer` to the config.
444 ///
445 /// If the same type of renderer was already added,
446 /// it is replaced by the new one.
447 pub fn with_renderer(mut self, renderer: Renderer) -> Self {
448 if let Some(index) = self.generator.renderers.iter().position(|x| x == &renderer) {
449 self.generator.renderers[index] = renderer;
450 } else {
451 self.generator.renderers.push(renderer);
452 }
453
454 self
455 }
456
457 /// Add multiple renderers to the generator config.
458 ///
459 /// See [`with_renderer`](Self::with_renderer) for details.
460 pub fn with_renderers<I>(mut self, renderers: I) -> Self
461 where
462 I: IntoIterator<Item = Renderer>,
463 {
464 for renderer in renderers {
465 self = self.with_renderer(renderer);
466 }
467
468 self
469 }
470
471 /// Enable code generation for [`quick_xml`] serialization.
472 pub fn with_quick_xml_serialize(self) -> Self {
473 self.with_renderers([
474 Renderer::Types,
475 Renderer::Defaults,
476 Renderer::NamespaceConstants,
477 Renderer::QuickXmlSerialize,
478 ])
479 }
480
481 /// Enable code generation for [`quick_xml`] deserialization.
482 pub fn with_quick_xml_deserialize(self) -> Self {
483 self.with_renderers([
484 Renderer::Types,
485 Renderer::Defaults,
486 Renderer::NamespaceConstants,
487 Renderer::QuickXmlDeserialize,
488 ])
489 }
490
491 /// Enable code generation for [`quick_xml`] serialization and deserialization.
492 pub fn with_quick_xml(self) -> Self {
493 self.with_quick_xml_serialize().with_quick_xml_deserialize()
494 }
495
496 /// Set the [`serde`] support.
497 pub fn with_serde_support(mut self, serde_support: SerdeSupport) -> Self {
498 self.generator.serde_support = serde_support;
499
500 if self.generator.serde_support != SerdeSupport::None {
501 self.optimizer.flags |= OptimizerFlags::SERDE;
502 }
503
504 self
505 }
506
507 /// Set the types the code should be generated for.
508 pub fn with_generate<I>(mut self, types: I) -> Self
509 where
510 I: IntoIterator,
511 I::Item: Into<IdentTriple>,
512 {
513 self.generator.generate = Generate::Types(types.into_iter().map(Into::into).collect());
514
515 self
516 }
517
518 /// Set the typedef mode for the generator.
519 pub fn with_typedef_mode(mut self, mode: TypedefMode) -> Self {
520 self.generator.typedef_mode = mode;
521
522 self
523 }
524
525 /// Set the traits the generated types should derive from.
526 pub fn with_derive<I>(mut self, derive: I) -> Self
527 where
528 I: IntoIterator,
529 I::Item: Into<String>,
530 {
531 self.generator.derive = Some(
532 derive
533 .into_iter()
534 .map(Into::into)
535 .filter(|s| !s.is_empty())
536 .collect(),
537 );
538
539 self
540 }
541}
542
543impl Default for ParserConfig {
544 fn default() -> Self {
545 Self {
546 resolver: vec![Resolver::File],
547 schemas: vec![],
548 namespaces: vec![],
549 flags: ParserFlags::RESOLVE_INCLUDES | ParserFlags::DEFAULT_NAMESPACES,
550 debug_output: None,
551 }
552 }
553}
554
555impl Default for InterpreterConfig {
556 fn default() -> Self {
557 Self {
558 types: vec![],
559 debug_output: None,
560 flags: InterpreterFlags::BUILDIN_TYPES
561 | InterpreterFlags::DEFAULT_TYPEDEFS
562 | InterpreterFlags::WITH_XS_ANY_TYPE,
563 }
564 }
565}
566
567impl Default for OptimizerConfig {
568 fn default() -> Self {
569 Self {
570 debug_output: None,
571 flags: OptimizerFlags::REMOVE_EMPTY_ENUM_VARIANTS
572 | OptimizerFlags::REMOVE_EMPTY_ENUMS
573 | OptimizerFlags::REMOVE_DUPLICATE_UNION_VARIANTS
574 | OptimizerFlags::REMOVE_EMPTY_UNIONS,
575 }
576 }
577}
578
579impl Default for GeneratorConfig {
580 fn default() -> Self {
581 Self {
582 types: vec![],
583 derive: None,
584 type_postfix: TypePostfix::default(),
585 dyn_type_traits: None,
586 box_flags: BoxFlags::AUTO,
587 typedef_mode: TypedefMode::Auto,
588 serde_support: SerdeSupport::None,
589 generate: Generate::Named,
590 flags: GeneratorFlags::empty(),
591 xsd_parser: "xsd_parser".into(),
592 renderers: vec![Renderer::Types],
593 }
594 }
595}
596
597impl Default for TypePostfix {
598 fn default() -> Self {
599 Self {
600 type_: String::from("Type"),
601 element: String::new(),
602 element_type: String::from("ElementType"),
603 }
604 }
605}
606
607/* IdentTriple */
608
609impl IdentTriple {
610 /// Resolve the triple to an actual type that is available in the schema.
611 ///
612 /// # Errors
613 ///
614 /// Returns an error if the namespace or the namespace prefix could not be
615 /// resolved.
616 pub fn resolve(self, schemas: &Schemas) -> Result<Ident, InterpreterError> {
617 let ns = match self.ns {
618 None => None,
619 Some(NamespaceIdent::Prefix(prefix)) => Some(
620 schemas
621 .resolve_prefix(&prefix)
622 .ok_or(InterpreterError::UnknownNamespacePrefix(prefix))?,
623 ),
624 #[allow(clippy::unnecessary_literal_unwrap)]
625 Some(NamespaceIdent::Namespace(ns)) => {
626 let ns = Some(ns);
627 Some(
628 schemas
629 .resolve_namespace(&ns)
630 .ok_or_else(|| InterpreterError::UnknownNamespace(ns.unwrap()))?,
631 )
632 }
633 };
634
635 Ok(Ident {
636 ns,
637 name: Name::new_named(self.name),
638 type_: self.type_,
639 })
640 }
641}
642
643impl<X> From<(IdentType, X)> for IdentTriple
644where
645 X: AsRef<str>,
646{
647 fn from((type_, ident): (IdentType, X)) -> Self {
648 let ident = ident.as_ref();
649 let (prefix, name) = ident
650 .split_once(':')
651 .map_or((None, ident), |(a, b)| (Some(a), b));
652 let ns = prefix.map(|x| NamespaceIdent::prefix(x.as_bytes().to_owned()));
653 let name = name.to_owned();
654
655 Self { ns, name, type_ }
656 }
657}
658
659impl<N, X> From<(IdentType, N, X)> for IdentTriple
660where
661 N: Into<Option<NamespaceIdent>>,
662 X: Into<String>,
663{
664 fn from((type_, ns, name): (IdentType, N, X)) -> Self {
665 let ns = ns.into();
666 let name = name.into();
667
668 Self { ns, name, type_ }
669 }
670}
671
672/* NamespaceIdent */
673
674impl NamespaceIdent {
675 /// Creates a new [`NamespaceIdent::Prefix`] instance from the passed `value`.
676 pub fn prefix<X>(value: X) -> Self
677 where
678 NamespacePrefix: From<X>,
679 {
680 Self::Prefix(NamespacePrefix::from(value))
681 }
682
683 /// Creates a new [`NamespaceIdent::Namespace`] instance from the passed `value`.
684 pub fn namespace<X>(value: X) -> Self
685 where
686 Namespace: From<X>,
687 {
688 Self::Namespace(Namespace::from(value))
689 }
690}
691
692impl From<Namespace> for NamespaceIdent {
693 fn from(value: Namespace) -> Self {
694 Self::Namespace(value)
695 }
696}
697
698impl From<NamespacePrefix> for NamespaceIdent {
699 fn from(value: NamespacePrefix) -> Self {
700 Self::Prefix(value)
701 }
702}