1mod generator;
4mod interpreter;
5mod optimizer;
6mod parser;
7mod renderer;
8
9use url::Url;
10
11pub use xsd_parser_types::misc::{Namespace, NamespacePrefix};
12
13pub use crate::models::{meta::MetaType, schema::NamespaceId, IdentType, Name, TypeIdent};
14
15use crate::models::{
16 meta::CustomMeta,
17 schema::{xs::SchemaContent, SchemaId, Schemas},
18};
19use crate::pipeline::renderer::NamespaceSerialization;
20use crate::traits::Naming;
21use crate::InterpreterError;
22
23pub use self::generator::{
24 BoxFlags, Generate, GeneratorConfig, GeneratorFlags, TypePostfix, TypedefMode,
25};
26pub use self::interpreter::{InterpreterConfig, InterpreterFlags};
27pub use self::optimizer::{OptimizerConfig, OptimizerFlags};
28pub use self::parser::{ParserConfig, ParserFlags, Resolver, Schema};
29pub use self::renderer::{
30 DynTypeTraits, RenderStep, RenderStepConfig, RendererConfig, RendererFlags, SerdeXmlRsVersion,
31};
32
33#[must_use]
35#[derive(Default, Debug, Clone)]
36pub struct Config {
37 pub parser: ParserConfig,
39
40 pub interpreter: InterpreterConfig,
42
43 pub optimizer: OptimizerConfig,
45
46 pub generator: GeneratorConfig,
48
49 pub renderer: RendererConfig,
51}
52
53impl Config {
54 pub fn with_schema<T>(mut self, schema: T) -> Self
56 where
57 T: Into<Schema>,
58 {
59 self.parser.schemas.push(schema.into());
60
61 self
62 }
63
64 pub fn with_schemas<I>(mut self, schemas: I) -> Self
66 where
67 I: IntoIterator,
68 I::Item: Into<Schema>,
69 {
70 for schema in schemas {
71 self = self.with_schema(schema.into());
72 }
73
74 self
75 }
76
77 pub fn set_parser_flags(mut self, flags: ParserFlags) -> Self {
79 self.parser.flags = flags;
80
81 self
82 }
83
84 pub fn with_parser_flags(mut self, flags: ParserFlags) -> Self {
86 self.parser.flags.insert(flags);
87
88 self
89 }
90
91 pub fn without_parser_flags(mut self, flags: ParserFlags) -> Self {
93 self.parser.flags.remove(flags);
94
95 self
96 }
97
98 pub fn set_interpreter_flags(mut self, flags: InterpreterFlags) -> Self {
100 self.interpreter.flags = flags;
101
102 self
103 }
104
105 pub fn with_interpreter_flags(mut self, flags: InterpreterFlags) -> Self {
107 self.interpreter.flags.insert(flags);
108
109 self
110 }
111
112 pub fn without_interpreter_flags(mut self, flags: InterpreterFlags) -> Self {
114 self.interpreter.flags.remove(flags);
115
116 self
117 }
118
119 pub fn set_optimizer_flags(mut self, flags: OptimizerFlags) -> Self {
121 self.optimizer.flags = flags;
122
123 self
124 }
125
126 pub fn with_optimizer_flags(mut self, flags: OptimizerFlags) -> Self {
128 self.optimizer.flags.insert(flags);
129
130 self
131 }
132
133 pub fn without_optimizer_flags(mut self, flags: OptimizerFlags) -> Self {
135 self.optimizer.flags.remove(flags);
136
137 self
138 }
139
140 pub fn set_generator_flags(mut self, flags: GeneratorFlags) -> Self {
142 self.generator.flags = flags;
143
144 self
145 }
146
147 pub fn with_generator_flags(mut self, flags: GeneratorFlags) -> Self {
149 self.generator.flags.insert(flags);
150
151 self
152 }
153
154 pub fn without_generator_flags(mut self, flags: GeneratorFlags) -> Self {
156 self.generator.flags.remove(flags);
157
158 self
159 }
160
161 pub fn set_renderer_flags(mut self, flags: RendererFlags) -> Self {
163 self.renderer.flags = flags;
164
165 self
166 }
167
168 pub fn with_renderer_flags(mut self, flags: RendererFlags) -> Self {
170 self.renderer.flags.insert(flags);
171
172 self
173 }
174
175 pub fn without_renderer_flags(mut self, flags: RendererFlags) -> Self {
177 self.renderer.flags.remove(flags);
178
179 self
180 }
181
182 pub fn set_box_flags(mut self, flags: BoxFlags) -> Self {
184 self.generator.box_flags = flags;
185
186 self
187 }
188
189 pub fn with_box_flags(mut self, flags: BoxFlags) -> Self {
191 self.generator.box_flags.insert(flags);
192
193 self
194 }
195
196 pub fn without_box_flags(mut self, flags: BoxFlags) -> Self {
198 self.generator.box_flags.remove(flags);
199
200 self
201 }
202
203 pub fn with_render_step<T>(mut self, step: T) -> Self
208 where
209 T: RenderStepConfig + 'static,
210 {
211 let step = Box::new(step);
212 let mut index = 0;
213 let mut position = None;
214
215 self.renderer.steps.retain(|x| {
217 let mut remove = x.is_mutual_exclusive_to(&*step) || step.is_mutual_exclusive_to(&**x);
218
219 if remove && position.is_none() {
220 remove = false;
221 position = Some(index);
222 }
223
224 index += 1;
225
226 !remove
227 });
228
229 if let Some(pos) = position {
231 self.renderer.steps[pos] = step;
232 } else {
233 self.renderer.steps.push(step);
234 }
235
236 self
237 }
238
239 pub fn with_render_steps<I>(mut self, steps: I) -> Self
243 where
244 I: IntoIterator,
245 I::Item: RenderStepConfig + 'static,
246 {
247 for step in steps {
248 self = self.with_render_step(step);
249 }
250
251 self
252 }
253
254 pub fn with_quick_xml_serialize(self) -> Self {
256 self.with_render_steps([
257 RenderStep::Types,
258 RenderStep::Defaults,
259 RenderStep::PrefixConstants,
260 RenderStep::NamespaceConstants,
261 RenderStep::QuickXmlSerialize {
262 namespaces: NamespaceSerialization::Global,
263 default_namespace: None,
264 },
265 ])
266 }
267
268 pub fn with_quick_xml_serialize_config(
270 mut self,
271 namespaces: NamespaceSerialization,
272 default_namespace: Option<Namespace>,
273 ) -> Self {
274 self = self.with_render_steps([RenderStep::Types, RenderStep::Defaults]);
275
276 if namespaces != NamespaceSerialization::None {
277 self = self.with_render_step(RenderStep::PrefixConstants);
278 }
279
280 self.with_render_steps([
281 RenderStep::NamespaceConstants,
282 RenderStep::QuickXmlSerialize {
283 namespaces,
284 default_namespace,
285 },
286 ])
287 }
288
289 pub fn with_quick_xml_deserialize(self) -> Self {
291 self.with_quick_xml_deserialize_config(false)
292 }
293
294 pub fn with_quick_xml_deserialize_config(self, boxed_deserializer: bool) -> Self {
297 self.with_render_steps([
298 RenderStep::Types,
299 RenderStep::Defaults,
300 RenderStep::NamespaceConstants,
301 RenderStep::QuickXmlDeserialize { boxed_deserializer },
302 ])
303 }
304
305 pub fn with_quick_xml(self) -> Self {
308 self.with_quick_xml_serialize().with_quick_xml_deserialize()
309 }
310
311 pub fn with_quick_xml_config(
314 self,
315 namespace_serialization: NamespaceSerialization,
316 default_serialize_namespace: Option<Namespace>,
317 boxed_deserializer: bool,
318 ) -> Self {
319 self.with_quick_xml_serialize_config(namespace_serialization, default_serialize_namespace)
320 .with_quick_xml_deserialize_config(boxed_deserializer)
321 }
322
323 pub fn with_serde_quick_xml(mut self) -> Self {
325 self.optimizer.flags |= OptimizerFlags::SERDE;
326
327 self.with_render_steps([RenderStep::TypesSerdeQuickXml, RenderStep::Defaults])
328 }
329
330 pub fn with_serde_xml_rs(mut self, version: SerdeXmlRsVersion) -> Self {
332 self.optimizer.flags |= OptimizerFlags::SERDE;
333
334 self.with_render_steps([
335 RenderStep::TypesSerdeXmlRs { version },
336 RenderStep::Defaults,
337 ])
338 }
339
340 pub fn with_advanced_enums(self) -> Self {
349 self.with_generator_flags(GeneratorFlags::ADVANCED_ENUMS)
350 .with_render_step(RenderStep::EnumConstants)
351 }
352
353 pub fn with_namespace<P, N>(mut self, prefix: P, namespace: N) -> Self
357 where
358 P: Into<NamespacePrefix>,
359 N: Into<Namespace>,
360 {
361 self.parser
362 .namespaces
363 .push((prefix.into(), namespace.into()));
364
365 self
366 }
367
368 pub fn with_namespaces<I, P, N>(mut self, namespaces: I) -> Self
372 where
373 I: IntoIterator<Item = (P, N)>,
374 P: Into<NamespacePrefix>,
375 N: Into<Namespace>,
376 {
377 for (prefix, namespace) in namespaces {
378 self.parser
379 .namespaces
380 .push((prefix.into(), namespace.into()));
381 }
382
383 self
384 }
385
386 pub fn with_generate<I>(mut self, types: I) -> Self
388 where
389 I: IntoIterator,
390 I::Item: Into<IdentQuadruple>,
391 {
392 self.generator.generate = Generate::Types(types.into_iter().map(Into::into).collect());
393
394 self
395 }
396
397 pub fn with_typedef_mode(mut self, mode: TypedefMode) -> Self {
399 self.generator.typedef_mode = mode;
400
401 self
402 }
403
404 pub fn with_derive<I>(mut self, derive: I) -> Self
406 where
407 I: IntoIterator,
408 I::Item: Into<String>,
409 {
410 self.renderer.derive = Some(
411 derive
412 .into_iter()
413 .map(Into::into)
414 .filter(|s| !s.is_empty())
415 .collect(),
416 );
417
418 self
419 }
420
421 pub fn with_any_type_support(self) -> Self {
423 self.with_generator_flags(GeneratorFlags::ANY_TYPE_SUPPORT)
424 }
425
426 pub fn with_any_types<S, T>(mut self, any_type: S, any_attributes_type: T) -> Self
428 where
429 S: Into<String>,
430 T: Into<String>,
431 {
432 self.generator.any_type = any_type.into();
433 self.generator.any_attributes_type = any_attributes_type.into();
434
435 self.with_any_type_support()
436 }
437
438 pub fn with_mixed_type_support(self) -> Self {
440 self.with_generator_flags(GeneratorFlags::MIXED_TYPE_SUPPORT)
441 }
442
443 pub fn with_mixed_types<S, T>(mut self, text_type: S, mixed_type: T) -> Self
445 where
446 S: Into<String>,
447 T: Into<String>,
448 {
449 self.generator.text_type = text_type.into();
450 self.generator.mixed_type = mixed_type.into();
451
452 self.with_mixed_type_support()
453 }
454
455 pub fn with_nillable_type_support(self) -> Self {
457 self.with_generator_flags(GeneratorFlags::NILLABLE_TYPE_SUPPORT)
458 }
459
460 pub fn with_nillable_type<S>(mut self, nillable_type: S) -> Self
462 where
463 S: Into<String>,
464 {
465 self.generator.nillable_type = nillable_type.into();
466
467 self.with_nillable_type_support()
468 }
469
470 pub fn with_naming<X>(mut self, naming: X) -> Self
472 where
473 X: Naming + 'static,
474 {
475 self.interpreter.naming = Some(Box::new(naming));
476
477 self
478 }
479
480 pub fn with_type<I, M>(mut self, ident: I, meta: M) -> Self
490 where
491 I: Into<IdentQuadruple>,
492 M: Into<MetaType>,
493 {
494 self.interpreter.types.push((ident.into(), meta.into()));
495
496 self
497 }
498
499 pub fn with_xs_any_simple_type<S>(self, path: S) -> Self
507 where
508 S: AsRef<str>,
509 {
510 let path = path.as_ref();
511 let name = path.rsplit_once("::").map_or(path, |(_, name)| name);
512
513 let ident = (IdentType::Type, Namespace::XS, "anySimpleType");
514 let meta = CustomMeta::new(name)
515 .include_from(path)
516 .with_namespace(Namespace::XS)
517 .with_namespace(Namespace::XSI);
518
519 self.with_type(ident, meta)
520 }
521
522 pub fn with_qname_type(self) -> Self {
524 self.with_qname_type_from("::xsd_parser_types::xml::QName")
525 }
526
527 pub fn with_qname_type_from(self, path: &str) -> Self {
529 let name = path.rsplit_once("::").map_or(path, |(_, name)| name);
530
531 let ident = (IdentType::Type, Namespace::XS, "QName");
532 let meta = CustomMeta::new(name)
533 .include_from(path)
534 .with_namespace(Namespace::XS)
535 .with_default(crate::misc::qname_default);
536
537 self.with_type(ident, meta)
538 }
539
540 pub fn with_type_postfix<S>(mut self, value: S) -> Self
544 where
545 S: Into<String>,
546 {
547 self.generator.type_postfix.type_ = value.into();
548
549 self
550 }
551
552 pub fn with_element_postfix<S>(mut self, value: S) -> Self
556 where
557 S: Into<String>,
558 {
559 self.generator.type_postfix.element = value.into();
560
561 self
562 }
563
564 pub fn with_element_type_postfix<S>(mut self, value: S) -> Self
568 where
569 S: Into<String>,
570 {
571 self.generator.type_postfix.element_type = value.into();
572
573 self
574 }
575
576 pub fn with_nillable_content_postfix<S>(mut self, value: S) -> Self
580 where
581 S: Into<String>,
582 {
583 self.generator.type_postfix.nillable_content = value.into();
584
585 self
586 }
587
588 pub fn with_dynamic_element_postfix<S>(mut self, value: S) -> Self
592 where
593 S: Into<String>,
594 {
595 self.generator.type_postfix.dynamic_element = value.into();
596
597 self
598 }
599}
600
601#[deprecated(note = "Use IdentQuadruple instead")]
605pub type IdentTriple = IdentQuadruple;
606
607#[derive(Debug, Clone)]
619pub struct IdentQuadruple {
620 pub ns: Option<NamespaceIdent>,
622
623 pub schema: Option<SchemaIdent>,
625
626 pub name: String,
628
629 pub type_: IdentType,
631}
632
633impl IdentQuadruple {
634 #[inline]
636 #[must_use]
637 pub fn new<S>(name: S, type_: IdentType) -> Self
638 where
639 S: Into<String>,
640 {
641 Self {
642 ns: None,
643 schema: None,
644 name: name.into(),
645 type_,
646 }
647 }
648
649 #[inline]
651 #[must_use]
652 pub fn with_ns<X>(mut self, ns: X) -> Self
653 where
654 X: Into<NamespaceIdent>,
655 {
656 self.ns = Some(ns.into());
657
658 self
659 }
660
661 #[inline]
663 #[must_use]
664 pub fn with_schema<X>(mut self, schema: X) -> Self
665 where
666 X: Into<SchemaIdent>,
667 {
668 self.schema = Some(schema.into());
669
670 self
671 }
672
673 #[inline]
675 #[must_use]
676 pub fn with_name<X>(mut self, name: X) -> Self
677 where
678 X: Into<String>,
679 {
680 self.name = name.into();
681
682 self
683 }
684
685 #[inline]
687 #[must_use]
688 pub fn with_type(mut self, type_: IdentType) -> Self {
689 self.type_ = type_;
690
691 self
692 }
693
694 pub fn resolve(self, schemas: &Schemas) -> Result<TypeIdent, InterpreterError> {
722 let Self {
723 ns,
724 schema,
725 name,
726 type_,
727 } = self;
728
729 let name = Name::new_named(name);
730
731 let ns = match ns {
732 None | Some(NamespaceIdent::Anonymous) => schemas
733 .resolve_namespace(&None)
734 .ok_or(InterpreterError::AnonymousNamespaceIsUndefined)?,
735 Some(NamespaceIdent::Id(ns)) => ns,
736 Some(NamespaceIdent::Prefix(prefix)) => schemas
737 .resolve_prefix(&prefix)
738 .ok_or(InterpreterError::UnknownNamespacePrefix(prefix))?,
739 #[allow(clippy::unnecessary_literal_unwrap)]
740 Some(NamespaceIdent::Namespace(ns)) => {
741 let ns = Some(ns);
742
743 schemas
744 .resolve_namespace(&ns)
745 .ok_or_else(|| InterpreterError::UnknownNamespace(ns.unwrap()))?
746 }
747 };
748
749 let schema = match schema {
750 None => schemas
751 .get_namespace_info(&ns)
752 .and_then(|x| {
753 if x.schemas.len() == 1 {
754 Some(x.schemas[0])
755 } else {
756 None
757 }
758 })
759 .or_else(|| schemas.resolve_schema(ns, name.as_str(), type_))
760 .unwrap_or(SchemaId::UNKNOWN),
761 Some(SchemaIdent::Id(schema)) => schema,
762 Some(SchemaIdent::Name(s)) => schemas
763 .schemas()
764 .find(|(_, info)| matches!(&info.name, Some(name) if *name == s))
765 .map_or(SchemaId::UNKNOWN, |(id, _)| *id),
766 Some(SchemaIdent::Location(url)) => schemas
767 .schemas()
768 .find(|(_, info)| matches!(&info.location, Some(location) if *location == url))
769 .map_or(SchemaId::UNKNOWN, |(id, _)| *id),
770 };
771
772 Ok(TypeIdent {
773 ns,
774 schema,
775 name,
776 type_,
777 })
778 }
779}
780
781impl<X> From<(IdentType, X)> for IdentQuadruple
782where
783 X: AsRef<str>,
784{
785 fn from((type_, ident): (IdentType, X)) -> Self {
786 let ident = ident.as_ref();
787 let (prefix, name) = ident
788 .split_once(':')
789 .map_or((None, ident), |(a, b)| (Some(a), b));
790 let ns = prefix.map(|x| NamespaceIdent::prefix(x.as_bytes().to_owned()));
791 let name = name.to_owned();
792 let schema = None;
793
794 Self {
795 ns,
796 schema,
797 name,
798 type_,
799 }
800 }
801}
802
803impl<N, X> From<(IdentType, N, X)> for IdentQuadruple
804where
805 N: Into<NamespaceIdent>,
806 X: Into<String>,
807{
808 fn from((type_, ns, name): (IdentType, N, X)) -> Self {
809 Self::from((type_, Some(ns), name))
810 }
811}
812
813impl<N, X> From<(IdentType, Option<N>, X)> for IdentQuadruple
814where
815 N: Into<NamespaceIdent>,
816 X: Into<String>,
817{
818 fn from((type_, ns, name): (IdentType, Option<N>, X)) -> Self {
819 let ns = ns.map(Into::into);
820 let name = name.into();
821 let schema = None;
822
823 Self {
824 ns,
825 schema,
826 name,
827 type_,
828 }
829 }
830}
831
832impl<N, S, X> From<(IdentType, N, S, X)> for IdentQuadruple
833where
834 N: Into<NamespaceIdent>,
835 S: Into<SchemaIdent>,
836 X: Into<String>,
837{
838 fn from((type_, ns, schema, name): (IdentType, N, S, X)) -> Self {
839 Self::from((type_, Some(ns), Some(schema), name))
840 }
841}
842
843impl<N, S, X> From<(IdentType, Option<N>, S, X)> for IdentQuadruple
844where
845 N: Into<NamespaceIdent>,
846 S: Into<SchemaIdent>,
847 X: Into<String>,
848{
849 fn from((type_, ns, schema, name): (IdentType, Option<N>, S, X)) -> Self {
850 Self::from((type_, ns, Some(schema), name))
851 }
852}
853
854impl<N, S, X> From<(IdentType, N, Option<S>, X)> for IdentQuadruple
855where
856 N: Into<NamespaceIdent>,
857 S: Into<SchemaIdent>,
858 X: Into<String>,
859{
860 fn from((type_, ns, schema, name): (IdentType, N, Option<S>, X)) -> Self {
861 Self::from((type_, Some(ns), schema, name))
862 }
863}
864
865impl<N, S, X> From<(IdentType, Option<N>, Option<S>, X)> for IdentQuadruple
866where
867 N: Into<NamespaceIdent>,
868 S: Into<SchemaIdent>,
869 X: Into<String>,
870{
871 fn from((type_, ns, schema, name): (IdentType, Option<N>, Option<S>, X)) -> Self {
872 let ns = ns.map(Into::into);
873 let schema = schema.map(Into::into);
874 let name = name.into();
875
876 Self {
877 ns,
878 schema,
879 name,
880 type_,
881 }
882 }
883}
884
885#[derive(Debug, Clone)]
889pub enum NamespaceIdent {
890 Anonymous,
892
893 Id(NamespaceId),
895
896 Prefix(NamespacePrefix),
898
899 Namespace(Namespace),
901}
902
903impl NamespaceIdent {
904 #[inline]
906 #[must_use]
907 pub fn id(value: NamespaceId) -> Self {
908 Self::Id(value)
909 }
910
911 #[inline]
913 #[must_use]
914 pub fn prefix<X>(value: X) -> Self
915 where
916 NamespacePrefix: From<X>,
917 {
918 Self::Prefix(NamespacePrefix::from(value))
919 }
920
921 #[inline]
923 #[must_use]
924 pub fn namespace<X>(value: X) -> Self
925 where
926 Namespace: From<X>,
927 {
928 Self::Namespace(Namespace::from(value))
929 }
930}
931
932impl From<NamespaceId> for NamespaceIdent {
933 #[inline]
934 fn from(value: NamespaceId) -> Self {
935 Self::Id(value)
936 }
937}
938
939impl From<Namespace> for NamespaceIdent {
940 #[inline]
941 fn from(value: Namespace) -> Self {
942 Self::Namespace(value)
943 }
944}
945
946impl From<NamespacePrefix> for NamespaceIdent {
947 #[inline]
948 fn from(value: NamespacePrefix) -> Self {
949 Self::Prefix(value)
950 }
951}
952
953#[derive(Debug, Clone)]
957pub enum SchemaIdent {
958 Id(SchemaId),
960
961 Name(String),
963
964 Location(Url),
966}
967
968impl SchemaIdent {
969 #[inline]
971 #[must_use]
972 pub fn id(value: SchemaId) -> Self {
973 Self::Id(value)
974 }
975
976 #[inline]
978 #[must_use]
979 pub fn name<X>(value: X) -> Self
980 where
981 X: Into<String>,
982 {
983 Self::Name(value.into())
984 }
985
986 #[inline]
988 #[must_use]
989 pub fn location<X>(value: X) -> Self
990 where
991 X: Into<Url>,
992 {
993 Self::Location(value.into())
994 }
995}
996
997impl From<SchemaId> for SchemaIdent {
998 #[inline]
999 fn from(value: SchemaId) -> Self {
1000 Self::Id(value)
1001 }
1002}
1003
1004impl From<String> for SchemaIdent {
1005 #[inline]
1006 fn from(value: String) -> Self {
1007 Self::Name(value)
1008 }
1009}
1010
1011impl From<Url> for SchemaIdent {
1012 #[inline]
1013 fn from(value: Url) -> Self {
1014 Self::Location(value)
1015 }
1016}
1017
1018impl Schemas {
1019 fn resolve_schema(&self, ns: NamespaceId, name: &str, type_: IdentType) -> Option<SchemaId> {
1020 let ns_info = self.get_namespace_info(&ns)?;
1021
1022 for schema in &ns_info.schemas {
1023 let Some(schema_info) = self.get_schema(schema) else {
1024 continue;
1025 };
1026
1027 for c in &schema_info.schema.content {
1028 match (type_, c) {
1029 (IdentType::Element, SchemaContent::Element(x)) if matches!(&x.name, Some(n) if n == name) => {
1030 return Some(*schema)
1031 }
1032 (IdentType::Type, SchemaContent::SimpleType(x)) if matches!(&x.name, Some(n) if n == name) => {
1033 return Some(*schema)
1034 }
1035 (IdentType::Type, SchemaContent::ComplexType(x)) if matches!(&x.name, Some(n) if n == name) => {
1036 return Some(*schema)
1037 }
1038 (_, _) => (),
1039 }
1040 }
1041 }
1042
1043 None
1044 }
1045}