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