xsd_parser/pipeline/renderer/steps/
defaults.rs

1use proc_macro2::TokenStream;
2use quote::{format_ident, quote};
3
4use crate::models::data::{ComplexData, ComplexDataAttribute, ComplexDataStruct, DataTypeVariant};
5
6use super::super::{Context, RenderStep, RenderStepType};
7
8/// Implements a [`RenderStep`] that renders associated methods that return the default
9/// values of the different attributes and elements according to the schema.
10#[derive(Debug, Clone, Copy)]
11pub struct DefaultsRenderStep;
12
13impl RenderStep for DefaultsRenderStep {
14    fn render_step_type(&self) -> RenderStepType {
15        RenderStepType::ExtraImpls
16    }
17
18    fn render_type(&mut self, ctx: &mut Context<'_, '_>) {
19        if let DataTypeVariant::Complex(x) = &ctx.data.variant {
20            x.render_defaults(ctx);
21        }
22    }
23}
24
25/* ComplexData */
26
27impl ComplexData<'_> {
28    pub(crate) fn render_defaults(&self, ctx: &mut Context<'_, '_>) {
29        match self {
30            ComplexData::Enum {
31                type_: _,
32                content_type,
33            } => {
34                if let Some(content_type) = content_type {
35                    content_type.render_defaults(ctx);
36                }
37            }
38            ComplexData::Struct {
39                type_,
40                content_type,
41            } => {
42                type_.render_defaults(ctx);
43
44                if let Some(content_type) = content_type {
45                    content_type.render_defaults(ctx);
46                }
47            }
48        }
49    }
50}
51
52impl ComplexDataStruct<'_> {
53    pub(crate) fn render_defaults(&self, ctx: &mut Context<'_, '_>) {
54        let type_ident = &self.type_ident;
55        let mut has_attributes = false;
56        let attribute_defaults = self
57            .attributes
58            .iter()
59            .filter_map(|attrib| attrib.render_default_fn(ctx))
60            .inspect(|_| has_attributes = true);
61
62        let impl_ = quote! {
63            impl #type_ident {
64                #( #attribute_defaults )*
65            }
66        };
67
68        if has_attributes {
69            ctx.current_module().append(impl_);
70        }
71    }
72}
73
74impl ComplexDataAttribute<'_> {
75    fn render_default_fn(&self, ctx: &Context<'_, '_>) -> Option<TokenStream> {
76        let default = self.default_value.as_ref()?;
77        let target_ident = ctx.resolve_type_for_module(&self.target_type);
78        let default_fn_ident = format_ident!("default_{}", self.ident);
79
80        Some(quote! {
81            #[must_use]
82            pub fn #default_fn_ident() -> #target_ident {
83                #default
84            }
85        })
86    }
87}