xsd_parser/config/
mod.rs

1//! Contains the [`Config`] structures for the [`generate`](super::generate) method.
2
3mod generator;
4mod interpreter;
5mod optimizer;
6mod parser;
7mod renderer;
8
9use xsd_parser_types::misc::{Namespace, NamespacePrefix};
10
11pub use crate::models::{meta::MetaType, Ident, IdentType, Name};
12
13use crate::pipeline::renderer::NamespaceSerialization;
14use crate::traits::Naming;
15use crate::InterpreterError;
16
17pub use self::generator::{
18    BoxFlags, Generate, GeneratorConfig, GeneratorFlags, TypePostfix, TypedefMode,
19};
20pub use self::interpreter::{InterpreterConfig, InterpreterFlags};
21pub use self::optimizer::{OptimizerConfig, OptimizerFlags};
22pub use self::parser::{ParserConfig, ParserFlags, Resolver, Schema};
23pub use self::renderer::{
24    DynTypeTraits, RenderStep, RenderStepConfig, RendererConfig, RendererFlags, SerdeXmlRsVersion,
25};
26
27use crate::models::schema::Schemas;
28
29/// Configuration structure for the [`generate`](super::generate) method.
30#[must_use]
31#[derive(Default, Debug, Clone)]
32pub struct Config {
33    /// Configuration for the schema parser.
34    pub parser: ParserConfig,
35
36    /// Configuration for the schema interpreter.
37    pub interpreter: InterpreterConfig,
38
39    /// Configuration for the type information optimizer.
40    pub optimizer: OptimizerConfig,
41
42    /// Configuration for the code generator.
43    pub generator: GeneratorConfig,
44
45    /// Configuration for the code renderer.
46    pub renderer: RendererConfig,
47}
48
49impl Config {
50    /// Adds the passed `schema` to the list of schemas to parse.
51    pub fn with_schema(mut self, schema: Schema) -> Self {
52        self.parser.schemas.push(schema);
53
54        self
55    }
56
57    /// Adds the passed `schemas` to the list of schemas to parse.
58    pub fn with_schemas<I>(mut self, schemas: I) -> Self
59    where
60        I: IntoIterator<Item = Schema>,
61    {
62        for schema in schemas {
63            self = self.with_schema(schema);
64        }
65
66        self
67    }
68
69    /// Set parser flags to the config.
70    pub fn set_parser_flags(mut self, flags: ParserFlags) -> Self {
71        self.parser.flags = flags;
72
73        self
74    }
75
76    /// Add parser flags to the config.
77    pub fn with_parser_flags(mut self, flags: ParserFlags) -> Self {
78        self.parser.flags.insert(flags);
79
80        self
81    }
82
83    /// Remove parser flags to the config.
84    pub fn without_parser_flags(mut self, flags: ParserFlags) -> Self {
85        self.parser.flags.remove(flags);
86
87        self
88    }
89
90    /// Set interpreter flags to the config.
91    pub fn set_interpreter_flags(mut self, flags: InterpreterFlags) -> Self {
92        self.interpreter.flags = flags;
93
94        self
95    }
96
97    /// Add code interpreter flags to the config.
98    pub fn with_interpreter_flags(mut self, flags: InterpreterFlags) -> Self {
99        self.interpreter.flags.insert(flags);
100
101        self
102    }
103
104    /// Remove code interpreter flags to the config.
105    pub fn without_interpreter_flags(mut self, flags: InterpreterFlags) -> Self {
106        self.interpreter.flags.remove(flags);
107
108        self
109    }
110
111    /// Set optimizer flags to the config.
112    pub fn set_optimizer_flags(mut self, flags: OptimizerFlags) -> Self {
113        self.optimizer.flags = flags;
114
115        self
116    }
117
118    /// Add optimizer flags to the config.
119    pub fn with_optimizer_flags(mut self, flags: OptimizerFlags) -> Self {
120        self.optimizer.flags.insert(flags);
121
122        self
123    }
124
125    /// Remove optimizer flags to the config.
126    pub fn without_optimizer_flags(mut self, flags: OptimizerFlags) -> Self {
127        self.optimizer.flags.remove(flags);
128
129        self
130    }
131
132    /// Set generator flags to the config.
133    pub fn set_generator_flags(mut self, flags: GeneratorFlags) -> Self {
134        self.generator.flags = flags;
135
136        self
137    }
138
139    /// Add code generator flags to the config.
140    pub fn with_generator_flags(mut self, flags: GeneratorFlags) -> Self {
141        self.generator.flags.insert(flags);
142
143        self
144    }
145
146    /// Remove code generator flags to the config.
147    pub fn without_generator_flags(mut self, flags: GeneratorFlags) -> Self {
148        self.generator.flags.remove(flags);
149
150        self
151    }
152
153    /// Set renderer flags to the config.
154    pub fn set_renderer_flags(mut self, flags: RendererFlags) -> Self {
155        self.renderer.flags = flags;
156
157        self
158    }
159
160    /// Add code renderer flags to the config.
161    pub fn with_renderer_flags(mut self, flags: RendererFlags) -> Self {
162        self.renderer.flags.insert(flags);
163
164        self
165    }
166
167    /// Remove code renderer flags to the config.
168    pub fn without_renderer_flags(mut self, flags: RendererFlags) -> Self {
169        self.renderer.flags.remove(flags);
170
171        self
172    }
173
174    /// Set boxing flags to the code generator config.
175    pub fn set_box_flags(mut self, flags: BoxFlags) -> Self {
176        self.generator.box_flags = flags;
177
178        self
179    }
180
181    /// Add boxing flags to the code generator config.
182    pub fn with_box_flags(mut self, flags: BoxFlags) -> Self {
183        self.generator.box_flags.insert(flags);
184
185        self
186    }
187
188    /// Remove boxing flags to the code generator config.
189    pub fn without_box_flags(mut self, flags: BoxFlags) -> Self {
190        self.generator.box_flags.remove(flags);
191
192        self
193    }
194
195    /// Adds the passed `step` to the config.
196    ///
197    /// If the same type of renderer was already added,
198    /// it is replaced by the new one.
199    pub fn with_render_step<T>(mut self, step: T) -> Self
200    where
201        T: RenderStepConfig + 'static,
202    {
203        let step = Box::new(step);
204        let mut index = 0;
205        let mut position = None;
206
207        // Find the position to place the new step and remove any other mutual exclusive step
208        self.renderer.steps.retain(|x| {
209            let mut remove = x.is_mutual_exclusive_to(&*step) || step.is_mutual_exclusive_to(&**x);
210
211            if remove && position.is_none() {
212                remove = false;
213                position = Some(index);
214            }
215
216            index += 1;
217
218            !remove
219        });
220
221        // Insert at the found position or append
222        if let Some(pos) = position {
223            self.renderer.steps[pos] = step;
224        } else {
225            self.renderer.steps.push(step);
226        }
227
228        self
229    }
230
231    /// Add multiple renderers to the generator config.
232    ///
233    /// See [`with_render_step`](Self::with_render_step) for details.
234    pub fn with_render_steps<I>(mut self, steps: I) -> Self
235    where
236        I: IntoIterator,
237        I::Item: RenderStepConfig + 'static,
238    {
239        for step in steps {
240            self = self.with_render_step(step);
241        }
242
243        self
244    }
245
246    /// Enable code generation for [`quick_xml`] serialization.
247    pub fn with_quick_xml_serialize(self) -> Self {
248        self.with_render_steps([
249            RenderStep::Types,
250            RenderStep::Defaults,
251            RenderStep::PrefixConstants,
252            RenderStep::NamespaceConstants,
253            RenderStep::QuickXmlSerialize {
254                namespaces: NamespaceSerialization::Global,
255                default_namespace: None,
256            },
257        ])
258    }
259
260    /// Enable code generation for [`quick_xml`] serialization.
261    pub fn with_quick_xml_serialize_config(
262        mut self,
263        namespaces: NamespaceSerialization,
264        default_namespace: Option<Namespace>,
265    ) -> Self {
266        self = self.with_render_steps([RenderStep::Types, RenderStep::Defaults]);
267
268        if namespaces != NamespaceSerialization::None {
269            self = self.with_render_step(RenderStep::PrefixConstants);
270        }
271
272        self.with_render_steps([
273            RenderStep::NamespaceConstants,
274            RenderStep::QuickXmlSerialize {
275                namespaces,
276                default_namespace,
277            },
278        ])
279    }
280
281    /// Enable code generation for [`quick_xml`] deserialization with the default settings.
282    pub fn with_quick_xml_deserialize(self) -> Self {
283        self.with_quick_xml_deserialize_config(false)
284    }
285
286    /// Enable render steps for [`quick_xml`] deserialization
287    /// with the passed configuration.
288    pub fn with_quick_xml_deserialize_config(self, boxed_deserializer: bool) -> Self {
289        self.with_render_steps([
290            RenderStep::Types,
291            RenderStep::Defaults,
292            RenderStep::NamespaceConstants,
293            RenderStep::QuickXmlDeserialize { boxed_deserializer },
294        ])
295    }
296
297    /// Enable render steps for [`quick_xml`] serialization and deserialization
298    /// with the default settings.
299    pub fn with_quick_xml(self) -> Self {
300        self.with_quick_xml_serialize().with_quick_xml_deserialize()
301    }
302
303    /// Enable render steps for [`quick_xml`] serialization and deserialization
304    /// with the passed configuration.
305    pub fn with_quick_xml_config(
306        self,
307        namespace_serialization: NamespaceSerialization,
308        default_serialize_namespace: Option<Namespace>,
309        boxed_deserializer: bool,
310    ) -> Self {
311        self.with_quick_xml_serialize_config(namespace_serialization, default_serialize_namespace)
312            .with_quick_xml_deserialize_config(boxed_deserializer)
313    }
314
315    /// Enable render steps for types with [`quick_xml`] serde support.
316    pub fn with_serde_quick_xml(mut self) -> Self {
317        self.optimizer.flags |= OptimizerFlags::SERDE;
318
319        self.with_render_steps([RenderStep::TypesSerdeQuickXml, RenderStep::Defaults])
320    }
321
322    /// Enable render steps for types with [`quick_xml`] serde support.
323    pub fn with_serde_xml_rs(mut self, version: SerdeXmlRsVersion) -> Self {
324        self.optimizer.flags |= OptimizerFlags::SERDE;
325
326        self.with_render_steps([
327            RenderStep::TypesSerdeXmlRs { version },
328            RenderStep::Defaults,
329        ])
330    }
331
332    /// Set the types the code should be generated for.
333    pub fn with_generate<I>(mut self, types: I) -> Self
334    where
335        I: IntoIterator,
336        I::Item: Into<IdentTriple>,
337    {
338        self.generator.generate = Generate::Types(types.into_iter().map(Into::into).collect());
339
340        self
341    }
342
343    /// Set the typedef mode for the generator.
344    pub fn with_typedef_mode(mut self, mode: TypedefMode) -> Self {
345        self.generator.typedef_mode = mode;
346
347        self
348    }
349
350    /// Set the traits the generated types should derive from.
351    pub fn with_derive<I>(mut self, derive: I) -> Self
352    where
353        I: IntoIterator,
354        I::Item: Into<String>,
355    {
356        self.renderer.derive = Some(
357            derive
358                .into_iter()
359                .map(Into::into)
360                .filter(|s| !s.is_empty())
361                .collect(),
362        );
363
364        self
365    }
366
367    /// Enable support for `xs:any` types.
368    pub fn with_any_type_support(self) -> Self {
369        self.with_generator_flags(GeneratorFlags::ANY_TYPE_SUPPORT)
370    }
371
372    /// Set the types to use to handle `xs:any` and `xs:anyAttribute` elements.
373    pub fn with_any_types<S, T>(mut self, any_type: S, any_attributes_type: T) -> Self
374    where
375        S: Into<String>,
376        T: Into<String>,
377    {
378        self.generator.any_type = any_type.into();
379        self.generator.any_attributes_type = any_attributes_type.into();
380
381        self.with_any_type_support()
382    }
383
384    /// Enable support for mixed types.
385    pub fn with_mixed_type_support(self) -> Self {
386        self.with_generator_flags(GeneratorFlags::MIXED_TYPE_SUPPORT)
387    }
388
389    /// Set the types to use to handle mixed types and text data.
390    pub fn with_mixed_types<S, T>(mut self, text_type: S, mixed_type: T) -> Self
391    where
392        S: Into<String>,
393        T: Into<String>,
394    {
395        self.generator.text_type = text_type.into();
396        self.generator.mixed_type = mixed_type.into();
397
398        self.with_mixed_type_support()
399    }
400
401    /// Enable support for nillable types.
402    pub fn with_nillable_type_support(self) -> Self {
403        self.with_generator_flags(GeneratorFlags::NILLABLE_TYPE_SUPPORT)
404    }
405
406    /// Set the type to use to handle nillable elements.
407    pub fn with_nillable_type<S>(mut self, nillable_type: S) -> Self
408    where
409        S: Into<String>,
410    {
411        self.generator.nillable_type = nillable_type.into();
412
413        self.with_nillable_type_support()
414    }
415
416    /// Set the [`Naming`] trait that is used to generated names in the interpreter.
417    pub fn with_naming<X>(mut self, naming: X) -> Self
418    where
419        X: Naming + 'static,
420    {
421        self.interpreter.naming = Some(Box::new(naming));
422
423        self
424    }
425}
426
427/// Identifier that is used inside the config.
428///
429/// Each element in a XML schema is uniquely identified by the following three
430/// values:
431///     - The namespace of the element (or no namespace at all).
432///     - The name of the element.
433///     - The type of element.
434///
435/// This struct is used to bundle these three information to a unique identifier
436/// for an element.
437#[derive(Debug, Clone)]
438pub struct IdentTriple {
439    /// Namespace where the type is defined in.
440    pub ns: Option<NamespaceIdent>,
441
442    /// Name of the type.
443    pub name: String,
444
445    /// Type of the identifier (because pure names are not unique in XSD).
446    pub type_: IdentType,
447}
448
449impl IdentTriple {
450    /// Resolve the triple to an actual type that is available in the schema.
451    ///
452    /// # Errors
453    ///
454    /// Returns an error if the namespace or the namespace prefix could not be
455    /// resolved.
456    pub fn resolve(self, schemas: &Schemas) -> Result<Ident, InterpreterError> {
457        let ns = match self.ns {
458            None => None,
459            Some(NamespaceIdent::Prefix(prefix)) => Some(
460                schemas
461                    .resolve_prefix(&prefix)
462                    .ok_or(InterpreterError::UnknownNamespacePrefix(prefix))?,
463            ),
464            #[allow(clippy::unnecessary_literal_unwrap)]
465            Some(NamespaceIdent::Namespace(ns)) => {
466                let ns = Some(ns);
467                Some(
468                    schemas
469                        .resolve_namespace(&ns)
470                        .ok_or_else(|| InterpreterError::UnknownNamespace(ns.unwrap()))?,
471                )
472            }
473        };
474
475        Ok(Ident {
476            ns,
477            name: Name::new_named(self.name),
478            type_: self.type_,
479        })
480    }
481}
482
483impl<X> From<(IdentType, X)> for IdentTriple
484where
485    X: AsRef<str>,
486{
487    fn from((type_, ident): (IdentType, X)) -> Self {
488        let ident = ident.as_ref();
489        let (prefix, name) = ident
490            .split_once(':')
491            .map_or((None, ident), |(a, b)| (Some(a), b));
492        let ns = prefix.map(|x| NamespaceIdent::prefix(x.as_bytes().to_owned()));
493        let name = name.to_owned();
494
495        Self { ns, name, type_ }
496    }
497}
498
499impl<N, X> From<(IdentType, N, X)> for IdentTriple
500where
501    N: Into<Option<NamespaceIdent>>,
502    X: Into<String>,
503{
504    fn from((type_, ns, name): (IdentType, N, X)) -> Self {
505        let ns = ns.into();
506        let name = name.into();
507
508        Self { ns, name, type_ }
509    }
510}
511
512/// Identifies a namespace by either it's known prefix or by the namespace directly.
513#[derive(Debug, Clone)]
514pub enum NamespaceIdent {
515    /// Uses a namespace prefix to refer to a specific namespace in the schema.
516    Prefix(NamespacePrefix),
517
518    /// Uses the full namespace to refer to a specific namespace in the schema.
519    Namespace(Namespace),
520}
521
522impl NamespaceIdent {
523    /// Creates a new [`NamespaceIdent::Prefix`] instance from the passed `value`.
524    pub fn prefix<X>(value: X) -> Self
525    where
526        NamespacePrefix: From<X>,
527    {
528        Self::Prefix(NamespacePrefix::from(value))
529    }
530
531    /// Creates a new [`NamespaceIdent::Namespace`] instance from the passed `value`.
532    pub fn namespace<X>(value: X) -> Self
533    where
534        Namespace: From<X>,
535    {
536        Self::Namespace(Namespace::from(value))
537    }
538}
539
540impl From<Namespace> for NamespaceIdent {
541    fn from(value: Namespace) -> Self {
542        Self::Namespace(value)
543    }
544}
545
546impl From<NamespacePrefix> for NamespaceIdent {
547    fn from(value: NamespacePrefix) -> Self {
548        Self::Prefix(value)
549    }
550}