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 if namespaces == NamespaceSerialization::Dynamic {
281 self = self.with_render_step(RenderStep::QuickXmlCollectNamespaces);
282 }
283
284 self.with_render_steps([
285 RenderStep::NamespaceConstants,
286 RenderStep::QuickXmlSerialize {
287 namespaces,
288 default_namespace,
289 },
290 ])
291 }
292
293 pub fn with_quick_xml_deserialize(self) -> Self {
295 self.with_quick_xml_deserialize_config(false)
296 }
297
298 pub fn with_quick_xml_deserialize_config(self, boxed_deserializer: bool) -> Self {
301 self.with_render_steps([
302 RenderStep::Types,
303 RenderStep::Defaults,
304 RenderStep::NamespaceConstants,
305 RenderStep::QuickXmlDeserialize { boxed_deserializer },
306 ])
307 }
308
309 pub fn with_quick_xml(self) -> Self {
312 self.with_quick_xml_serialize().with_quick_xml_deserialize()
313 }
314
315 pub fn with_quick_xml_config(
318 self,
319 namespace_serialization: NamespaceSerialization,
320 default_serialize_namespace: Option<Namespace>,
321 boxed_deserializer: bool,
322 ) -> Self {
323 self.with_quick_xml_serialize_config(namespace_serialization, default_serialize_namespace)
324 .with_quick_xml_deserialize_config(boxed_deserializer)
325 }
326
327 pub fn with_serde_quick_xml(mut self) -> Self {
329 self.optimizer.flags |= OptimizerFlags::SERDE;
330
331 self.with_render_steps([RenderStep::TypesSerdeQuickXml, RenderStep::Defaults])
332 }
333
334 pub fn with_serde_xml_rs(mut self, version: SerdeXmlRsVersion) -> Self {
336 self.optimizer.flags |= OptimizerFlags::SERDE;
337
338 self.with_render_steps([
339 RenderStep::TypesSerdeXmlRs { version },
340 RenderStep::Defaults,
341 ])
342 }
343
344 pub fn with_advanced_enums(self) -> Self {
353 self.with_generator_flags(GeneratorFlags::ADVANCED_ENUMS)
354 .with_render_step(RenderStep::EnumConstants)
355 }
356
357 pub fn with_namespace<P, N>(mut self, prefix: P, namespace: N) -> Self
361 where
362 P: Into<NamespacePrefix>,
363 N: Into<Namespace>,
364 {
365 self.parser
366 .namespaces
367 .push((prefix.into(), namespace.into()));
368
369 self
370 }
371
372 pub fn with_namespaces<I, P, N>(mut self, namespaces: I) -> Self
376 where
377 I: IntoIterator<Item = (P, N)>,
378 P: Into<NamespacePrefix>,
379 N: Into<Namespace>,
380 {
381 for (prefix, namespace) in namespaces {
382 self.parser
383 .namespaces
384 .push((prefix.into(), namespace.into()));
385 }
386
387 self
388 }
389
390 pub fn with_generate<I>(mut self, types: I) -> Self
392 where
393 I: IntoIterator,
394 I::Item: Into<IdentQuadruple>,
395 {
396 self.generator.generate = Generate::Types(types.into_iter().map(Into::into).collect());
397
398 self
399 }
400
401 pub fn with_typedef_mode(mut self, mode: TypedefMode) -> Self {
403 self.generator.typedef_mode = mode;
404
405 self
406 }
407
408 pub fn with_derive<I>(mut self, derive: I) -> Self
410 where
411 I: IntoIterator,
412 I::Item: Into<String>,
413 {
414 self.renderer.derive = Some(
415 derive
416 .into_iter()
417 .map(Into::into)
418 .filter(|s| !s.is_empty())
419 .collect(),
420 );
421
422 self
423 }
424
425 pub fn with_any_type_support(self) -> Self {
427 self.with_generator_flags(GeneratorFlags::ANY_TYPE_SUPPORT)
428 }
429
430 pub fn with_any_types<S, T>(mut self, any_type: S, any_attributes_type: T) -> Self
432 where
433 S: Into<String>,
434 T: Into<String>,
435 {
436 self.generator.any_type = any_type.into();
437 self.generator.any_attributes_type = any_attributes_type.into();
438
439 self.with_any_type_support()
440 }
441
442 pub fn with_mixed_type_support(self) -> Self {
444 self.with_generator_flags(GeneratorFlags::MIXED_TYPE_SUPPORT)
445 }
446
447 pub fn with_mixed_types<S, T>(mut self, text_type: S, mixed_type: T) -> Self
449 where
450 S: Into<String>,
451 T: Into<String>,
452 {
453 self.generator.text_type = text_type.into();
454 self.generator.mixed_type = mixed_type.into();
455
456 self.with_mixed_type_support()
457 }
458
459 pub fn with_nillable_type_support(self) -> Self {
461 self.with_generator_flags(GeneratorFlags::NILLABLE_TYPE_SUPPORT)
462 }
463
464 pub fn with_nillable_type<S>(mut self, nillable_type: S) -> Self
466 where
467 S: Into<String>,
468 {
469 self.generator.nillable_type = nillable_type.into();
470
471 self.with_nillable_type_support()
472 }
473
474 pub fn with_naming<X>(mut self, naming: X) -> Self
476 where
477 X: Naming + 'static,
478 {
479 self.interpreter.naming = Some(Box::new(naming));
480
481 self
482 }
483
484 pub fn with_type<I, M>(mut self, ident: I, meta: M) -> Self
494 where
495 I: Into<IdentQuadruple>,
496 M: Into<MetaType>,
497 {
498 self.interpreter.types.push((ident.into(), meta.into()));
499
500 self
501 }
502
503 pub fn with_xs_any_simple_type<S>(self, path: S) -> Self
511 where
512 S: AsRef<str>,
513 {
514 let path = path.as_ref();
515 let name = path.rsplit_once("::").map_or(path, |(_, name)| name);
516
517 let ident = (IdentType::Type, Namespace::XS, "anySimpleType");
518 let meta = CustomMeta::new(name)
519 .include_from(path)
520 .with_namespace(Namespace::XS)
521 .with_namespace(Namespace::XSI);
522
523 self.with_type(ident, meta)
524 }
525
526 pub fn with_qname_type(self) -> Self {
528 self.with_qname_type_from("::xsd_parser_types::xml::QName")
529 }
530
531 pub fn with_qname_type_from(self, path: &str) -> Self {
533 let name = path.rsplit_once("::").map_or(path, |(_, name)| name);
534
535 let ident = (IdentType::Type, Namespace::XS, "QName");
536 let meta = CustomMeta::new(name)
537 .include_from(path)
538 .with_namespace(Namespace::XS)
539 .with_default(crate::misc::qname_default);
540
541 self.with_type(ident, meta)
542 }
543
544 pub fn with_type_postfix<S>(mut self, value: S) -> Self
548 where
549 S: Into<String>,
550 {
551 self.generator.type_postfix.type_ = value.into();
552
553 self
554 }
555
556 pub fn with_element_postfix<S>(mut self, value: S) -> Self
560 where
561 S: Into<String>,
562 {
563 self.generator.type_postfix.element = value.into();
564
565 self
566 }
567
568 pub fn with_element_type_postfix<S>(mut self, value: S) -> Self
572 where
573 S: Into<String>,
574 {
575 self.generator.type_postfix.element_type = value.into();
576
577 self
578 }
579
580 pub fn with_nillable_content_postfix<S>(mut self, value: S) -> Self
584 where
585 S: Into<String>,
586 {
587 self.generator.type_postfix.nillable_content = value.into();
588
589 self
590 }
591
592 pub fn with_dynamic_element_postfix<S>(mut self, value: S) -> Self
596 where
597 S: Into<String>,
598 {
599 self.generator.type_postfix.dynamic_element = value.into();
600
601 self
602 }
603}
604
605#[deprecated(note = "Use IdentQuadruple instead")]
609pub type IdentTriple = IdentQuadruple;
610
611#[derive(Debug, Clone)]
623pub struct IdentQuadruple {
624 pub ns: Option<NamespaceIdent>,
626
627 pub schema: Option<SchemaIdent>,
629
630 pub name: String,
632
633 pub type_: IdentType,
635}
636
637impl IdentQuadruple {
638 #[inline]
640 #[must_use]
641 pub fn new<S>(name: S, type_: IdentType) -> Self
642 where
643 S: Into<String>,
644 {
645 Self {
646 ns: None,
647 schema: None,
648 name: name.into(),
649 type_,
650 }
651 }
652
653 #[inline]
655 #[must_use]
656 pub fn with_ns<X>(mut self, ns: X) -> Self
657 where
658 X: Into<NamespaceIdent>,
659 {
660 self.ns = Some(ns.into());
661
662 self
663 }
664
665 #[inline]
667 #[must_use]
668 pub fn with_schema<X>(mut self, schema: X) -> Self
669 where
670 X: Into<SchemaIdent>,
671 {
672 self.schema = Some(schema.into());
673
674 self
675 }
676
677 #[inline]
679 #[must_use]
680 pub fn with_name<X>(mut self, name: X) -> Self
681 where
682 X: Into<String>,
683 {
684 self.name = name.into();
685
686 self
687 }
688
689 #[inline]
691 #[must_use]
692 pub fn with_type(mut self, type_: IdentType) -> Self {
693 self.type_ = type_;
694
695 self
696 }
697
698 pub fn resolve(self, schemas: &Schemas) -> Result<TypeIdent, InterpreterError> {
726 let Self {
727 ns,
728 schema,
729 name,
730 type_,
731 } = self;
732
733 let name = Name::new_named(name);
734
735 let ns = match ns {
736 None | Some(NamespaceIdent::Anonymous) => schemas
737 .resolve_namespace(&None)
738 .ok_or(InterpreterError::AnonymousNamespaceIsUndefined)?,
739 Some(NamespaceIdent::Id(ns)) => ns,
740 Some(NamespaceIdent::Prefix(prefix)) => schemas
741 .resolve_prefix(&prefix)
742 .ok_or(InterpreterError::UnknownNamespacePrefix(prefix))?,
743 #[allow(clippy::unnecessary_literal_unwrap)]
744 Some(NamespaceIdent::Namespace(ns)) => {
745 let ns = Some(ns);
746
747 schemas
748 .resolve_namespace(&ns)
749 .ok_or_else(|| InterpreterError::UnknownNamespace(ns.unwrap()))?
750 }
751 };
752
753 let schema = match schema {
754 None => schemas
755 .get_namespace_info(&ns)
756 .and_then(|x| {
757 if x.schemas.len() == 1 {
758 Some(x.schemas[0])
759 } else {
760 None
761 }
762 })
763 .or_else(|| schemas.resolve_schema(ns, name.as_str(), type_))
764 .unwrap_or(SchemaId::UNKNOWN),
765 Some(SchemaIdent::Id(schema)) => schema,
766 Some(SchemaIdent::Name(s)) => schemas
767 .schemas()
768 .find(|(_, info)| matches!(&info.name, Some(name) if *name == s))
769 .map_or(SchemaId::UNKNOWN, |(id, _)| *id),
770 Some(SchemaIdent::Location(url)) => schemas
771 .schemas()
772 .find(|(_, info)| matches!(&info.location, Some(location) if *location == url))
773 .map_or(SchemaId::UNKNOWN, |(id, _)| *id),
774 };
775
776 Ok(TypeIdent {
777 ns,
778 schema,
779 name,
780 type_,
781 })
782 }
783}
784
785impl<X> From<(IdentType, X)> for IdentQuadruple
786where
787 X: AsRef<str>,
788{
789 fn from((type_, ident): (IdentType, X)) -> Self {
790 let ident = ident.as_ref();
791 let (prefix, name) = ident
792 .split_once(':')
793 .map_or((None, ident), |(a, b)| (Some(a), b));
794 let ns = prefix.map(|x| NamespaceIdent::prefix(x.as_bytes().to_owned()));
795 let name = name.to_owned();
796 let schema = None;
797
798 Self {
799 ns,
800 schema,
801 name,
802 type_,
803 }
804 }
805}
806
807impl<N, X> From<(IdentType, N, X)> for IdentQuadruple
808where
809 N: Into<NamespaceIdent>,
810 X: Into<String>,
811{
812 fn from((type_, ns, name): (IdentType, N, X)) -> Self {
813 Self::from((type_, Some(ns), name))
814 }
815}
816
817impl<N, X> From<(IdentType, Option<N>, X)> for IdentQuadruple
818where
819 N: Into<NamespaceIdent>,
820 X: Into<String>,
821{
822 fn from((type_, ns, name): (IdentType, Option<N>, X)) -> Self {
823 let ns = ns.map(Into::into);
824 let name = name.into();
825 let schema = None;
826
827 Self {
828 ns,
829 schema,
830 name,
831 type_,
832 }
833 }
834}
835
836impl<N, S, X> From<(IdentType, N, S, X)> for IdentQuadruple
837where
838 N: Into<NamespaceIdent>,
839 S: Into<SchemaIdent>,
840 X: Into<String>,
841{
842 fn from((type_, ns, schema, name): (IdentType, N, S, X)) -> Self {
843 Self::from((type_, Some(ns), Some(schema), name))
844 }
845}
846
847impl<N, S, X> From<(IdentType, Option<N>, S, X)> for IdentQuadruple
848where
849 N: Into<NamespaceIdent>,
850 S: Into<SchemaIdent>,
851 X: Into<String>,
852{
853 fn from((type_, ns, schema, name): (IdentType, Option<N>, S, X)) -> Self {
854 Self::from((type_, ns, Some(schema), name))
855 }
856}
857
858impl<N, S, X> From<(IdentType, N, Option<S>, X)> for IdentQuadruple
859where
860 N: Into<NamespaceIdent>,
861 S: Into<SchemaIdent>,
862 X: Into<String>,
863{
864 fn from((type_, ns, schema, name): (IdentType, N, Option<S>, X)) -> Self {
865 Self::from((type_, Some(ns), schema, name))
866 }
867}
868
869impl<N, S, X> From<(IdentType, Option<N>, Option<S>, X)> for IdentQuadruple
870where
871 N: Into<NamespaceIdent>,
872 S: Into<SchemaIdent>,
873 X: Into<String>,
874{
875 fn from((type_, ns, schema, name): (IdentType, Option<N>, Option<S>, X)) -> Self {
876 let ns = ns.map(Into::into);
877 let schema = schema.map(Into::into);
878 let name = name.into();
879
880 Self {
881 ns,
882 schema,
883 name,
884 type_,
885 }
886 }
887}
888
889#[derive(Debug, Clone)]
893pub enum NamespaceIdent {
894 Anonymous,
896
897 Id(NamespaceId),
899
900 Prefix(NamespacePrefix),
902
903 Namespace(Namespace),
905}
906
907impl NamespaceIdent {
908 #[inline]
910 #[must_use]
911 pub fn id(value: NamespaceId) -> Self {
912 Self::Id(value)
913 }
914
915 #[inline]
917 #[must_use]
918 pub fn prefix<X>(value: X) -> Self
919 where
920 NamespacePrefix: From<X>,
921 {
922 Self::Prefix(NamespacePrefix::from(value))
923 }
924
925 #[inline]
927 #[must_use]
928 pub fn namespace<X>(value: X) -> Self
929 where
930 Namespace: From<X>,
931 {
932 Self::Namespace(Namespace::from(value))
933 }
934}
935
936impl From<NamespaceId> for NamespaceIdent {
937 #[inline]
938 fn from(value: NamespaceId) -> Self {
939 Self::Id(value)
940 }
941}
942
943impl From<Namespace> for NamespaceIdent {
944 #[inline]
945 fn from(value: Namespace) -> Self {
946 Self::Namespace(value)
947 }
948}
949
950impl From<NamespacePrefix> for NamespaceIdent {
951 #[inline]
952 fn from(value: NamespacePrefix) -> Self {
953 Self::Prefix(value)
954 }
955}
956
957#[derive(Debug, Clone)]
961pub enum SchemaIdent {
962 Id(SchemaId),
964
965 Name(String),
967
968 Location(Url),
970}
971
972impl SchemaIdent {
973 #[inline]
975 #[must_use]
976 pub fn id(value: SchemaId) -> Self {
977 Self::Id(value)
978 }
979
980 #[inline]
982 #[must_use]
983 pub fn name<X>(value: X) -> Self
984 where
985 X: Into<String>,
986 {
987 Self::Name(value.into())
988 }
989
990 #[inline]
992 #[must_use]
993 pub fn location<X>(value: X) -> Self
994 where
995 X: Into<Url>,
996 {
997 Self::Location(value.into())
998 }
999}
1000
1001impl From<SchemaId> for SchemaIdent {
1002 #[inline]
1003 fn from(value: SchemaId) -> Self {
1004 Self::Id(value)
1005 }
1006}
1007
1008impl From<String> for SchemaIdent {
1009 #[inline]
1010 fn from(value: String) -> Self {
1011 Self::Name(value)
1012 }
1013}
1014
1015impl From<Url> for SchemaIdent {
1016 #[inline]
1017 fn from(value: Url) -> Self {
1018 Self::Location(value)
1019 }
1020}
1021
1022impl Schemas {
1023 fn resolve_schema(&self, ns: NamespaceId, name: &str, type_: IdentType) -> Option<SchemaId> {
1024 let ns_info = self.get_namespace_info(&ns)?;
1025
1026 for schema in &ns_info.schemas {
1027 let Some(schema_info) = self.get_schema(schema) else {
1028 continue;
1029 };
1030
1031 for c in &schema_info.schema.content {
1032 match (type_, c) {
1033 (IdentType::Element, SchemaContent::Element(x)) if matches!(&x.name, Some(n) if n == name) => {
1034 return Some(*schema)
1035 }
1036 (IdentType::Type, SchemaContent::SimpleType(x)) if matches!(&x.name, Some(n) if n == name) => {
1037 return Some(*schema)
1038 }
1039 (IdentType::Type, SchemaContent::ComplexType(x)) if matches!(&x.name, Some(n) if n == name) => {
1040 return Some(*schema)
1041 }
1042 (_, _) => (),
1043 }
1044 }
1045 }
1046
1047 None
1048 }
1049}