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}