xsd_parser/generator/
context.rs

1use std::ops::Deref;
2
3use parking_lot::Mutex;
4use proc_macro2::{Ident as Ident2, TokenStream};
5use quote::format_ident;
6
7use crate::{
8    code::{IdentPath, Module, ModulePath},
9    schema::NamespaceId,
10    types::Ident,
11};
12
13use super::{Config, GeneratorFlags};
14
15/// Context for the rendering process.
16///
17/// This contains different additional information and configuration that may be
18/// needed by a [`Renderer`](super::Renderer) to render the actual code. It is
19/// also used to collect the rendered code and add it to the corresponding module.
20#[derive(Debug)]
21pub struct Context<'a, 'types> {
22    ident: &'a Ident,
23    config: &'a Config<'types>,
24    module: Mutex<&'a mut Module>,
25
26    module_path: ModulePath,
27    serialize_module_path: ModulePath,
28    deserialize_module_path: ModulePath,
29}
30
31impl<'a, 'types> Context<'a, 'types> {
32    /// Returns the namespace ID of the currently rendered type.
33    pub fn current_ns(&self) -> Option<NamespaceId> {
34        self.check_flags(GeneratorFlags::USE_MODULES)
35            .then_some(self.ident.ns)
36            .flatten()
37    }
38
39    /// Resolves the passed `ident` relative to the module of the current rendered type.
40    pub fn resolve_type_for_module(&self, ident: &IdentPath) -> TokenStream {
41        ident.relative_to(&self.module_path)
42    }
43
44    /// Add using directives to the module the of the current rendered type.
45    pub fn add_usings<I>(&self, usings: I)
46    where
47        I: IntoIterator,
48        I::Item: ToString,
49    {
50        let mut root = self.module.lock();
51        Self::main_module(self.module_path.last(), &mut root).usings(usings);
52    }
53
54    /// Returns a mutable reference to the module of the current rendered type.
55    pub fn module(&mut self) -> &mut Module {
56        let root = self.module.get_mut();
57
58        Self::main_module(self.module_path.last(), root)
59    }
60
61    pub(crate) fn resolve_type_for_serialize_module(&self, ident: &IdentPath) -> TokenStream {
62        ident.relative_to(&self.serialize_module_path)
63    }
64
65    pub(crate) fn resolve_type_for_deserialize_module(&self, ident: &IdentPath) -> TokenStream {
66        ident.relative_to(&self.deserialize_module_path)
67    }
68
69    pub(crate) fn quick_xml_serialize(&mut self) -> &mut Module {
70        self.module().module_mut("quick_xml_serialize")
71    }
72
73    pub(crate) fn quick_xml_deserialize(&mut self) -> &mut Module {
74        self.module().module_mut("quick_xml_deserialize")
75    }
76
77    pub(crate) fn add_quick_xml_serialize_usings<I>(&self, usings: I)
78    where
79        I: IntoIterator,
80        I::Item: ToString,
81    {
82        let mut root = self.module.lock();
83        Self::main_module(self.module_path.last(), &mut root)
84            .module_mut("quick_xml_serialize")
85            .usings(usings);
86    }
87
88    pub(crate) fn add_quick_xml_deserialize_usings<I>(&self, usings: I)
89    where
90        I: IntoIterator,
91        I::Item: ToString,
92    {
93        let mut root = self.module.lock();
94        Self::main_module(self.module_path.last(), &mut root)
95            .module_mut("quick_xml_deserialize")
96            .usings(usings);
97    }
98
99    pub(super) fn new(
100        ident: &'a Ident,
101        config: &'a Config<'types>,
102        module: &'a mut Module,
103    ) -> Self {
104        let ns = config
105            .check_flags(GeneratorFlags::USE_MODULES)
106            .then_some(ident.ns)
107            .flatten();
108        let module_path = ModulePath::from_namespace(ns, config.types);
109        let serialize_module_path = module_path
110            .clone()
111            .join(format_ident!("quick_xml_serialize"));
112        let deserialize_module_path = module_path
113            .clone()
114            .join(format_ident!("quick_xml_deserialize"));
115
116        Self {
117            ident,
118            config,
119            module: Mutex::new(module),
120
121            module_path,
122            serialize_module_path,
123            deserialize_module_path,
124        }
125    }
126
127    fn main_module<'x>(ident: Option<&Ident2>, root: &'x mut Module) -> &'x mut Module {
128        if let Some(ident) = ident {
129            root.module_mut(ident.to_string())
130        } else {
131            root
132        }
133    }
134}
135
136impl<'types> Deref for Context<'_, 'types> {
137    type Target = Config<'types>;
138
139    fn deref(&self) -> &Self::Target {
140        self.config
141    }
142}