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, ContentMode, GenerateFlags, SerdeSupport, TypedefMode};
9pub use crate::schema::{Namespace, NamespacePrefix};
10pub use crate::types::{IdentType, Type};
11
12/// Configuration structure for the [`generate`](super::generate) method.
13#[must_use]
14#[derive(Default, Debug, Clone)]
15pub struct Config {
16    /// Configuration for the schema parser.
17    pub parser: ParserConfig,
18
19    /// Configuration for the schema interpreter.
20    pub interpreter: InterpreterConfig,
21
22    /// Configuration for the type information optimizer.
23    pub optimizer: OptimizerConfig,
24
25    /// Configuration for the code generator.
26    pub generator: GeneratorConfig,
27}
28
29/// Configuration for the schema parser.
30#[derive(Debug, Clone)]
31pub struct ParserConfig {
32    /// List of resolvers to use for resolving referenced schemas.
33    pub resolver: Vec<Resolver>,
34
35    /// List of namespaces to add to the parser before the schemas are loaded.
36    ///
37    /// See [`with_namespace`](crate::Parser::with_namespace) for more details.
38    pub namespaces: Vec<(NamespacePrefix, Namespace)>,
39
40    /// List of schemas to load.
41    pub schemas: Vec<Schema>,
42
43    /// Additional flags to control the parser.
44    pub flags: ParserFlags,
45
46    /// Wether to enable the debug output and where to write it to.
47    pub debug_output: Option<PathBuf>,
48}
49
50/// Configuration for the schema interpreter.
51#[derive(Debug, Clone)]
52pub struct InterpreterConfig {
53    /// List of user defined types to add to the interpreter before the schemas
54    /// are actually interpreted.
55    ///
56    /// See [`with_type`](crate::Interpreter::with_type) for more details.
57    pub types: Vec<(IdentType, String, Type)>,
58
59    /// Additional flags to control the interpreter.
60    pub flags: InterpreterFlags,
61
62    /// Wether to enable the debug output and where to write it to.
63    pub debug_output: Option<PathBuf>,
64}
65
66/// Configuration for the type information optimizer.
67#[derive(Debug, Clone)]
68pub struct OptimizerConfig {
69    /// Additional flags to control the optimizer.
70    pub flags: OptimizerFlags,
71
72    /// Wether to enable the debug output and where to write it to.
73    pub debug_output: Option<PathBuf>,
74}
75
76/// Configuration for the code generator.
77#[derive(Debug, Clone)]
78pub struct GeneratorConfig {
79    /// Types to add to the generator before the actual code is generated.
80    ///
81    /// See [`with_type`](crate::Generator::with_type) for more details.
82    pub types: Vec<(IdentType, String)>,
83
84    /// Sets the traits the generated types should derive from.
85    ///
86    /// See [`derive`](crate::Generator::derive) for more details.
87    pub derive: Option<Vec<String>>,
88
89    /// Set the traits that should be implemented by dynamic types.
90    ///
91    /// See [`dyn_type_traits`](crate::Generator::dyn_type_traits) for more details.
92    pub dyn_type_traits: Option<Vec<String>>,
93
94    /// Postfixes that should be applied to the name of the different generated
95    /// types.
96    ///
97    /// See [`with_type_postfix`](crate::Generator::with_type_postfix) for more details.
98    pub type_postfix: TypePostfix,
99
100    /// Tell the generator how to deal with boxing.
101    pub box_flags: BoxFlags,
102
103    /// Tell the generator what type should be generated for the content of an XML element.
104    pub content_mode: ContentMode,
105
106    /// Tells the generator how to deal with type definitions.
107    pub typedef_mode: TypedefMode,
108
109    /// Tells the generator how to generate code for the [`serde`] crate.
110    pub serde_support: SerdeSupport,
111
112    /// Specify which types the generator should generate code for.
113    pub generate: Generate,
114
115    /// Additional flags to control the generator.
116    pub flags: GenerateFlags,
117
118    /// Name of the `xsd-parser` crate that is used for the generated code.
119    pub xsd_parser: String,
120}
121
122/// Postfixed that will be added to the different types generated by the code generator.
123#[derive(Debug, Clone)]
124pub struct TypePostfix {
125    /// Postfix added to normal types (like `xs:simpleType` or `xs:complexType`).
126    pub type_: String,
127
128    /// Postfixes added to elements (like `xs:element`).
129    pub element: String,
130
131    /// Postfixes added to inline types if elements (like `xs:element`).
132    pub element_type: String,
133}
134
135/// Configuration for the resolver used in [`ParserConfig`].
136#[derive(Debug, Clone)]
137pub enum Resolver {
138    /// Resolver that is used to resolve ewb resources (like `http://...` or `https://...`).
139    #[cfg(feature = "web-resolver")]
140    Web,
141
142    /// Resolver that is used to resolve local resources from disk (like `./local-schema.xsd` or `file://...`).
143    File,
144}
145
146/// Configuration for the schemas to load used in [`ParserConfig`].
147#[derive(Debug, Clone)]
148pub enum Schema {
149    /// Load a schema from the provided URL.
150    Url(Url),
151
152    /// Load a schema from the provided file path.
153    File(PathBuf),
154
155    /// Load the schema from the provided string.
156    Schema(String),
157}
158
159/// Configuration which types the [`Generator`](crate::Generator) should generate
160/// code for used in [`GeneratorConfig`].
161#[derive(Debug, Clone)]
162pub enum Generate {
163    /// The generator will generate code for all types of the schemas.
164    All,
165
166    /// List of identifiers the generator will generate code for.
167    ///
168    /// A type is a combination of a identifier type and a string like so:
169    /// - `(IdentType::Type, "xs:int")`
170    /// - `(IdentType::Element, "example:rootElement")`
171    Types(Vec<(IdentType, String)>),
172}
173
174bitflags! {
175    /// Flags to control the [`Parser`](crate::Parser).
176    #[derive(Debug, Clone)]
177    pub struct ParserFlags: u32 {
178        /// Whether the parser should resolve `xs:include` and `xs:import` elements
179        /// or not.
180        ///
181        /// See [`resolve_includes`](crate::Parser::resolve_includes) for details.
182        const RESOLVE_INCLUDES = 1 << 0;
183
184        /// Whether to add the default namespaces to the parser or not.
185        ///
186        /// See [`with_default_namespaces`](crate::Parser::with_default_namespaces) for details.
187        const DEFAULT_NAMESPACES = 1 << 1;
188    }
189}
190
191bitflags! {
192    /// Flags to control the [`Interpreter`](crate::Interpreter).
193    #[derive(Debug, Clone)]
194    pub struct InterpreterFlags: u32 {
195        /// Whether to add the build-in types to the interpreter or not.
196        ///
197        /// See [`with_buildin_types`](crate::Interpreter::with_buildin_types) for details.
198        const BUILDIN_TYPES = 1 << 0;
199
200        /// Whether to add the default types definitions to the interpreter or not.
201        ///
202        /// See [`with_default_typedefs`](crate::Interpreter::with_default_typedefs) for details.
203        const DEFAULT_TYPEDEFS = 1 << 1;
204
205        /// Whether to add a default type definitions for `xs:anyType` or not.
206        ///
207        /// See [`with_xs_any_type`](crate::Interpreter::with_xs_any_type) for details.
208        const WITH_XS_ANY_TYPE = 1 << 2;
209    }
210}
211
212bitflags! {
213    /// Flags to control the [`Optimizer`](crate::Optimizer).
214    #[derive(Debug, Clone)]
215    pub struct OptimizerFlags: u32 {
216        /// Whether to remove empty enum variants or not.
217        ///
218        /// See [`remove_empty_enum_variants`](crate::Optimizer::remove_empty_enum_variants) for details.
219        const REMOVE_EMPTY_ENUM_VARIANTS = 1 << 0;
220
221        /// Whether to remove empty enums or not.
222        ///
223        /// See [`remove_empty_enums`](crate::Optimizer::remove_empty_enums) for details.
224        const REMOVE_EMPTY_ENUMS = 1 << 1;
225
226        /// Whether to remove duplicate union variants or not.
227        ///
228        /// See [`remove_duplicate_union_variants`](crate::Optimizer::remove_duplicate_union_variants) for details.
229        const REMOVE_DUPLICATE_UNION_VARIANTS = 1 << 2;
230
231        /// Whether to remove empty unions or not.
232        ///
233        /// See [`remove_empty_unions`](crate::Optimizer::remove_empty_unions) for details.
234        const REMOVE_EMPTY_UNIONS = 1 << 3;
235
236        /// Whether to use the unrestricted base type of a type or not.
237        ///
238        /// See [`use_unrestricted_base_type`](crate::Optimizer::use_unrestricted_base_type) for details.
239        const USE_UNRESTRICTED_BASE_TYPE = 1 << 4;
240
241        /// Whether to convert dynamic types to choices or not.
242        ///
243        /// See [`convert_dynamic_to_choice`](crate::Optimizer::convert_dynamic_to_choice) for details.
244        const CONVERT_DYNAMIC_TO_CHOICE = 1 << 5;
245
246        /// Whether to flatten the content of an element or not.
247        ///
248        /// See [`flatten_element_content`](crate::Optimizer::flatten_element_content) for details.
249        const FLATTEN_ELEMENT_CONTENT = 1 << 6;
250
251        /// Whether to flatten unions or not.
252        ///
253        /// See [`flatten_unions`](crate::Optimizer::flatten_unions) for details.
254        const FLATTEN_UNIONS = 1 << 7;
255
256        /// Whether to merge enumerations and unions or not.
257        ///
258        /// See [`merge_enum_unions`](crate::Optimizer::merge_enum_unions) for details.
259        const MERGE_ENUM_UNIONS = 1 << 8;
260
261        /// Whether to resolve type definitions or not.
262        ///
263        /// See [`resolve_typedefs`](crate::Optimizer::resolve_typedefs) for details.
264        const RESOLVE_TYPEDEFS = 1 << 9;
265
266        /// Whether to remove duplicate types or not.
267        ///
268        /// See [`remove_duplicates`](crate::Optimizer::remove_duplicates) for details.
269        const REMOVE_DUPLICATES = 1 << 10;
270
271        /// Group that contains all necessary optimization that should be applied
272        /// if code with [`serde`] support should be rendered.
273        const SERDE =  Self::FLATTEN_ELEMENT_CONTENT.bits()
274            | Self::FLATTEN_UNIONS.bits()
275            | Self::MERGE_ENUM_UNIONS.bits();
276    }
277}
278
279impl Config {
280    /// Add optimizer flags to the config.
281    pub fn with_optimizer_flags(mut self, flags: OptimizerFlags) -> Self {
282        self.optimizer.flags.insert(flags);
283
284        self
285    }
286
287    /// Remove optimizer flags to the config.
288    pub fn without_optimizer_flags(mut self, flags: OptimizerFlags) -> Self {
289        self.optimizer.flags.remove(flags);
290
291        self
292    }
293
294    /// Add code generator flags to the config.
295    pub fn with_generate_flags(mut self, flags: GenerateFlags) -> Self {
296        self.generator.flags.insert(flags);
297
298        self
299    }
300
301    /// Remove code generator flags to the config.
302    pub fn without_generate_flags(mut self, flags: GenerateFlags) -> Self {
303        self.generator.flags.remove(flags);
304
305        self
306    }
307
308    /// Add boxing flags to the code generator config.
309    pub fn with_box_flags(mut self, flags: BoxFlags) -> Self {
310        self.generator.box_flags.insert(flags);
311
312        self
313    }
314
315    /// Remove boxing flags to the code generator config.
316    pub fn without_box_flags(mut self, flags: BoxFlags) -> Self {
317        self.generator.box_flags.remove(flags);
318
319        self
320    }
321
322    /// Enable code generation for [`quick_xml`] serialization and deserialization.
323    pub fn with_quick_xml(mut self) -> Self {
324        self.generator.flags |= GenerateFlags::QUICK_XML | GenerateFlags::FLATTEN_CONTENT;
325
326        self
327    }
328
329    /// Set the [`serde`] support.
330    pub fn with_serde_support(mut self, serde_support: SerdeSupport) -> Self {
331        self.generator.serde_support = serde_support;
332
333        if self.generator.serde_support != SerdeSupport::None {
334            self.optimizer.flags |= OptimizerFlags::SERDE;
335        }
336
337        self
338    }
339
340    /// Set the types the code should be generated for.
341    pub fn with_generate<I, T>(mut self, types: I) -> Self
342    where
343        I: IntoIterator<Item = (IdentType, T)>,
344        T: Into<String>,
345    {
346        self.generator.generate =
347            Generate::Types(types.into_iter().map(|(a, b)| (a, b.into())).collect());
348
349        self
350    }
351
352    /// Set the content mode for the generator.
353    pub fn with_content_mode(mut self, mode: ContentMode) -> Self {
354        self.generator.content_mode = mode;
355
356        self
357    }
358
359    /// Set the typedef mode for the generator.
360    pub fn with_typedef_mode(mut self, mode: TypedefMode) -> Self {
361        self.generator.typedef_mode = mode;
362
363        self
364    }
365
366    /// Set the traits the generated types should derive from.
367    pub fn with_derive<I>(mut self, derive: I) -> Self
368    where
369        I: IntoIterator,
370        I::Item: Into<String>,
371    {
372        self.generator.derive = Some(
373            derive
374                .into_iter()
375                .map(Into::into)
376                .filter(|s| !s.is_empty())
377                .collect(),
378        );
379
380        self
381    }
382}
383
384impl Default for ParserConfig {
385    fn default() -> Self {
386        Self {
387            resolver: vec![Resolver::File],
388            schemas: vec![],
389            namespaces: vec![],
390            flags: ParserFlags::RESOLVE_INCLUDES | ParserFlags::DEFAULT_NAMESPACES,
391            debug_output: None,
392        }
393    }
394}
395
396impl Default for InterpreterConfig {
397    fn default() -> Self {
398        Self {
399            types: vec![],
400            debug_output: None,
401            flags: InterpreterFlags::BUILDIN_TYPES
402                | InterpreterFlags::DEFAULT_TYPEDEFS
403                | InterpreterFlags::WITH_XS_ANY_TYPE,
404        }
405    }
406}
407
408impl Default for OptimizerConfig {
409    fn default() -> Self {
410        Self {
411            debug_output: None,
412            flags: OptimizerFlags::REMOVE_EMPTY_ENUM_VARIANTS
413                | OptimizerFlags::REMOVE_EMPTY_ENUMS
414                | OptimizerFlags::REMOVE_DUPLICATE_UNION_VARIANTS
415                | OptimizerFlags::REMOVE_EMPTY_UNIONS,
416        }
417    }
418}
419
420impl Default for GeneratorConfig {
421    fn default() -> Self {
422        Self {
423            types: vec![],
424            derive: None,
425            type_postfix: TypePostfix::default(),
426            dyn_type_traits: None,
427            box_flags: BoxFlags::AUTO,
428            content_mode: ContentMode::Auto,
429            typedef_mode: TypedefMode::Auto,
430            serde_support: SerdeSupport::None,
431            generate: Generate::All,
432            flags: GenerateFlags::empty(),
433            xsd_parser: "xsd_parser".into(),
434        }
435    }
436}
437
438impl Default for TypePostfix {
439    fn default() -> Self {
440        Self {
441            type_: String::from("Type"),
442            element: String::new(),
443            element_type: String::from("ElementType"),
444        }
445    }
446}