xsd_parser/pipeline/renderer/steps/
prefix_const.rs

1use std::mem::replace;
2
3use proc_macro2::Literal;
4use quote::quote;
5
6use crate::models::code::IdentPath;
7
8use super::super::{Context, MetaData, Module, RenderStep, RenderStepType};
9
10/// Implements a [`RenderStep`] that renders constants for the different namespaces
11/// used in the schema.
12#[derive(Default, Debug)]
13pub struct PrefixConstantsRenderStep(State);
14
15#[derive(Default, Debug)]
16enum State {
17    #[default]
18    ResolveNamespace,
19    NamespaceResolved(IdentPath),
20    Done,
21}
22
23impl RenderStep for PrefixConstantsRenderStep {
24    fn render_step_type(&self) -> RenderStepType {
25        RenderStepType::ExtraImpls
26    }
27
28    fn initialize(&mut self, meta: &mut MetaData<'_>) {
29        if meta.types.meta.types.modules.is_empty() {
30            self.0 = State::Done;
31        }
32    }
33
34    fn render_type(&mut self, ctx: &mut Context<'_, '_>) {
35        if matches!(&self.0, State::ResolveNamespace) {
36            self.0 = State::NamespaceResolved(
37                ctx.resolve_root_ident_path("xsd_parser_types::misc::NamespacePrefix"),
38            );
39        }
40    }
41
42    fn finish(&mut self, meta: &MetaData<'_>, module: &mut Module) {
43        let State::NamespaceResolved(prefix) = replace(&mut self.0, State::Done) else {
44            return;
45        };
46
47        let prefix_constants = meta.types.meta.types.modules.values().filter_map(|module| {
48            let pfx = module.prefix()?;
49            let const_name = module.make_prefix_const()?;
50            let const_name = const_name.path.ident();
51            let prefix_literal = Literal::byte_string(pfx.as_str().as_bytes());
52
53            Some(quote! {
54                pub const #const_name: #prefix = #prefix::new_const(#prefix_literal);
55            })
56        });
57
58        module.prepend(quote! { #( #prefix_constants )* });
59    }
60}