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, GeneratorFlags, SerdeSupport, TypedefMode};
9pub use crate::schema::{Namespace, NamespacePrefix};
10pub use crate::types::{IdentType, Type};
11
12use crate::schema::Schemas;
13use crate::types::{Ident, Name};
14use crate::InterpreterError;
15
16/// Configuration structure for the [`generate`](super::generate) method.
17#[must_use]
18#[derive(Default, Debug, Clone)]
19pub struct Config {
20 /// Configuration for the schema parser.
21 pub parser: ParserConfig,
22
23 /// Configuration for the schema interpreter.
24 pub interpreter: InterpreterConfig,
25
26 /// Configuration for the type information optimizer.
27 pub optimizer: OptimizerConfig,
28
29 /// Configuration for the code generator.
30 pub generator: GeneratorConfig,
31}
32
33/// Configuration for the schema parser.
34#[derive(Debug, Clone)]
35pub struct ParserConfig {
36 /// List of resolvers to use for resolving referenced schemas.
37 pub resolver: Vec<Resolver>,
38
39 /// List of namespaces to add to the parser before the schemas are loaded.
40 ///
41 /// See [`with_namespace`](crate::Parser::with_namespace) for more details.
42 pub namespaces: Vec<(NamespacePrefix, Namespace)>,
43
44 /// List of schemas to load.
45 pub schemas: Vec<Schema>,
46
47 /// Additional flags to control the parser.
48 pub flags: ParserFlags,
49
50 /// Wether to enable the debug output and where to write it to.
51 pub debug_output: Option<PathBuf>,
52}
53
54/// Configuration for the schema interpreter.
55#[derive(Debug, Clone)]
56pub struct InterpreterConfig {
57 /// List of user defined types to add to the interpreter before the schemas
58 /// are actually interpreted.
59 ///
60 /// See [`with_type`](crate::Interpreter::with_type) for more details.
61 pub types: Vec<(IdentTriple, Type)>,
62
63 /// Additional flags to control the interpreter.
64 pub flags: InterpreterFlags,
65
66 /// Wether to enable the debug output and where to write it to.
67 pub debug_output: Option<PathBuf>,
68}
69
70/// Configuration for the type information optimizer.
71#[derive(Debug, Clone)]
72pub struct OptimizerConfig {
73 /// Additional flags to control the optimizer.
74 pub flags: OptimizerFlags,
75
76 /// Wether to enable the debug output and where to write it to.
77 pub debug_output: Option<PathBuf>,
78}
79
80/// Configuration for the code generator.
81#[derive(Debug, Clone)]
82pub struct GeneratorConfig {
83 /// Types to add to the generator before the actual code is generated.
84 ///
85 /// See [`with_type`](crate::Generator::with_type) for more details.
86 pub types: Vec<IdentTriple>,
87
88 /// Sets the traits the generated types should derive from.
89 ///
90 /// See [`derive`](crate::Generator::derive) for more details.
91 pub derive: Option<Vec<String>>,
92
93 /// Set the traits that should be implemented by dynamic types.
94 ///
95 /// See [`dyn_type_traits`](crate::Generator::dyn_type_traits) for more details.
96 pub dyn_type_traits: Option<Vec<String>>,
97
98 /// Postfixes that should be applied to the name of the different generated
99 /// types.
100 ///
101 /// See [`with_type_postfix`](crate::Generator::with_type_postfix) for more details.
102 pub type_postfix: TypePostfix,
103
104 /// Tell the generator how to deal with boxing.
105 pub box_flags: BoxFlags,
106
107 /// Tells the generator how to deal with type definitions.
108 pub typedef_mode: TypedefMode,
109
110 /// Tells the generator how to generate code for the [`serde`] crate.
111 pub serde_support: SerdeSupport,
112
113 /// Specify which types the generator should generate code for.
114 pub generate: Generate,
115
116 /// Additional flags to control the generator.
117 pub flags: GeneratorFlags,
118
119 /// Name of the `xsd-parser` crate that is used for the generated code.
120 pub xsd_parser: String,
121}
122
123/// Postfixed that will be added to the different types generated by the code generator.
124#[derive(Debug, Clone)]
125pub struct TypePostfix {
126 /// Postfix added to normal types (like `xs:simpleType` or `xs:complexType`).
127 pub type_: String,
128
129 /// Postfixes added to elements (like `xs:element`).
130 pub element: String,
131
132 /// Postfixes added to inline types if elements (like `xs:element`).
133 pub element_type: String,
134}
135
136/// Configuration for the resolver used in [`ParserConfig`].
137#[derive(Debug, Clone)]
138pub enum Resolver {
139 /// Resolver that is used to resolve ewb resources (like `http://...` or `https://...`).
140 #[cfg(feature = "web-resolver")]
141 Web,
142
143 /// Resolver that is used to resolve local resources from disk (like `./local-schema.xsd` or `file://...`).
144 File,
145}
146
147/// Configuration for the schemas to load used in [`ParserConfig`].
148#[derive(Debug, Clone)]
149pub enum Schema {
150 /// Load a schema from the provided URL.
151 Url(Url),
152
153 /// Load a schema from the provided file path.
154 File(PathBuf),
155
156 /// Load the schema from the provided string.
157 Schema(String),
158}
159
160/// Configuration which types the [`Generator`](crate::Generator) should generate
161/// code for used in [`GeneratorConfig`].
162#[derive(Debug, Clone)]
163pub enum Generate {
164 /// The generator will generate code for all types of the schemas.
165 All,
166
167 /// List of identifiers the generator will generate code for.
168 Types(Vec<IdentTriple>),
169}
170
171/// Identifier that is used inside the config.
172#[derive(Debug, Clone)]
173pub struct IdentTriple {
174 /// Namespace the type is defined in.
175 pub ns: Option<NamespaceIdent>,
176
177 /// Name of the type.
178 pub name: String,
179
180 /// Type of the identifier (because pure names are not unique in XSD).
181 pub type_: IdentType,
182}
183
184/// Identifies a namespace by either it's known prefix or by the namespace directly.
185#[derive(Debug, Clone)]
186pub enum NamespaceIdent {
187 /// Uses a namespace prefix to refer to a specific namespace in the schema.
188 Prefix(NamespacePrefix),
189
190 /// Uses the full namespace to refer to a specific namespace in the schema.
191 Namespace(Namespace),
192}
193
194bitflags! {
195 /// Flags to control the [`Parser`](crate::Parser).
196 #[derive(Debug, Clone)]
197 pub struct ParserFlags: u32 {
198 /// Whether the parser should resolve `xs:include` and `xs:import` elements
199 /// or not.
200 ///
201 /// See [`resolve_includes`](crate::Parser::resolve_includes) for details.
202 const RESOLVE_INCLUDES = 1 << 0;
203
204 /// Whether to add the default namespaces to the parser or not.
205 ///
206 /// See [`with_default_namespaces`](crate::Parser::with_default_namespaces) for details.
207 const DEFAULT_NAMESPACES = 1 << 1;
208 }
209}
210
211bitflags! {
212 /// Flags to control the [`Interpreter`](crate::Interpreter).
213 #[derive(Debug, Clone)]
214 pub struct InterpreterFlags: u32 {
215 /// Whether to add the build-in types to the interpreter or not.
216 ///
217 /// See [`with_buildin_types`](crate::Interpreter::with_buildin_types) for details.
218 const BUILDIN_TYPES = 1 << 0;
219
220 /// Whether to add the default types definitions to the interpreter or not.
221 ///
222 /// See [`with_default_typedefs`](crate::Interpreter::with_default_typedefs) for details.
223 const DEFAULT_TYPEDEFS = 1 << 1;
224
225 /// Whether to add a default type definitions for `xs:anyType` or not.
226 ///
227 /// See [`with_xs_any_type`](crate::Interpreter::with_xs_any_type) for details.
228 const WITH_XS_ANY_TYPE = 1 << 2;
229 }
230}
231
232bitflags! {
233 /// Flags to control the [`Optimizer`](crate::Optimizer).
234 #[derive(Debug, Clone)]
235 pub struct OptimizerFlags: u32 {
236 /// Whether to remove empty enum variants or not.
237 ///
238 /// See [`remove_empty_enum_variants`](crate::Optimizer::remove_empty_enum_variants) for details.
239 const REMOVE_EMPTY_ENUM_VARIANTS = 1 << 0;
240
241 /// Whether to remove empty enums or not.
242 ///
243 /// See [`remove_empty_enums`](crate::Optimizer::remove_empty_enums) for details.
244 const REMOVE_EMPTY_ENUMS = 1 << 1;
245
246 /// Whether to remove duplicate union variants or not.
247 ///
248 /// See [`remove_duplicate_union_variants`](crate::Optimizer::remove_duplicate_union_variants) for details.
249 const REMOVE_DUPLICATE_UNION_VARIANTS = 1 << 2;
250
251 /// Whether to remove empty unions or not.
252 ///
253 /// See [`remove_empty_unions`](crate::Optimizer::remove_empty_unions) for details.
254 const REMOVE_EMPTY_UNIONS = 1 << 3;
255
256 /// Whether to use the unrestricted base type of a type or not.
257 ///
258 /// See [`use_unrestricted_base_type`](crate::Optimizer::use_unrestricted_base_type) for details.
259 const USE_UNRESTRICTED_BASE_TYPE = 1 << 4;
260
261 /// Whether to convert dynamic types to choices or not.
262 ///
263 /// See [`convert_dynamic_to_choice`](crate::Optimizer::convert_dynamic_to_choice) for details.
264 const CONVERT_DYNAMIC_TO_CHOICE = 1 << 5;
265
266 /// Whether to flatten the content of complex types or not.
267 ///
268 /// See [`flatten_complex_types`](crate::Optimizer::flatten_complex_types) for details.
269 const FLATTEN_COMPLEX_TYPES = 1 << 6;
270
271 /// Whether to flatten unions or not.
272 ///
273 /// See [`flatten_unions`](crate::Optimizer::flatten_unions) for details.
274 const FLATTEN_UNIONS = 1 << 7;
275
276 /// Whether to merge enumerations and unions or not.
277 ///
278 /// See [`merge_enum_unions`](crate::Optimizer::merge_enum_unions) for details.
279 const MERGE_ENUM_UNIONS = 1 << 8;
280
281 /// Whether to resolve type definitions or not.
282 ///
283 /// See [`resolve_typedefs`](crate::Optimizer::resolve_typedefs) for details.
284 const RESOLVE_TYPEDEFS = 1 << 9;
285
286 /// Whether to remove duplicate types or not.
287 ///
288 /// See [`remove_duplicates`](crate::Optimizer::remove_duplicates) for details.
289 const REMOVE_DUPLICATES = 1 << 10;
290
291 /// Group that contains all necessary optimization that should be applied
292 /// if code with [`serde`] support should be rendered.
293 const SERDE = Self::FLATTEN_COMPLEX_TYPES.bits()
294 | Self::FLATTEN_UNIONS.bits()
295 | Self::MERGE_ENUM_UNIONS.bits();
296
297 /// Wether to merge the cardinality of a complex choice type or not.
298 ///
299 /// See [`merge_choice_cardinalities`](crate::Optimizer::merge_choice_cardinalities) for details.
300 const MERGE_CHOICE_CARDINALITIES = 1 << 11;
301 }
302}
303
304impl Config {
305 /// Set interpreter flags to the config.
306 pub fn set_interpreter_flags(mut self, flags: InterpreterFlags) -> Self {
307 self.interpreter.flags = flags;
308
309 self
310 }
311
312 /// Add code interpreter flags to the config.
313 pub fn with_interpreter_flags(mut self, flags: InterpreterFlags) -> Self {
314 self.interpreter.flags.insert(flags);
315
316 self
317 }
318
319 /// Remove code interpreter flags to the config.
320 pub fn without_interpreter_flags(mut self, flags: InterpreterFlags) -> Self {
321 self.interpreter.flags.remove(flags);
322
323 self
324 }
325
326 /// Set optimizer flags to the config.
327 pub fn set_optimizer_flags(mut self, flags: OptimizerFlags) -> Self {
328 self.optimizer.flags = flags;
329
330 self
331 }
332
333 /// Add optimizer flags to the config.
334 pub fn with_optimizer_flags(mut self, flags: OptimizerFlags) -> Self {
335 self.optimizer.flags.insert(flags);
336
337 self
338 }
339
340 /// Remove optimizer flags to the config.
341 pub fn without_optimizer_flags(mut self, flags: OptimizerFlags) -> Self {
342 self.optimizer.flags.remove(flags);
343
344 self
345 }
346
347 /// Set generator flags to the config.
348 pub fn set_generator_flags(mut self, flags: GeneratorFlags) -> Self {
349 self.generator.flags = flags;
350
351 self
352 }
353
354 /// Add code generator flags to the config.
355 pub fn with_generator_flags(mut self, flags: GeneratorFlags) -> Self {
356 self.generator.flags.insert(flags);
357
358 self
359 }
360
361 /// Remove code generator flags to the config.
362 pub fn without_generator_flags(mut self, flags: GeneratorFlags) -> Self {
363 self.generator.flags.remove(flags);
364
365 self
366 }
367
368 /// Set boxing flags to the code generator config.
369 pub fn set_box_flags(mut self, flags: BoxFlags) -> Self {
370 self.generator.box_flags = flags;
371
372 self
373 }
374
375 /// Add boxing flags to the code generator config.
376 pub fn with_box_flags(mut self, flags: BoxFlags) -> Self {
377 self.generator.box_flags.insert(flags);
378
379 self
380 }
381
382 /// Remove boxing flags to the code generator config.
383 pub fn without_box_flags(mut self, flags: BoxFlags) -> Self {
384 self.generator.box_flags.remove(flags);
385
386 self
387 }
388
389 /// Enable code generation for [`quick_xml`] serialization and deserialization.
390 pub fn with_quick_xml(mut self) -> Self {
391 self.generator.flags |= GeneratorFlags::QUICK_XML;
392
393 self
394 }
395
396 /// Set the [`serde`] support.
397 pub fn with_serde_support(mut self, serde_support: SerdeSupport) -> Self {
398 self.generator.serde_support = serde_support;
399
400 if self.generator.serde_support != SerdeSupport::None {
401 self.optimizer.flags |= OptimizerFlags::SERDE;
402 }
403
404 self
405 }
406
407 /// Set the types the code should be generated for.
408 pub fn with_generate<I>(mut self, types: I) -> Self
409 where
410 I: IntoIterator,
411 I::Item: Into<IdentTriple>,
412 {
413 self.generator.generate = Generate::Types(types.into_iter().map(Into::into).collect());
414
415 self
416 }
417
418 /// Set the typedef mode for the generator.
419 pub fn with_typedef_mode(mut self, mode: TypedefMode) -> Self {
420 self.generator.typedef_mode = mode;
421
422 self
423 }
424
425 /// Set the traits the generated types should derive from.
426 pub fn with_derive<I>(mut self, derive: I) -> Self
427 where
428 I: IntoIterator,
429 I::Item: Into<String>,
430 {
431 self.generator.derive = Some(
432 derive
433 .into_iter()
434 .map(Into::into)
435 .filter(|s| !s.is_empty())
436 .collect(),
437 );
438
439 self
440 }
441}
442
443impl Default for ParserConfig {
444 fn default() -> Self {
445 Self {
446 resolver: vec![Resolver::File],
447 schemas: vec![],
448 namespaces: vec![],
449 flags: ParserFlags::RESOLVE_INCLUDES | ParserFlags::DEFAULT_NAMESPACES,
450 debug_output: None,
451 }
452 }
453}
454
455impl Default for InterpreterConfig {
456 fn default() -> Self {
457 Self {
458 types: vec![],
459 debug_output: None,
460 flags: InterpreterFlags::BUILDIN_TYPES
461 | InterpreterFlags::DEFAULT_TYPEDEFS
462 | InterpreterFlags::WITH_XS_ANY_TYPE,
463 }
464 }
465}
466
467impl Default for OptimizerConfig {
468 fn default() -> Self {
469 Self {
470 debug_output: None,
471 flags: OptimizerFlags::REMOVE_EMPTY_ENUM_VARIANTS
472 | OptimizerFlags::REMOVE_EMPTY_ENUMS
473 | OptimizerFlags::REMOVE_DUPLICATE_UNION_VARIANTS
474 | OptimizerFlags::REMOVE_EMPTY_UNIONS,
475 }
476 }
477}
478
479impl Default for GeneratorConfig {
480 fn default() -> Self {
481 Self {
482 types: vec![],
483 derive: None,
484 type_postfix: TypePostfix::default(),
485 dyn_type_traits: None,
486 box_flags: BoxFlags::AUTO,
487 typedef_mode: TypedefMode::Auto,
488 serde_support: SerdeSupport::None,
489 generate: Generate::All,
490 flags: GeneratorFlags::empty(),
491 xsd_parser: "xsd_parser".into(),
492 }
493 }
494}
495
496impl Default for TypePostfix {
497 fn default() -> Self {
498 Self {
499 type_: String::from("Type"),
500 element: String::new(),
501 element_type: String::from("ElementType"),
502 }
503 }
504}
505
506/* IdentTriple */
507
508impl IdentTriple {
509 /// Resolve the triple to an actual type that is available in the schema.
510 ///
511 /// # Errors
512 ///
513 /// Returns an error if the namespace or the namespace prefix could not be
514 /// resolved.
515 pub fn resolve(self, schemas: &Schemas) -> Result<Ident, InterpreterError> {
516 let ns = match self.ns {
517 None => None,
518 Some(NamespaceIdent::Prefix(prefix)) => Some(
519 schemas
520 .resolve_prefix(&prefix)
521 .ok_or(InterpreterError::UnknownNamespacePrefix(prefix))?,
522 ),
523 #[allow(clippy::unnecessary_literal_unwrap)]
524 Some(NamespaceIdent::Namespace(ns)) => {
525 let ns = Some(ns);
526 Some(
527 schemas
528 .resolve_namespace(&ns)
529 .ok_or_else(|| InterpreterError::UnknownNamespace(ns.unwrap()))?,
530 )
531 }
532 };
533
534 Ok(Ident {
535 ns,
536 name: Name::new(self.name),
537 type_: self.type_,
538 })
539 }
540}
541
542impl<X> From<(IdentType, X)> for IdentTriple
543where
544 X: AsRef<str>,
545{
546 fn from((type_, ident): (IdentType, X)) -> Self {
547 let ident = ident.as_ref();
548 let (prefix, name) = ident
549 .split_once(':')
550 .map_or((None, ident), |(a, b)| (Some(a), b));
551 let ns = prefix.map(|x| NamespaceIdent::prefix(x.as_bytes().to_owned()));
552 let name = name.to_owned();
553
554 Self { ns, name, type_ }
555 }
556}
557
558impl<N, X> From<(IdentType, N, X)> for IdentTriple
559where
560 N: Into<Option<NamespaceIdent>>,
561 X: Into<String>,
562{
563 fn from((type_, ns, name): (IdentType, N, X)) -> Self {
564 let ns = ns.into();
565 let name = name.into();
566
567 Self { ns, name, type_ }
568 }
569}
570
571/* NamespaceIdent */
572
573impl NamespaceIdent {
574 /// Creates a new [`NamespaceIdent::Prefix`] instance from the passed `value`.
575 pub fn prefix<X>(value: X) -> Self
576 where
577 NamespacePrefix: From<X>,
578 {
579 Self::Prefix(NamespacePrefix::from(value))
580 }
581
582 /// Creates a new [`NamespaceIdent::Namespace`] instance from the passed `value`.
583 pub fn namespace<X>(value: X) -> Self
584 where
585 Namespace: From<X>,
586 {
587 Self::Namespace(Namespace::from(value))
588 }
589}
590
591impl From<Namespace> for NamespaceIdent {
592 fn from(value: Namespace) -> Self {
593 Self::Namespace(value)
594 }
595}
596
597impl From<NamespacePrefix> for NamespaceIdent {
598 fn from(value: NamespacePrefix) -> Self {
599 Self::Prefix(value)
600 }
601}