xsd_parser/pipeline/renderer/steps/
with_namespace_trait.rs

1use proc_macro2::{Ident as Ident2, TokenStream};
2use quote::quote;
3
4use crate::models::data::{
5    ComplexData, ComplexDataEnum, ComplexDataStruct, DynamicData, EnumerationData, ReferenceData,
6    UnionData,
7};
8
9use super::super::{Context, DataTypeVariant, RenderStep};
10
11/// Implements a [`RenderStep`] that renders the [`WithNamespace`](crate::WithNamespace)
12/// trait for each type defined in the schema.
13#[derive(Debug)]
14pub struct WithNamespaceTraitRenderStep;
15
16impl RenderStep for WithNamespaceTraitRenderStep {
17    fn render_type(&mut self, ctx: &mut Context<'_, '_>) {
18        match &ctx.data.variant {
19            DataTypeVariant::BuildIn(_) | DataTypeVariant::Custom(_) => (),
20            DataTypeVariant::Union(x) => x.render_with_namespace_trait(ctx),
21            DataTypeVariant::Dynamic(x) => x.render_with_namespace_trait(ctx),
22            DataTypeVariant::Reference(x) => x.render_with_namespace_trait(ctx),
23            DataTypeVariant::Enumeration(x) => x.render_with_namespace_trait(ctx),
24            DataTypeVariant::Complex(x) => x.render_with_namespace_trait(ctx),
25        }
26    }
27}
28
29/* UnionType */
30
31impl UnionData<'_> {
32    pub(crate) fn render_with_namespace_trait(&self, ctx: &mut Context<'_, '_>) {
33        if let Some(code) = render_trait_with_namespace(ctx, &self.type_ident) {
34            ctx.module().append(code);
35        }
36    }
37}
38
39/* DynamicType */
40
41impl DynamicData<'_> {
42    pub(crate) fn render_with_namespace_trait(&self, ctx: &mut Context<'_, '_>) {
43        if let Some(code) = render_trait_with_namespace(ctx, &self.type_ident) {
44            ctx.module().append(code);
45        }
46    }
47}
48
49/* ReferenceType */
50
51impl ReferenceData<'_> {
52    pub(crate) fn render_with_namespace_trait(&self, ctx: &mut Context<'_, '_>) {
53        if let Some(code) = render_trait_with_namespace(ctx, &self.type_ident) {
54            ctx.module().append(code);
55        }
56    }
57}
58
59/* EnumerationType */
60
61impl EnumerationData<'_> {
62    pub(crate) fn render_with_namespace_trait(&self, ctx: &mut Context<'_, '_>) {
63        if let Some(code) = render_trait_with_namespace(ctx, &self.type_ident) {
64            ctx.module().append(code);
65        }
66    }
67}
68
69/* ComplexType */
70
71impl ComplexData<'_> {
72    pub(crate) fn render_with_namespace_trait(&self, ctx: &mut Context<'_, '_>) {
73        match self {
74            Self::Enum {
75                type_,
76                content_type,
77            } => {
78                type_.render_with_namespace_trait(ctx);
79
80                if let Some(content_type) = content_type {
81                    content_type.render_with_namespace_trait(ctx);
82                }
83            }
84            Self::Struct {
85                type_,
86                content_type,
87            } => {
88                type_.render_with_namespace_trait(ctx);
89
90                if let Some(content_type) = content_type {
91                    content_type.render_with_namespace_trait(ctx);
92                }
93            }
94        }
95    }
96}
97
98impl ComplexDataEnum<'_> {
99    fn render_with_namespace_trait(&self, ctx: &mut Context<'_, '_>) {
100        if let Some(code) = render_trait_with_namespace(ctx, &self.type_ident) {
101            ctx.module().append(code);
102        }
103    }
104}
105
106impl ComplexDataStruct<'_> {
107    fn render_with_namespace_trait(&self, ctx: &mut Context<'_, '_>) {
108        if let Some(code) = render_trait_with_namespace(ctx, &self.type_ident) {
109            ctx.module().append(code);
110        }
111    }
112}
113
114fn render_trait_with_namespace(ctx: &Context<'_, '_>, type_ident: &Ident2) -> Option<TokenStream> {
115    let ns = ctx.ident.ns.as_ref()?;
116    let module = ctx.types.meta.types.modules.get(ns)?;
117    let xsd_parser = &ctx.xsd_parser_crate;
118
119    let (prefix, namespace) = match (&module.name, &module.namespace) {
120        (Some(prefix), Some(namespace)) => {
121            let prefix = prefix.to_string();
122            let namespace = namespace.to_string();
123
124            (quote!(Some(#prefix)), quote!(Some(#namespace)))
125        }
126        (None, Some(namespace)) => {
127            let namespace = namespace.to_string();
128
129            (quote!(None), quote!(Some(#namespace)))
130        }
131        (_, None) => (quote!(None), quote!(None)),
132    };
133
134    Some(quote! {
135        impl #xsd_parser::WithNamespace for #type_ident {
136            fn prefix() -> Option<&'static str> {
137                #prefix
138            }
139
140            fn namespace() -> Option<&'static str> {
141                #namespace
142            }
143        }
144    })
145}