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}