xsd_parser/config/
generator.rs

1use bitflags::bitflags;
2
3use super::IdentTriple;
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<IdentTriple>,
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 `MIXED_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}
237
238bitflags! {
239    /// Flags to tell the [`Generator`](crate::Generator) how to deal with boxed
240    /// types.
241    #[derive(Default, Debug, Clone, Copy, Eq, PartialEq)]
242    pub struct BoxFlags: u32 {
243        /// Boxed types will only be used if necessary.
244        ///
245        /// # Examples
246        ///
247        /// Consider the following XML schema:
248        /// ```xml
249        #[doc = include_str!("../../tests/generator/box_flags/schema.xsd")]
250        /// ```
251        ///
252        /// Enable the `AUTO` feature only will result in the following code:
253        /// ```rust
254        #[doc = include_str!("../../tests/generator/box_flags/expected/auto.rs")]
255        /// ```
256        const AUTO = 0;
257
258        /// Elements in a `xs:choice` type will always be boxed.
259        ///
260        /// # Examples
261        ///
262        /// Consider the following XML schema:
263        /// ```xml
264        #[doc = include_str!("../../tests/generator/box_flags/schema.xsd")]
265        /// ```
266        ///
267        /// Enable the `ENUM_ELEMENTS` feature only will result in the following code:
268        /// ```rust
269        #[doc = include_str!("../../tests/generator/box_flags/expected/enum_elements.rs")]
270        /// ```
271        const ENUM_ELEMENTS = 1 << 0;
272
273        /// Elements in a `xs:all` or `xs:sequence` type will always be boxed.
274        ///
275        /// # Examples
276        ///
277        /// Consider the following XML schema:
278        /// ```xml
279        #[doc = include_str!("../../tests/generator/box_flags/schema.xsd")]
280        /// ```
281        ///
282        /// Enable the `STRUCT_ELEMENTS` feature only will result in the following code:
283        /// ```rust
284        #[doc = include_str!("../../tests/generator/box_flags/expected/struct_elements.rs")]
285        /// ```
286        const STRUCT_ELEMENTS = 1 << 1;
287    }
288}
289
290/// Postfixed that will be added to the different types generated by the code generator.
291#[derive(Debug, Clone)]
292pub struct TypePostfix {
293    /// Postfix added to normal types (like `xs:simpleType` or `xs:complexType`).
294    pub type_: String,
295
296    /// Postfixes added to elements (like `xs:element`).
297    pub element: String,
298
299    /// Postfixes added to inline types if elements (like `xs:element`).
300    pub element_type: String,
301
302    /// Postfix for the type that is used as content for [`Nillable`](xsd_parser_types::xml::Nillable) elements.
303    pub nillable_content: String,
304
305    /// Postfix for concrete elements in a substitution group.
306    pub dynamic_element: String,
307}
308
309impl Default for TypePostfix {
310    fn default() -> Self {
311        Self {
312            type_: String::from("Type"),
313            element: String::new(),
314            element_type: String::from("ElementType"),
315            nillable_content: String::from("NotNil"),
316            dynamic_element: String::from("Dyn"),
317        }
318    }
319}
320
321/// Tells the [`Generator`](crate::Generator) how to deal with type definitions.
322#[derive(Default, Debug, Clone, Copy, Eq, PartialEq)]
323pub enum TypedefMode {
324    /// The [`Generator`](crate::Generator) will automatically detect if a
325    /// new type struct or a simple type definition should be used
326    /// for a [`Reference`](crate::models::meta::MetaTypeVariant::Reference) type.
327    ///
328    /// Detecting the correct type automatically depends basically on the
329    /// occurrence of the references type. If the target type is only referenced
330    /// exactly once, a type definition is rendered. If a different
331    /// occurrence is used, it is wrapped in a new type struct because usually
332    /// additional code needs to be implemented for such types.
333    ///
334    /// # Examples
335    ///
336    /// Consider the following XML schema:
337    /// ```xml
338    #[doc = include_str!("../../tests/generator/typedef_mode/schema.xsd")]
339    /// ```
340    ///
341    /// If the typedef mode is set to [`TypedefMode::Auto`] the following code is rendered:
342    /// ```rust
343    #[doc = include_str!("../../tests/generator/typedef_mode/expected/auto.rs")]
344    /// ```
345    #[default]
346    Auto,
347
348    /// The [`Generator`](crate::Generator) will always use a simple type definition
349    /// for a [`Reference`](crate::models::meta::MetaTypeVariant::Reference) type.
350    ///
351    /// # Examples
352    ///
353    /// Consider the following XML schema:
354    /// ```xml
355    #[doc = include_str!("../../tests/generator/typedef_mode/schema.xsd")]
356    /// ```
357    ///
358    /// If the typedef mode is set to [`TypedefMode::Typedef`] the following code is rendered:
359    /// ```rust
360    #[doc = include_str!("../../tests/generator/typedef_mode/expected/typedef.rs")]
361    /// ```
362    Typedef,
363
364    /// The [`Generator`](crate::Generator) will always use a new type struct
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::NewType`] the following code is rendered:
375    /// ```rust
376    #[doc = include_str!("../../tests/generator/typedef_mode/expected/new_type.rs")]
377    /// ```
378    NewType,
379}
380
381/// Configuration which types the [`Generator`](crate::Generator) should generate
382/// code for used in [`GeneratorConfig`].
383#[derive(Debug, Clone)]
384pub enum Generate {
385    /// The generator will generate code for all types of the schemas.
386    All,
387
388    /// The generator will generate code for all types that have a name.
389    Named,
390
391    /// List of identifiers the generator will generate code for.
392    Types(Vec<IdentTriple>),
393}