xsd_parser/pipeline/renderer/
context.rs

1use std::any::{Any, TypeId};
2use std::borrow::Cow;
3use std::collections::hash_map::{Entry, HashMap};
4use std::ops::Deref;
5use std::str::FromStr;
6
7use parking_lot::Mutex;
8use proc_macro2::{Ident as Ident2, TokenStream};
9use quote::format_ident;
10
11use crate::config::GeneratorFlags;
12use crate::models::code::{IdentPath, ModuleIdent};
13use crate::models::{
14    code::{Module, ModulePath},
15    data::{DataType, PathData},
16    Ident,
17};
18
19use super::MetaData;
20
21/// Context for the rendering process.
22///
23/// This contains different additional information and configuration that may be
24/// needed by a [`Renderer`](super::Renderer) to render the actual code. It is
25/// also used to collect the rendered code and add it to the corresponding module.
26#[derive(Debug)]
27pub struct Context<'a, 'types> {
28    /// Meta information for the rendering process.
29    pub meta: &'a MetaData<'types>,
30
31    /// Data type that needs to be rendered.
32    pub data: &'a DataType<'types>,
33
34    /// Identifier of the data type that needs to be rendered.
35    pub ident: &'a Ident,
36
37    /// Generic data storage for any type that implements [`ValueKey`].
38    pub values: Values,
39
40    module: Mutex<&'a mut Module>,
41
42    module_path: ModulePath,
43    serialize_module_path: ModulePath,
44    deserialize_module_path: ModulePath,
45}
46
47/// Cache that can store any value.
48///
49/// It uses a key type to identify the value inserted to the cache. The key type
50/// needs to implement [`ValueKey`].
51#[derive(Default, Debug)]
52pub struct Values(HashMap<TypeId, Box<dyn Any>>);
53
54/// Trait that represents a key of a certain type that can be stored in the
55/// [`Values`] cache.
56pub trait ValueKey: Any {
57    /// Actual value type that is stored in the [`Values`] cache.
58    ///
59    /// You can also use `Self` as type if you don't want to make use of a
60    /// separate key type.
61    type Type: Any;
62}
63
64impl<'a, 'types> Context<'a, 'types> {
65    /// Resolves the passed `ident` relative to the module of the current rendered type.
66    pub fn resolve_type_for_module(&self, target_type: &PathData) -> TokenStream {
67        self.add_usings(&target_type.usings);
68
69        target_type.resolve_relative_to(&self.module_path)
70    }
71
72    /// Resolves the passed identifier `path` for build-in types before it can
73    /// be rendered.
74    ///
75    /// If [`GeneratorFlags::BUILD_IN_ABSOLUTE_PATHS`] is set, the path is returned
76    /// as it, otherwise it will return the identifier only (without the path).
77    ///
78    /// # Panics
79    ///
80    /// Panics if the passed `path` is not a valid [`IdentPath`].
81    pub fn resolve_build_in(&self, path: &str) -> IdentPath {
82        let path = self.patch_using(Cow::Borrowed(path));
83        let path = IdentPath::from_str(&path).unwrap();
84
85        if self.check_generator_flags(GeneratorFlags::BUILD_IN_ABSOLUTE_PATHS) {
86            path
87        } else {
88            let (ident, _path, _absolute) = path.into_parts();
89
90            IdentPath::from_ident(ident)
91        }
92    }
93
94    /// Resolve the passed identifier `path` before it can be rendered.
95    ///
96    /// If [`GeneratorFlags::ABSOLUTE_PATHS_INSTEAD_USINGS`] is set this will
97    /// returns the `path` as is, otherwise it will add a suitable using
98    /// (see [`add_usings`](Context::add_usings)) and returns the identifier
99    /// only (without the path).
100    pub fn resolve_ident_path(&self, path: &str) -> IdentPath {
101        self.resolve_ident_path_impl(path, Self::add_usings)
102    }
103
104    /// Add using directives to the module the of the current rendered type.
105    pub fn add_usings<I>(&self, usings: I)
106    where
107        I: IntoIterator,
108        I::Item: ToString,
109    {
110        let usings = self.patch_usings(usings);
111        let mut root = self.module.lock();
112        Self::get_current_module(&self.module_path.0, &mut root).usings(false, usings);
113    }
114
115    /// Add using directives to the root module.
116    pub fn add_root_usings<I>(&self, usings: I)
117    where
118        I: IntoIterator,
119        I::Item: ToString,
120    {
121        let usings = self.patch_usings(usings);
122        self.module.lock().usings(false, usings);
123    }
124
125    /// Returns a mutable reference to the main module.
126    ///
127    /// This might be useful if you need to add code anywhere to the generated
128    /// result.
129    pub fn main_module(&mut self) -> &mut Module {
130        self.module.get_mut()
131    }
132
133    /// Returns a mutable reference to the module of the current rendered type.
134    pub fn current_module(&mut self) -> &mut Module {
135        let root = self.module.get_mut();
136
137        Self::get_current_module(&self.module_path.0, root)
138    }
139
140    /// Set a `value` for the specified key `K`.
141    pub fn set<K>(&mut self, value: K::Type)
142    where
143        K: ValueKey,
144    {
145        self.values.set::<K>(value);
146    }
147
148    /// Get the value that was stored for the specified key `K`.
149    ///
150    /// Panics if the key was not set before.
151    pub fn get<K>(&self) -> K::Type
152    where
153        K: ValueKey,
154        K::Type: Clone,
155    {
156        self.values.get::<K>()
157    }
158
159    /// Get a reference to the value that was stored for the specified key `K`.
160    ///
161    /// Panics if the key was not set before.
162    pub fn get_ref<K>(&self) -> &K::Type
163    where
164        K: ValueKey,
165    {
166        self.values.get_ref::<K>()
167    }
168
169    /// Get a mutable reference to the value that was stored for the specified key `K`.
170    ///
171    /// Panics if the key was not set before.
172    pub fn get_mut<K>(&mut self) -> &mut K::Type
173    where
174        K: ValueKey,
175    {
176        self.values.get_mut::<K>()
177    }
178
179    /// Get a mutable reference to the value that was stored for the specified key `K`.
180    /// If no value is available a new one is created.
181    pub fn get_or_create<K>(&mut self) -> &mut K::Type
182    where
183        K: ValueKey,
184        K::Type: Default,
185    {
186        self.values.get_or_create::<K>()
187    }
188
189    /// Extracts the value stored for the specified key `K`.
190    ///
191    /// Panics if the key was not set before.
192    pub fn extract<K>(&mut self) -> K::Type
193    where
194        K: ValueKey,
195    {
196        self.values.extract::<K>()
197    }
198
199    /// Removes any values for the specified key `K`.
200    pub fn unset<K>(&mut self)
201    where
202        K: ValueKey,
203    {
204        self.values.unset::<K>();
205    }
206
207    /// Takes an iterator of usings (anything that implements `ToString`) and
208    /// executes [`patch_using`](Self::patch_using) for each element.
209    pub fn patch_usings<I>(&self, usings: I) -> impl Iterator<Item = String> + use<'_, I>
210    where
211        I: IntoIterator,
212        I::Item: ToString,
213    {
214        let alloc = &self.alloc_crate;
215        let xsd_parser_types = &self.xsd_parser_types;
216
217        usings.into_iter().map(move |s| {
218            Self::patch_using_impl(alloc, xsd_parser_types, Cow::Owned(s.to_string())).into_owned()
219        })
220    }
221
222    /// Replaces the `alloc::` and `xsd_parser::` in the path with the configured
223    /// name for the `alloc` and `xsd-parser` crate.
224    ///
225    /// See [`Renderer::alloc_crate`](crate::pipeline::Renderer::alloc_crate) and
226    /// [`Renderer::xsd_parser_types`](crate::pipeline::Renderer::xsd_parser_types)
227    /// for details.
228    ///
229    /// This should be used before you add using directives to a module manually.
230    /// Normally you should use [`add_usings`](Self::add_usings) which does the
231    /// patching automatically, but if you want to add code somewhere in the module
232    /// tree, this might be useful.
233    pub fn patch_using<'x>(&self, using: Cow<'x, str>) -> Cow<'x, str> {
234        Self::patch_using_impl(&self.alloc_crate, &self.xsd_parser_types, using)
235    }
236
237    pub(crate) fn resolve_root_ident_path(&self, path: &str) -> IdentPath {
238        self.resolve_ident_path_impl(path, Self::add_root_usings)
239    }
240
241    pub(crate) fn resolve_type_for_serialize_module(&self, target_type: &PathData) -> TokenStream {
242        self.add_quick_xml_serialize_usings(false, &target_type.usings);
243
244        target_type.resolve_relative_to(&self.serialize_module_path)
245    }
246
247    pub(crate) fn resolve_type_for_deserialize_module(
248        &self,
249        target_type: &PathData,
250    ) -> TokenStream {
251        self.add_quick_xml_deserialize_usings(false, &target_type.usings);
252
253        target_type.resolve_relative_to(&self.deserialize_module_path)
254    }
255
256    pub(crate) fn quick_xml_serialize(&mut self) -> &mut Module {
257        self.current_module().module_mut("quick_xml_serialize")
258    }
259
260    pub(crate) fn quick_xml_deserialize(&mut self) -> &mut Module {
261        self.current_module().module_mut("quick_xml_deserialize")
262    }
263
264    pub(crate) fn resolve_quick_xml_serialize_ident_path(&self, path: &str) -> IdentPath {
265        self.resolve_ident_path_impl(path, |x, path| {
266            x.add_quick_xml_serialize_usings(false, path);
267        })
268    }
269
270    pub(crate) fn resolve_quick_xml_deserialize_ident_path(&self, path: &str) -> IdentPath {
271        self.resolve_ident_path_impl(path, |x, path| {
272            x.add_quick_xml_deserialize_usings(false, path);
273        })
274    }
275
276    pub(crate) fn add_quick_xml_serialize_usings<I>(&self, anonymous: bool, usings: I)
277    where
278        I: IntoIterator,
279        I::Item: ToString,
280    {
281        let usings = self.patch_usings(usings);
282
283        let mut root = self.module.lock();
284        Self::get_current_module(&self.module_path.0, &mut root)
285            .module_mut("quick_xml_serialize")
286            .usings(anonymous, usings);
287    }
288
289    pub(crate) fn add_quick_xml_deserialize_usings<I>(&self, anonymous: bool, usings: I)
290    where
291        I: IntoIterator,
292        I::Item: ToString,
293    {
294        let usings = self.patch_usings(usings);
295
296        let mut root = self.module.lock();
297        Self::get_current_module(&self.module_path.0, &mut root)
298            .module_mut("quick_xml_deserialize")
299            .usings(anonymous, usings);
300    }
301
302    pub(super) fn new(
303        meta: &'a MetaData<'types>,
304        data: &'a DataType<'types>,
305        ident: &'a Ident,
306        module: &'a mut Module,
307    ) -> Self {
308        let module_ident = ModuleIdent::new(
309            meta.types,
310            ident,
311            meta.check_generator_flags(GeneratorFlags::USE_NAMESPACE_MODULES),
312            meta.check_generator_flags(GeneratorFlags::USE_SCHEMA_MODULES),
313        );
314        let module_path = ModulePath::from_ident(meta.types.meta.types, module_ident);
315        let serialize_module_path = module_path
316            .clone()
317            .join(format_ident!("quick_xml_serialize"));
318        let deserialize_module_path = module_path
319            .clone()
320            .join(format_ident!("quick_xml_deserialize"));
321
322        Self {
323            meta,
324            data,
325            ident,
326            module: Mutex::new(module),
327
328            module_path,
329            serialize_module_path,
330            deserialize_module_path,
331
332            values: Values::new(),
333        }
334    }
335
336    fn get_current_module<I>(idents: I, root: &mut Module) -> &mut Module
337    where
338        I: IntoIterator,
339        I::Item: ToString,
340    {
341        let mut module = root;
342
343        for ident in idents {
344            module = module.module_mut(ident.to_string());
345        }
346
347        module
348    }
349
350    fn resolve_ident_path_impl<'x, F>(&self, path: &'x str, add_usings: F) -> IdentPath
351    where
352        F: FnOnce(&Self, [Cow<'x, str>; 1]),
353    {
354        let path = self.patch_using(Cow::Borrowed(path));
355        let ret = IdentPath::from_str(&path).unwrap();
356
357        if self.check_generator_flags(GeneratorFlags::ABSOLUTE_PATHS_INSTEAD_USINGS) {
358            ret
359        } else {
360            add_usings(self, [path]);
361            let (ident, _path, _absolute) = ret.into_parts();
362
363            IdentPath::from_ident(ident)
364        }
365    }
366
367    fn patch_using_impl<'x>(
368        alloc: &Ident2,
369        xsd_parser_types: &Ident2,
370        using: Cow<'x, str>,
371    ) -> Cow<'x, str> {
372        if let Some(s) = using.strip_prefix("xsd_parser_types::") {
373            Cow::Owned(format!("{xsd_parser_types}::{s}"))
374        } else if let Some(s) = using.strip_prefix("::xsd_parser_types::") {
375            Cow::Owned(format!("::{xsd_parser_types}::{s}"))
376        } else if let Some(s) = using.strip_prefix("alloc::") {
377            Cow::Owned(format!("{alloc}::{s}"))
378        } else if let Some(s) = using.strip_prefix("::alloc::") {
379            Cow::Owned(format!("::{alloc}::{s}"))
380        } else {
381            using
382        }
383    }
384}
385
386impl<'types> Deref for Context<'_, 'types> {
387    type Target = MetaData<'types>;
388
389    fn deref(&self) -> &Self::Target {
390        self.meta
391    }
392}
393
394/* Values */
395
396impl Values {
397    /// Create a new empty [`Values`] instance.
398    #[must_use]
399    pub fn new() -> Self {
400        Self::default()
401    }
402
403    /// Set a `value` for the specified key `K`.
404    pub fn set<K>(&mut self, value: K::Type)
405    where
406        K: ValueKey,
407    {
408        self.0.insert(TypeId::of::<K>(), Box::new(value));
409    }
410
411    /// Get the value that was stored for the specified key `K`.
412    ///
413    /// Panics if the key was not set before.
414    #[must_use]
415    pub fn get<K>(&self) -> K::Type
416    where
417        K: ValueKey,
418        K::Type: Clone,
419    {
420        self.get_ref::<K>().clone()
421    }
422
423    /// Get a reference to the value that was stored for the specified key `K`.
424    ///
425    /// Panics if the key was not set before.
426    #[must_use]
427    pub fn get_ref<K>(&self) -> &K::Type
428    where
429        K: ValueKey,
430    {
431        self.0
432            .get(&TypeId::of::<K>())
433            .unwrap()
434            .downcast_ref::<K::Type>()
435            .unwrap()
436    }
437
438    /// Get a mutable reference to the value that was stored for the specified key `K`.
439    ///
440    /// Panics if the key was not set before.
441    pub fn get_mut<K>(&mut self) -> &mut K::Type
442    where
443        K: ValueKey,
444    {
445        self.0
446            .get_mut(&TypeId::of::<K>())
447            .unwrap()
448            .downcast_mut::<K::Type>()
449            .unwrap()
450    }
451
452    /// Get a mutable reference to the value that was stored for the specified key `K`.
453    /// If no value is available a new one is created.
454    pub fn get_or_create<K>(&mut self) -> &mut K::Type
455    where
456        K: ValueKey,
457        K::Type: Default,
458    {
459        match self.0.entry(TypeId::of::<K>()) {
460            Entry::Vacant(e) => e.insert(Box::new(<K::Type as Default>::default())),
461            Entry::Occupied(e) => e.into_mut(),
462        }
463        .downcast_mut::<K::Type>()
464        .unwrap()
465    }
466
467    /// Extracts the value stored for the specified key `K`.
468    ///
469    /// Panics if the key was not set before.
470    pub fn extract<K>(&mut self) -> K::Type
471    where
472        K: ValueKey,
473    {
474        *self
475            .0
476            .remove(&TypeId::of::<K>())
477            .unwrap()
478            .downcast::<K::Type>()
479            .unwrap()
480    }
481
482    /// Removes any values for the specified key `K`.
483    pub fn unset<K>(&mut self)
484    where
485        K: ValueKey,
486    {
487        self.0.remove(&TypeId::of::<K>());
488    }
489}