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}