1use std::borrow::Cow;
2use std::collections::{BTreeMap, BTreeSet, HashSet};
3use std::ops::{Deref, DerefMut};
4use std::str::FromStr;
5
6use bitflags::bitflags;
7use inflector::Inflector;
8use proc_macro2::{Ident as Ident2, TokenStream};
9use quote::{format_ident, quote, ToTokens};
10use smallvec::SmallVec;
11
12use crate::schema::{MaxOccurs, MinOccurs, NamespaceId};
13use crate::types::{DynamicInfo, Ident, Name, Type, TypeVariant, Types};
14
15use super::helper::render_usings;
16use super::Error;
17
18bitflags! {
19 #[derive(Debug, Clone, Copy)]
22 pub struct GeneratorFlags: u32 {
23 #[doc = include_str!("../../tests/generator/generator_flags/schema.xsd")]
30 #[doc = include_str!("../../tests/generator/generator_flags/expected/empty.rs")]
35 const NONE = 0;
37
38 #[doc = include_str!("../../tests/generator/generator_flags/schema.xsd")]
45 #[doc = include_str!("../../tests/generator/generator_flags/expected/use_modules.rs")]
50 const USE_MODULES = 1 << 0;
52
53 #[doc = include_str!("../../tests/generator/generator_flags/schema.xsd")]
61 #[doc = include_str!("../../tests/generator/generator_flags/expected/flatten_content.rs")]
66 const FLATTEN_CONTENT = Self::FLATTEN_ENUM_CONTENT.bits()
68 | Self::FLATTEN_STRUCT_CONTENT.bits();
69
70 const FLATTEN_ENUM_CONTENT = 1 << 1;
74
75 const FLATTEN_STRUCT_CONTENT = 1 << 2;
79
80 const QUICK_XML_SERIALIZE = 1 << 3;
83
84 const QUICK_XML_DESERIALIZE = 1 << 4;
87
88 const QUICK_XML = Self::WITH_NAMESPACE_CONSTANTS.bits()
92 | Self::QUICK_XML_SERIALIZE.bits()
93 | Self::QUICK_XML_DESERIALIZE.bits();
94
95 const WITH_NAMESPACE_TRAIT = 1 << 5;
97
98 const WITH_NAMESPACE_CONSTANTS = 1 << 6;
100 }
101}
102
103bitflags! {
104 #[derive(Default, Debug, Clone, Copy, Eq, PartialEq)]
107 pub struct BoxFlags: u32 {
108 #[doc = include_str!("../../tests/generator/box_flags/schema.xsd")]
115 #[doc = include_str!("../../tests/generator/box_flags/expected/auto.rs")]
120 const AUTO = 0;
122
123 #[doc = include_str!("../../tests/generator/box_flags/schema.xsd")]
130 #[doc = include_str!("../../tests/generator/box_flags/expected/enum_elements.rs")]
135 const ENUM_ELEMENTS = 1 << 0;
137
138 #[doc = include_str!("../../tests/generator/box_flags/schema.xsd")]
145 #[doc = include_str!("../../tests/generator/box_flags/expected/struct_elements.rs")]
150 const STRUCT_ELEMENTS = 1 << 1;
152 }
153}
154
155#[derive(Default, Debug, Clone, Copy, Eq, PartialEq)]
157pub enum TypedefMode {
158 #[doc = include_str!("../../tests/generator/typedef_mode/schema.xsd")]
173 #[doc = include_str!("../../tests/generator/typedef_mode/expected/auto.rs")]
178 #[default]
180 Auto,
181
182 #[doc = include_str!("../../tests/generator/typedef_mode/schema.xsd")]
190 #[doc = include_str!("../../tests/generator/typedef_mode/expected/typedef.rs")]
195 Typedef,
197
198 #[doc = include_str!("../../tests/generator/typedef_mode/schema.xsd")]
206 #[doc = include_str!("../../tests/generator/typedef_mode/expected/new_type.rs")]
211 NewType,
213}
214
215#[derive(Default, Debug, Clone, Copy, Eq, PartialEq)]
218pub enum SerdeSupport {
219 #[doc = include_str!("../../tests/generator/serde_support/schema.xsd")]
226 #[doc = include_str!("../../tests/generator/serde_support/expected/none.rs")]
231 #[default]
233 None,
234
235 #[doc = include_str!("../../tests/generator/serde_support/schema.xsd")]
243 #[doc = include_str!("../../tests/generator/serde_support/expected/quick_xml.rs")]
248 QuickXml,
250
251 #[doc = include_str!("../../tests/generator/serde_support/schema.xsd")]
259 #[doc = include_str!("../../tests/generator/serde_support/expected/serde_xml_rs.rs")]
264 SerdeXmlRs,
266}
267
268impl SerdeSupport {
269 #[must_use]
271 pub fn is_none(&self) -> bool {
272 matches!(self, Self::None)
273 }
274
275 #[must_use]
277 pub fn is_some(&self) -> bool {
278 !matches!(self, Self::None)
279 }
280}
281
282#[derive(Default, Debug)]
285pub(super) struct Modules(pub BTreeMap<Option<NamespaceId>, Module>);
286
287impl Modules {
288 pub(super) fn get_mut(&mut self, ns: Option<NamespaceId>) -> &mut Module {
289 self.0.entry(ns).or_default()
290 }
291}
292
293impl Deref for Modules {
294 type Target = BTreeMap<Option<NamespaceId>, Module>;
295
296 fn deref(&self) -> &Self::Target {
297 &self.0
298 }
299}
300
301#[derive(Default, Debug)]
304pub(super) struct Module {
305 pub main: ModuleCode,
306 pub quick_xml_serialize: Option<ModuleCode>,
307 pub quick_xml_deserialize: Option<ModuleCode>,
308}
309
310#[derive(Default, Debug)]
313pub(super) struct ModuleCode {
314 pub code: TokenStream,
315 pub usings: BTreeSet<String>,
316}
317
318impl ModuleCode {
319 pub(super) fn code(&mut self, code: TokenStream) -> &mut Self {
320 self.code.extend(code);
321
322 self
323 }
324
325 pub(super) fn usings<I>(&mut self, usings: I) -> &mut Self
326 where
327 I: IntoIterator,
328 I::Item: ToString,
329 {
330 for using in usings {
331 self.usings.insert(using.to_string());
332 }
333
334 self
335 }
336}
337
338impl ToTokens for ModuleCode {
339 fn to_tokens(&self, tokens: &mut TokenStream) {
340 let Self { code, usings } = self;
341 let usings = render_usings(usings.iter());
342
343 tokens.extend(quote! {
344 #usings
345 #code
346 });
347 }
348}
349
350#[derive(Debug)]
353pub(super) struct PendingType<'types> {
354 pub ty: &'types Type,
355 pub ident: Ident,
356}
357
358#[derive(Debug)]
361pub(super) struct TypeRef {
362 pub ident: Ident,
363 pub type_ident: Ident2,
364 pub module_ident: Option<Ident2>,
365 pub boxed_elements: HashSet<Ident>,
366}
367
368#[derive(Debug)]
371pub(super) struct TraitInfos(BTreeMap<Ident, TraitInfo>);
372
373impl TraitInfos {
374 #[must_use]
375 pub(super) fn new(types: &Types) -> Self {
376 let mut ret = Self(BTreeMap::new());
377
378 for (base_ident, ty) in types.iter() {
379 let TypeVariant::Dynamic(ai) = &ty.variant else {
380 continue;
381 };
382
383 for type_ident in &ai.derived_types {
384 ret.0
385 .entry(type_ident.clone())
386 .or_default()
387 .traits_all
388 .insert(base_ident.clone());
389
390 match types.get_variant(type_ident) {
391 Some(TypeVariant::Dynamic(DynamicInfo {
392 type_: Some(type_ident),
393 ..
394 })) => {
395 ret.0
396 .entry(type_ident.clone())
397 .or_default()
398 .traits_all
399 .insert(base_ident.clone());
400 }
401 Some(TypeVariant::Reference(ri)) if ri.is_single() => {
402 ret.0
403 .entry(ri.type_.clone())
404 .or_default()
405 .traits_all
406 .insert(base_ident.clone());
407 }
408 _ => (),
409 }
410 }
411 }
412
413 for ident in ret.0.keys().cloned().collect::<Vec<_>>() {
414 let mut traits_second_level = BTreeSet::new();
415
416 ret.collect_traits(&ident, 0, &mut traits_second_level);
417
418 let info = ret.0.get_mut(&ident).unwrap();
419 info.traits_direct = info
420 .traits_all
421 .difference(&traits_second_level)
422 .cloned()
423 .collect();
424 }
425
426 ret
427 }
428
429 fn collect_traits(
430 &self,
431 ident: &Ident,
432 depth: usize,
433 traits_second_level: &mut BTreeSet<Ident>,
434 ) {
435 if depth > 1 {
436 traits_second_level.insert(ident.clone());
437 }
438
439 if let Some(info) = self.0.get(ident) {
440 for trait_ in &info.traits_all {
441 self.collect_traits(trait_, depth + 1, traits_second_level);
442 }
443 }
444 }
445}
446
447impl Deref for TraitInfos {
448 type Target = BTreeMap<Ident, TraitInfo>;
449
450 fn deref(&self) -> &Self::Target {
451 &self.0
452 }
453}
454
455#[derive(Default, Debug)]
458pub(super) struct TraitInfo {
459 pub traits_all: BTreeSet<Ident>,
460 pub traits_direct: BTreeSet<Ident>,
461}
462
463#[derive(Default, Debug, Clone, Copy, Eq, PartialEq)]
466pub(super) enum Occurs {
467 #[default]
468 None,
469 Single,
470 Optional,
471 DynamicList,
472 StaticList(usize),
473}
474
475impl Occurs {
476 pub(super) fn from_occurs(min: MinOccurs, max: MaxOccurs) -> Self {
477 match (min, max) {
478 (0, MaxOccurs::Bounded(0)) => Self::None,
479 (1, MaxOccurs::Bounded(1)) => Self::Single,
480 (0, MaxOccurs::Bounded(1)) => Self::Optional,
481 (a, MaxOccurs::Bounded(b)) if a == b => Self::StaticList(a),
482 (_, _) => Self::DynamicList,
483 }
484 }
485
486 pub(super) fn make_type(
487 self,
488 ident: &TokenStream,
489 need_indirection: bool,
490 ) -> Option<TokenStream> {
491 match self {
492 Self::None => None,
493 Self::Single if need_indirection => Some(quote! { Box<#ident> }),
494 Self::Single => Some(quote! { #ident }),
495 Self::Optional if need_indirection => Some(quote! { Option<Box<#ident>> }),
496 Self::Optional => Some(quote! { Option<#ident> }),
497 Self::DynamicList => Some(quote! { Vec<#ident> }),
498 Self::StaticList(sz) if need_indirection => Some(quote! { [Box<#ident>; #sz] }),
499 Self::StaticList(sz) => Some(quote! { [#ident; #sz] }),
500 }
501 }
502
503 pub(super) fn is_some(&self) -> bool {
504 *self != Self::None
505 }
506
507 pub(super) fn is_direct(&self) -> bool {
508 matches!(self, Self::Single | Self::Optional | Self::StaticList(_))
509 }
510}
511
512#[derive(Default, Debug)]
515pub(super) enum DynTypeTraits {
516 #[default]
517 Auto,
518 Custom(Vec<TokenStream>),
519}
520
521#[derive(Debug, Clone)]
524pub(super) struct IdentPath {
525 path: Option<ModulePath>,
526 ident: Ident2,
527}
528
529#[derive(Default, Debug, Clone)]
530pub(super) struct ModulePath(pub SmallVec<[Ident2; 2]>);
531
532impl IdentPath {
533 pub(super) fn from_type_ref(type_ref: &TypeRef) -> Self {
534 if type_ref.ident.is_build_in() {
535 Self::from_ident(type_ref.type_ident.clone())
536 } else {
537 Self::from_ident(type_ref.type_ident.clone()).with_path(type_ref.module_ident.clone())
538 }
539 }
540
541 pub(super) fn from_parts<I>(path: I, ident: Ident2) -> Self
542 where
543 I: IntoIterator<Item = Ident2>,
544 {
545 Self::from_ident(ident).with_path(path)
546 }
547
548 pub(super) fn from_ident(ident: Ident2) -> Self {
549 Self { ident, path: None }
550 }
551
552 pub(super) fn with_ident(mut self, ident: Ident2) -> Self {
553 self.ident = ident;
554
555 self
556 }
557
558 pub(super) fn with_path<I>(mut self, path: I) -> Self
559 where
560 I: IntoIterator<Item = Ident2>,
561 {
562 self.path = Some(ModulePath(path.into_iter().collect()));
563
564 self
565 }
566
567 pub(super) fn into_parts(self) -> (Ident2, Option<ModulePath>) {
568 let Self { ident, path } = self;
569
570 (ident, path)
571 }
572
573 pub(super) fn ident(&self) -> &Ident2 {
574 &self.ident
575 }
576
577 pub(super) fn relative_to(&self, dst: &ModulePath) -> TokenStream {
578 let ident = &self.ident;
579
580 let Some(src) = &self.path else {
581 return quote!(#ident);
582 };
583
584 let mut ret = TokenStream::new();
585 let mut src = src.0.iter().fuse();
586 let mut dst = dst.0.iter().fuse();
587
588 macro_rules! push {
589 ($x:expr) => {{
590 let x = $x;
591 if ret.is_empty() {
592 ret.extend(x)
593 } else {
594 ret.extend(quote!(::#x))
595 }
596 }};
597 }
598
599 loop {
600 match (src.next(), dst.next()) {
601 (Some(a), Some(b)) if a == b => {}
602 (Some(a), Some(_)) => {
603 push!(quote!(super));
604 while dst.next().is_some() {
605 push!(quote!(super));
606 }
607
608 push!(quote!(#a));
609 for a in src {
610 push!(quote!(#a));
611 }
612
613 push!(quote!(#ident));
614
615 return ret;
616 }
617 (Some(a), None) => push!(quote!(#a)),
618 (None, Some(_)) => push!(quote!(super)),
619 (None, None) => {
620 push!(quote!(#ident));
621 return ret;
622 }
623 }
624 }
625 }
626}
627
628impl FromStr for IdentPath {
629 type Err = ();
630
631 fn from_str(s: &str) -> Result<Self, Self::Err> {
632 let mut ident = None;
633 let mut path = ModulePath::default();
634
635 for part in s.split("::") {
636 let part = part.trim();
637 if part.is_empty() {
638 continue;
639 }
640
641 if let Some(ident) = ident.take() {
642 path.0.push(ident);
643 }
644
645 ident = Some(format_ident!("{part}"));
646 }
647
648 Ok(Self {
649 ident: ident.ok_or(())?,
650 path: Some(path),
651 })
652 }
653}
654
655impl ModulePath {
656 pub(super) fn from_namespace(ns: Option<NamespaceId>, types: &Types) -> Self {
657 let ident = ns
658 .and_then(|id| types.modules.get(&id))
659 .and_then(|module| module.name.as_ref())
660 .map(format_module_ident);
661
662 Self(ident.into_iter().collect())
663 }
664
665 pub(super) fn join(mut self, other: Ident2) -> Self {
666 self.0.push(other);
667
668 self
669 }
670}
671
672impl Deref for ModulePath {
673 type Target = SmallVec<[Ident2; 2]>;
674
675 fn deref(&self) -> &Self::Target {
676 &self.0
677 }
678}
679
680impl DerefMut for ModulePath {
681 fn deref_mut(&mut self) -> &mut Self::Target {
682 &mut self.0
683 }
684}
685
686pub(super) fn format_field_name(name: &Name, display_name: Option<&str>) -> Cow<'static, str> {
689 if let Some(display_name) = display_name {
690 return Cow::Owned(display_name.to_snake_case());
691 }
692
693 let ident = name
694 .to_type_name(false, None)
695 .as_str()
696 .unwrap()
697 .to_snake_case();
698
699 match KEYWORDS.binary_search_by(|(key, _)| key.cmp(&ident.as_str())) {
700 Ok(idx) => Cow::Borrowed(KEYWORDS[idx].1),
701 Err(_) => {
702 if ident.starts_with(char::is_numeric) {
703 Cow::Owned(format!("_{ident}"))
704 } else {
705 Cow::Owned(ident)
706 }
707 }
708 }
709}
710
711pub(super) fn format_field_ident(name: &Name, display_name: Option<&str>) -> Ident2 {
712 let ident = format_field_name(name, display_name);
713
714 format_ident!("{ident}")
715}
716
717pub(super) fn format_module_ident(name: &Name) -> Ident2 {
718 format_field_ident(name, None)
719}
720
721pub(super) fn format_type_name(name: &Name, display_name: Option<&str>) -> String {
722 if let Some(display_name) = display_name {
723 return display_name.to_pascal_case();
724 }
725
726 let name = name
727 .to_type_name(false, None)
728 .as_str()
729 .unwrap()
730 .to_pascal_case();
731
732 if name.starts_with(char::is_numeric) {
733 format!("_{name}")
734 } else {
735 name
736 }
737}
738
739pub(super) fn format_type_ident(name: &Name, display_name: Option<&str>) -> Ident2 {
740 let ident = format_type_name(name, display_name);
741
742 format_ident!("{ident}")
743}
744
745pub(super) fn format_variant_ident(name: &Name, display_name: Option<&str>) -> Ident2 {
746 format_type_ident(name, display_name)
747}
748
749pub(super) fn format_module(
750 types: &Types,
751 ns: Option<NamespaceId>,
752) -> Result<Option<Ident2>, Error> {
753 let Some(ns) = ns else {
754 return Ok(None);
755 };
756
757 let module = types.modules.get(&ns).ok_or(Error::UnknownNamespace(ns))?;
758 let Some(name) = &module.name else {
759 return Ok(None);
760 };
761
762 Ok(Some(format_module_ident(name)))
763}
764
765pub(super) fn make_type_name(postfixes: &[String], ty: &Type, ident: &Ident) -> Name {
766 match (&ty.variant, &ident.name) {
767 (TypeVariant::Reference(ti), Name::Unnamed { .. }) if ti.type_.name.is_named() => {
768 match Occurs::from_occurs(ti.min_occurs, ti.max_occurs) {
769 Occurs::DynamicList => return Name::new(format!("{}List", ti.type_.name)),
770 Occurs::Optional => return Name::new(format!("{}Opt", ti.type_.name)),
771 _ => (),
772 }
773 }
774 (_, _) => (),
775 };
776
777 let postfix = postfixes
778 .get(ident.type_ as usize)
779 .map_or("", |s| s.as_str());
780
781 match &ident.name {
782 Name::Named(s) if s.ends_with(postfix) => Name::Named(s.clone()),
783 Name::Named(s) => Name::Named(Cow::Owned(format!("{}{postfix}", Name::unify(s)))),
784 name => name.to_type_name(false, None),
785 }
786}
787
788const KEYWORDS: &[(&str, &str)] = &[
789 ("abstract", "abstract_"),
790 ("as", "as_"),
791 ("become", "become_"),
792 ("box", "box_"),
793 ("break", "break_"),
794 ("const", "const_"),
795 ("continue", "continue_"),
796 ("crate", "crate_"),
797 ("do", "do_"),
798 ("else", "else_"),
799 ("enum", "enum_"),
800 ("extern", "extern_"),
801 ("false", "false_"),
802 ("final", "final_"),
803 ("fn", "fn_"),
804 ("for", "for_"),
805 ("if", "if_"),
806 ("impl", "impl_"),
807 ("in", "in_"),
808 ("let", "let_"),
809 ("loop", "loop_"),
810 ("macro", "macro_"),
811 ("match", "match_"),
812 ("mod", "mod_"),
813 ("move", "move_"),
814 ("mut", "mut_"),
815 ("override", "override_"),
816 ("priv", "priv_"),
817 ("pub", "pub_"),
818 ("ref", "ref_"),
819 ("return", "return_"),
820 ("self", "self_"),
821 ("Self", "Self_"),
822 ("static", "static_"),
823 ("struct", "struct_"),
824 ("super", "super_"),
825 ("trait", "trait_"),
826 ("true", "true_"),
827 ("try", "try_"),
828 ("type", "type_"),
829 ("typeof", "typeof_"),
830 ("union", "union_"),
831 ("unsafe", "unsafe_"),
832 ("unsized", "unsized_"),
833 ("use", "use_"),
834 ("virtual", "virtual_"),
835 ("where", "where_"),
836 ("while", "while_"),
837 ("yield", "yield_"),
838];
839
840#[cfg(test)]
841mod tests {
842 use quote::{format_ident, quote};
843
844 use crate::generator::misc::ModulePath;
845
846 use super::IdentPath;
847
848 #[test]
849 #[rustfmt::skip]
850 fn type_path() {
851 let string = IdentPath::from_ident(format_ident!("String"));
852 let my_type = IdentPath::from_parts(
853 [format_ident!("my_module")],
854 format_ident!("MyType"),
855 );
856 let serializer = IdentPath::from_parts(
857 [
858 format_ident!("my_module"),
859 format_ident!("quick_xml_serialize"),
860 ],
861 format_ident!("MyTypeSerializer"),
862 );
863 let deserializer = IdentPath::from_parts(
864 [
865 format_ident!("my_module"),
866 format_ident!("quick_xml_deserialize"),
867 ],
868 format_ident!("MyTypeDeserializer"),
869 );
870
871 let empty_path = ModulePath::default();
872 let module_path = ModulePath::default().join(format_ident!("my_module"));
873 let other_module_path = ModulePath::default().join(format_ident!("other_module"));
874 let serializer_path = module_path.clone().join(format_ident!("quick_xml_serialize"));
875 let deserializer_path = module_path.clone().join(format_ident!("quick_xml_deserialize"));
876
877 macro_rules! test {
878 ($actual:expr, $( $expected:tt )*) => {{
879 let a = $actual.to_string();
880 let b = quote!($( $expected )*).to_string();
881
882 assert_eq!(a, b);
883 }};
884 }
885
886 test!(string.relative_to(&empty_path), String);
889 test!(string.relative_to(&module_path), String);
890 test!(string.relative_to(&other_module_path), String);
891 test!(string.relative_to(&serializer_path), String);
892 test!(string.relative_to(&deserializer_path), String);
893
894 test!(my_type.relative_to(&empty_path), my_module::MyType);
895 test!(my_type.relative_to(&module_path), MyType);
896 test!(my_type.relative_to(&other_module_path), super::my_module::MyType);
897 test!(my_type.relative_to(&serializer_path), super::MyType);
898 test!(my_type.relative_to(&deserializer_path), super::MyType);
899
900 test!(serializer.relative_to(&empty_path), my_module::quick_xml_serialize::MyTypeSerializer);
901 test!(serializer.relative_to(&module_path), quick_xml_serialize::MyTypeSerializer);
902 test!(serializer.relative_to(&other_module_path), super::my_module::quick_xml_serialize::MyTypeSerializer);
903 test!(serializer.relative_to(&serializer_path), MyTypeSerializer);
904 test!(serializer.relative_to(&deserializer_path), super::quick_xml_serialize::MyTypeSerializer);
905
906 test!(deserializer.relative_to(&empty_path), my_module::quick_xml_deserialize::MyTypeDeserializer);
907 test!(deserializer.relative_to(&module_path), quick_xml_deserialize::MyTypeDeserializer);
908 test!(deserializer.relative_to(&other_module_path), super::my_module::quick_xml_deserialize::MyTypeDeserializer);
909 test!(deserializer.relative_to(&serializer_path), super::quick_xml_deserialize::MyTypeDeserializer);
910 test!(deserializer.relative_to(&deserializer_path), MyTypeDeserializer);
911 }
912}