Skip to main content

xsd_parser/config/
generator.rs

1use bitflags::bitflags;
2
3use super::IdentQuadruple;
4
5/// Configuration for the code generator.
6#[derive(Debug, Clone)]
7pub struct GeneratorConfig {
8    /// Additional flags to control the generator.
9    pub flags: GeneratorFlags,
10
11    /// Types to add to the generator before the actual data types are generated.
12    ///
13    /// See [`with_type`](crate::Generator::with_type) for more details.
14    pub types: Vec<IdentQuadruple>,
15
16    /// Specify which meta types the generator should generate data types for.
17    pub generate: Generate,
18
19    /// Postfixes that should be applied to the name of the different generated
20    /// types.
21    ///
22    /// See [`with_type_postfix`](crate::Generator::with_type_postfix) for more details.
23    pub type_postfix: TypePostfix,
24
25    /// Tell the generator how to deal with boxing.
26    pub box_flags: BoxFlags,
27
28    /// Tells the generator how to deal with type definitions.
29    pub typedef_mode: TypedefMode,
30
31    /// Type to use to store unformatted text.
32    ///
33    /// See [`Generator::text_type`](crate::Generator::text_type) for details.
34    pub text_type: String,
35
36    /// Type to use to store mixed types.
37    ///
38    /// See [`Generator::mixed_type`](crate::Generator::mixed_type) for details.
39    pub mixed_type: String,
40
41    /// Type to use to store nillable types.
42    ///
43    /// See [`Generator::nillable_type`](crate::Generator::nillable_type) for details.
44    pub nillable_type: String,
45
46    /// Type to use to store unstructured `xs:any` elements.
47    ///
48    /// See [`Generator::any_type`](crate::Generator::any_type) for details.
49    pub any_type: String,
50
51    /// Type to use to store unstructured `xs:anyAttribute` attributes.
52    ///
53    /// See [`Generator::any_attributes_type`](crate::Generator::any_attributes_type)
54    /// for details.
55    pub any_attributes_type: String,
56}
57
58impl Default for GeneratorConfig {
59    fn default() -> Self {
60        Self {
61            types: vec![],
62            type_postfix: TypePostfix::default(),
63            box_flags: BoxFlags::AUTO,
64            typedef_mode: TypedefMode::Auto,
65            generate: Generate::Named,
66            flags: GeneratorFlags::empty(),
67            text_type: "::xsd_parser_types::xml::Text".into(),
68            mixed_type: "::xsd_parser_types::xml::Mixed".into(),
69            nillable_type: "::xsd_parser_types::xml::Nillable".into(),
70            any_type: "::xsd_parser_types::xml::AnyElement".into(),
71            any_attributes_type: "::xsd_parser_types::xml::AnyAttributes".into(),
72        }
73    }
74}
75
76bitflags! {
77    /// Different flags that control what code the [`Generator`](crate::Generator)
78    /// is generating.
79    #[derive(Debug, Clone, Copy)]
80    pub struct GeneratorFlags: u32 {
81        /// None of the features are enabled.
82        ///
83        /// # Examples
84        ///
85        /// Consider the following XML schema:
86        /// ```xml
87        #[doc = include_str!("../../tests/generator/generator_flags/schema.xsd")]
88        /// ```
89        ///
90        /// Setting none of the flags will result in the following code:
91        /// ```rust
92        #[doc = include_str!("../../tests/generator/generator_flags/expected/empty.rs")]
93        /// ```
94        const NONE = 0;
95
96        /// The generated code uses modules for the different namespaces.
97        ///
98        /// # Examples
99        ///
100        /// Consider the following XML schema:
101        /// ```xml
102        #[doc = include_str!("../../tests/generator/generator_flags/schema.xsd")]
103        /// ```
104        ///
105        /// Enable the `USE_MODULES` feature only will result in the following code:
106        /// ```rust,ignore
107        #[doc = include_str!("../../tests/generator/generator_flags/expected/use_modules.rs")]
108        /// ```
109        const USE_MODULES = Self::USE_NAMESPACE_MODULES.bits();
110
111        /// The generated code uses modules for the different namespaces.
112        ///
113        /// See [`USE_MODULES`](Self::USE_MODULES) for details.
114        const USE_NAMESPACE_MODULES = 1 << 0;
115
116        /// The generated code uses modules for the different schemas.
117        ///
118        /// See [`USE_MODULES`](Self::USE_MODULES) for details.
119        const USE_SCHEMA_MODULES = 1 << 1;
120
121        /// The generator flattens the content type of choice types if it does not
122        /// define any element attributes.
123        ///
124        /// # Examples
125        ///
126        /// Consider the following XML schema:
127        /// ```xml
128        #[doc = include_str!("../../tests/generator/generator_flags/schema.xsd")]
129        /// ```
130        ///
131        /// Enable the `FLATTEN_CONTENT` feature only will result in the following code:
132        /// ```rust
133        #[doc = include_str!("../../tests/generator/generator_flags/expected/flatten_content.rs")]
134        /// ```
135        const FLATTEN_CONTENT = Self::FLATTEN_ENUM_CONTENT.bits()
136            | Self::FLATTEN_STRUCT_CONTENT.bits();
137
138        /// The generator flattens the content of enum types if possible.
139        ///
140        /// See [`FLATTEN_CONTENT`](Self::FLATTEN_CONTENT) for details.
141        const FLATTEN_ENUM_CONTENT = 1 << 2;
142
143        /// The generator flattens the content of struct types if possible.
144        ///
145        /// See [`FLATTEN_CONTENT`](Self::FLATTEN_CONTENT) for details.
146        const FLATTEN_STRUCT_CONTENT = 1 << 3;
147
148        /// Enable support for mixed types.
149        ///
150        /// This will enable code generation for mixed types. This feature needs
151        /// to be used with caution, because support for mixed types when using
152        /// `serde` is quite limited.
153        ///
154        /// # Examples
155        ///
156        /// Consider the following XML schema:
157        /// ```xml
158        #[doc = include_str!("../../tests/generator/generator_flags/schema.xsd")]
159        /// ```
160        ///
161        /// Enable the `MIXED_TYPE_SUPPORT` feature only will result in the following code:
162        /// ```rust,ignore
163        #[doc = include_str!("../../tests/generator/generator_flags/expected/mixed_type_support.rs")]
164        /// ```
165        const MIXED_TYPE_SUPPORT = 1 << 4;
166
167        /// Enable support for nillable types.
168        ///
169        /// This will enable code generation for nillable types. This feature needs
170        /// to be used with caution, because support for nillable types when using
171        /// `serde` is quite limited.
172        ///
173        /// # Examples
174        ///
175        /// Consider the following XML schema:
176        /// ```xml
177        #[doc = include_str!("../../tests/generator/generator_flags/schema.xsd")]
178        /// ```
179        ///
180        /// Enable the `NILLABLE_TYPE_SUPPORT` feature only will result in the following code:
181        /// ```rust,ignore
182        #[doc = include_str!("../../tests/generator/generator_flags/expected/nillable_type_support.rs")]
183        /// ```
184        const NILLABLE_TYPE_SUPPORT = 1 << 5;
185
186        /// Enable support for `xs:any` types.
187        ///
188        /// This will enable code generation for `xs:any` types. This feature needs
189        /// to be used with caution, because support for any types when using
190        /// `serde` is quite limited.
191        ///
192        /// # Examples
193        ///
194        /// Consider the following XML schema:
195        /// ```xml
196        #[doc = include_str!("../../tests/generator/generator_flags/schema.xsd")]
197        /// ```
198        ///
199        /// Enable the `ANY_TYPE_SUPPORT` feature only will result in the following code:
200        /// ```rust,ignore
201        #[doc = include_str!("../../tests/generator/generator_flags/expected/any_type_support.rs")]
202        /// ```
203        const ANY_TYPE_SUPPORT = 1 << 6;
204
205        /// Use absolute paths for build-in types and traits.
206        ///
207        /// Using this flag will instruct the generator to use absolute paths
208        /// for build-in types and traits (e.g. `usize`, `String` or `From`) to
209        /// avoid naming conflicts with generated types.
210        ///
211        /// # Examples
212        ///
213        /// Consider the following XML schema:
214        /// ```xml
215        #[doc = include_str!("../../tests/generator/generator_flags/schema.xsd")]
216        /// ```
217        ///
218        /// Enable the `BUILD_IN_ABSOLUTE_PATHS` feature only will result in the following code:
219        /// ```rust,ignore
220        #[doc = include_str!("../../tests/generator/generator_flags/expected/build_in_absolute_paths.rs")]
221        /// ```
222        const BUILD_IN_ABSOLUTE_PATHS = 1 << 7;
223
224        /// Use absolute paths instead of using directives for all non build-in
225        /// types and traits.
226        ///
227        /// Using this flag will instruct the generator to use absolute paths
228        /// for non build-in and generated types and traits to avoid naming
229        /// conflicts with other generated types.
230        ///
231        /// This does not include build-in types (like `usize`, `String` or `From`),
232        /// to use absolute paths for these also, you have to add the
233        /// [`BUILD_IN_ABSOLUTE_PATHS`](Self::BUILD_IN_ABSOLUTE_PATHS) as well.
234        const ABSOLUTE_PATHS_INSTEAD_USINGS = 1 << 8;
235
236        /// Enable support for advanced enums.
237        ///
238        /// This will enable support for advanced enums, which are enums that have
239        /// additional constants or associated functions for the expected values of
240        /// the enum. The values are then used to match the expected values of the
241        /// enum when deserializing instead of doing a simple match on the byte string
242        /// literal.
243        ///
244        /// Caution! If you enable this flag, you have to provide suitable constants
245        /// or associated functions for the expected values of the enum, otherwise
246        /// the generated code will not compile. You can use the
247        /// [`EnumConstantsRenderStep`](crate::pipeline::renderer::EnumConstantsRenderStep)
248        /// or the [`RenderStep::EnumConstants`](super::RenderStep::EnumConstants)
249        /// to generate suitable code for these constants and associated functions.
250        const ADVANCED_ENUMS = 1 << 9;
251    }
252}
253
254bitflags! {
255    /// Flags to tell the [`Generator`](crate::Generator) how to deal with boxed
256    /// types.
257    #[derive(Default, Debug, Clone, Copy, Eq, PartialEq)]
258    pub struct BoxFlags: u32 {
259        /// Boxed types will only be used if necessary.
260        ///
261        /// # Examples
262        ///
263        /// Consider the following XML schema:
264        /// ```xml
265        #[doc = include_str!("../../tests/generator/box_flags/schema.xsd")]
266        /// ```
267        ///
268        /// Enable the `AUTO` feature only will result in the following code:
269        /// ```rust
270        #[doc = include_str!("../../tests/generator/box_flags/expected/auto.rs")]
271        /// ```
272        const AUTO = 0;
273
274        /// Elements in a `xs:choice` type will always be boxed.
275        ///
276        /// # Examples
277        ///
278        /// Consider the following XML schema:
279        /// ```xml
280        #[doc = include_str!("../../tests/generator/box_flags/schema.xsd")]
281        /// ```
282        ///
283        /// Enable the `ENUM_ELEMENTS` feature only will result in the following code:
284        /// ```rust
285        #[doc = include_str!("../../tests/generator/box_flags/expected/enum_elements.rs")]
286        /// ```
287        const ENUM_ELEMENTS = 1 << 0;
288
289        /// Elements in a `xs:all` or `xs:sequence` type will always be boxed.
290        ///
291        /// # Examples
292        ///
293        /// Consider the following XML schema:
294        /// ```xml
295        #[doc = include_str!("../../tests/generator/box_flags/schema.xsd")]
296        /// ```
297        ///
298        /// Enable the `STRUCT_ELEMENTS` feature only will result in the following code:
299        /// ```rust
300        #[doc = include_str!("../../tests/generator/box_flags/expected/struct_elements.rs")]
301        /// ```
302        const STRUCT_ELEMENTS = 1 << 1;
303    }
304}
305
306/// Postfixed that will be added to the different types generated by the code generator.
307#[derive(Debug, Clone)]
308pub struct TypePostfix {
309    /// Postfix added to normal types (like `xs:simpleType` or `xs:complexType`).
310    pub type_: String,
311
312    /// Postfixes added to elements (like `xs:element`).
313    pub element: String,
314
315    /// Postfixes added to inline types of elements (like `xs:element`).
316    pub element_type: String,
317
318    /// Postfix for the type that is used as content for [`Nillable`](xsd_parser_types::xml::Nillable) elements.
319    pub nillable_content: String,
320
321    /// Postfix for concrete elements in a substitution group.
322    pub dynamic_element: String,
323}
324
325impl Default for TypePostfix {
326    fn default() -> Self {
327        Self {
328            type_: String::from("Type"),
329            element: String::new(),
330            element_type: String::from("ElementType"),
331            nillable_content: String::from("NotNil"),
332            dynamic_element: String::from("Dyn"),
333        }
334    }
335}
336
337/// Tells the [`Generator`](crate::Generator) how to deal with type definitions.
338#[derive(Default, Debug, Clone, Copy, Eq, PartialEq)]
339pub enum TypedefMode {
340    /// The [`Generator`](crate::Generator) will automatically detect if a
341    /// new type struct or a simple type definition should be used
342    /// for a [`Reference`](crate::models::meta::MetaTypeVariant::Reference) type.
343    ///
344    /// Detecting the correct type automatically depends basically on the
345    /// occurrence of the references type. If the target type is only referenced
346    /// exactly once, a type definition is rendered. If a different
347    /// occurrence is used, it is wrapped in a new type struct because usually
348    /// additional code needs to be implemented for such types.
349    ///
350    /// # Examples
351    ///
352    /// Consider the following XML schema:
353    /// ```xml
354    #[doc = include_str!("../../tests/generator/typedef_mode/schema.xsd")]
355    /// ```
356    ///
357    /// If the typedef mode is set to [`TypedefMode::Auto`] the following code is rendered:
358    /// ```rust
359    #[doc = include_str!("../../tests/generator/typedef_mode/expected/auto.rs")]
360    /// ```
361    #[default]
362    Auto,
363
364    /// The [`Generator`](crate::Generator) will always use a simple type definition
365    /// for a [`Reference`](crate::models::meta::MetaTypeVariant::Reference) type.
366    ///
367    /// # Examples
368    ///
369    /// Consider the following XML schema:
370    /// ```xml
371    #[doc = include_str!("../../tests/generator/typedef_mode/schema.xsd")]
372    /// ```
373    ///
374    /// If the typedef mode is set to [`TypedefMode::Typedef`] the following code is rendered:
375    /// ```rust
376    #[doc = include_str!("../../tests/generator/typedef_mode/expected/typedef.rs")]
377    /// ```
378    Typedef,
379
380    /// The [`Generator`](crate::Generator) will always use a new type struct
381    /// for a [`Reference`](crate::models::meta::MetaTypeVariant::Reference) type.
382    ///
383    /// # Examples
384    ///
385    /// Consider the following XML schema:
386    /// ```xml
387    #[doc = include_str!("../../tests/generator/typedef_mode/schema.xsd")]
388    /// ```
389    ///
390    /// If the typedef mode is set to [`TypedefMode::NewType`] the following code is rendered:
391    /// ```rust
392    #[doc = include_str!("../../tests/generator/typedef_mode/expected/new_type.rs")]
393    /// ```
394    NewType,
395}
396
397/// Configuration which types the [`Generator`](crate::Generator) should generate
398/// code for used in [`GeneratorConfig`].
399#[derive(Debug, Clone)]
400pub enum Generate {
401    /// The generator will generate code for all types of the schemas.
402    All,
403
404    /// The generator will generate code for all types that have a name.
405    Named,
406
407    /// List of identifiers the generator will generate code for.
408    Types(Vec<IdentQuadruple>),
409}