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}