Skip to main content

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    TypeIdent,
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 TypeIdent,
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    /// Get a mutable reference to the value that was stored for the specified key `K`.
190    /// If no value is available a new one is created with the provided function `f`.
191    pub fn get_or_create_with<K, F>(&mut self, f: F) -> &mut K::Type
192    where
193        K: ValueKey,
194        F: FnOnce() -> K::Type,
195    {
196        self.values.get_or_create_with::<K, _>(f)
197    }
198
199    /// Extracts the value stored for the specified key `K`.
200    ///
201    /// Panics if the key was not set before.
202    pub fn extract<K>(&mut self) -> K::Type
203    where
204        K: ValueKey,
205    {
206        self.values.extract::<K>()
207    }
208
209    /// Removes any values for the specified key `K`.
210    pub fn unset<K>(&mut self)
211    where
212        K: ValueKey,
213    {
214        self.values.unset::<K>();
215    }
216
217    /// Takes an iterator of usings (anything that implements `ToString`) and
218    /// executes [`patch_using`](Self::patch_using) for each element.
219    pub fn patch_usings<I>(&self, usings: I) -> impl Iterator<Item = String> + use<'_, I>
220    where
221        I: IntoIterator,
222        I::Item: ToString,
223    {
224        let alloc = &self.alloc_crate;
225        let xsd_parser_types = &self.xsd_parser_types;
226
227        usings.into_iter().map(move |s| {
228            Self::patch_using_impl(alloc, xsd_parser_types, Cow::Owned(s.to_string())).into_owned()
229        })
230    }
231
232    /// Replaces the `alloc::` and `xsd_parser::` in the path with the configured
233    /// name for the `alloc` and `xsd-parser` crate.
234    ///
235    /// See [`Renderer::alloc_crate`](crate::pipeline::Renderer::alloc_crate) and
236    /// [`Renderer::xsd_parser_types`](crate::pipeline::Renderer::xsd_parser_types)
237    /// for details.
238    ///
239    /// This should be used before you add using directives to a module manually.
240    /// Normally you should use [`add_usings`](Self::add_usings) which does the
241    /// patching automatically, but if you want to add code somewhere in the module
242    /// tree, this might be useful.
243    pub fn patch_using<'x>(&self, using: Cow<'x, str>) -> Cow<'x, str> {
244        Self::patch_using_impl(&self.alloc_crate, &self.xsd_parser_types, using)
245    }
246
247    pub(crate) fn resolve_root_ident_path(&self, path: &str) -> IdentPath {
248        self.resolve_ident_path_impl(path, Self::add_root_usings)
249    }
250
251    pub(crate) fn resolve_type_for_serialize_module(&self, target_type: &PathData) -> TokenStream {
252        self.add_quick_xml_serialize_usings(false, &target_type.usings);
253
254        target_type.resolve_relative_to(&self.serialize_module_path)
255    }
256
257    pub(crate) fn resolve_type_for_deserialize_module(
258        &self,
259        target_type: &PathData,
260    ) -> TokenStream {
261        self.add_quick_xml_deserialize_usings(false, &target_type.usings);
262
263        target_type.resolve_relative_to(&self.deserialize_module_path)
264    }
265
266    pub(crate) fn quick_xml_serialize(&mut self) -> &mut Module {
267        self.current_module().module_mut("quick_xml_serialize")
268    }
269
270    pub(crate) fn quick_xml_deserialize(&mut self) -> &mut Module {
271        self.current_module().module_mut("quick_xml_deserialize")
272    }
273
274    pub(crate) fn resolve_quick_xml_serialize_ident_path(&self, path: &str) -> IdentPath {
275        self.resolve_ident_path_impl(path, |x, path| {
276            x.add_quick_xml_serialize_usings(false, path);
277        })
278    }
279
280    pub(crate) fn resolve_quick_xml_deserialize_ident_path(&self, path: &str) -> IdentPath {
281        self.resolve_ident_path_impl(path, |x, path| {
282            x.add_quick_xml_deserialize_usings(false, path);
283        })
284    }
285
286    pub(crate) fn add_quick_xml_serialize_usings<I>(&self, anonymous: bool, usings: I)
287    where
288        I: IntoIterator,
289        I::Item: ToString,
290    {
291        let usings = self.patch_usings(usings);
292
293        let mut root = self.module.lock();
294        Self::get_current_module(&self.module_path.0, &mut root)
295            .module_mut("quick_xml_serialize")
296            .usings(anonymous, usings);
297    }
298
299    pub(crate) fn add_quick_xml_deserialize_usings<I>(&self, anonymous: bool, usings: I)
300    where
301        I: IntoIterator,
302        I::Item: ToString,
303    {
304        let usings = self.patch_usings(usings);
305
306        let mut root = self.module.lock();
307        Self::get_current_module(&self.module_path.0, &mut root)
308            .module_mut("quick_xml_deserialize")
309            .usings(anonymous, usings);
310    }
311
312    pub(super) fn new(
313        meta: &'a MetaData<'types>,
314        data: &'a DataType<'types>,
315        ident: &'a TypeIdent,
316        module: &'a mut Module,
317        values: Values,
318    ) -> Self {
319        let module_ident = ModuleIdent::new(
320            meta.types,
321            ident,
322            meta.check_generator_flags(GeneratorFlags::USE_NAMESPACE_MODULES),
323            meta.check_generator_flags(GeneratorFlags::USE_SCHEMA_MODULES),
324        );
325        let module_path = ModulePath::from_ident(meta.types.meta.types, module_ident);
326        let serialize_module_path = module_path
327            .clone()
328            .join(format_ident!("quick_xml_serialize"));
329        let deserialize_module_path = module_path
330            .clone()
331            .join(format_ident!("quick_xml_deserialize"));
332
333        Self {
334            meta,
335            data,
336            ident,
337            module: Mutex::new(module),
338
339            module_path,
340            serialize_module_path,
341            deserialize_module_path,
342
343            values,
344        }
345    }
346
347    fn get_current_module<I>(idents: I, root: &mut Module) -> &mut Module
348    where
349        I: IntoIterator,
350        I::Item: ToString,
351    {
352        let mut module = root;
353
354        for ident in idents {
355            module = module.module_mut(ident.to_string());
356        }
357
358        module
359    }
360
361    fn resolve_ident_path_impl<'x, F>(&self, path: &'x str, add_usings: F) -> IdentPath
362    where
363        F: FnOnce(&Self, [Cow<'x, str>; 1]),
364    {
365        let path = self.patch_using(Cow::Borrowed(path));
366        let ret = IdentPath::from_str(&path).unwrap();
367
368        if self.check_generator_flags(GeneratorFlags::ABSOLUTE_PATHS_INSTEAD_USINGS) {
369            ret
370        } else {
371            add_usings(self, [path]);
372            let (ident, _path, _absolute) = ret.into_parts();
373
374            IdentPath::from_ident(ident)
375        }
376    }
377
378    fn patch_using_impl<'x>(
379        alloc: &Ident2,
380        xsd_parser_types: &Ident2,
381        using: Cow<'x, str>,
382    ) -> Cow<'x, str> {
383        if let Some(s) = using.strip_prefix("xsd_parser_types::") {
384            Cow::Owned(format!("{xsd_parser_types}::{s}"))
385        } else if let Some(s) = using.strip_prefix("::xsd_parser_types::") {
386            Cow::Owned(format!("::{xsd_parser_types}::{s}"))
387        } else if let Some(s) = using.strip_prefix("alloc::") {
388            Cow::Owned(format!("{alloc}::{s}"))
389        } else if let Some(s) = using.strip_prefix("::alloc::") {
390            Cow::Owned(format!("::{alloc}::{s}"))
391        } else {
392            using
393        }
394    }
395}
396
397impl<'types> Deref for Context<'_, 'types> {
398    type Target = MetaData<'types>;
399
400    fn deref(&self) -> &Self::Target {
401        self.meta
402    }
403}
404
405/* Values */
406
407impl Values {
408    /// Create a new empty [`Values`] instance.
409    #[must_use]
410    pub fn new() -> Self {
411        Self::default()
412    }
413
414    /// Set a `value` for the specified key `K`.
415    pub fn set<K>(&mut self, value: K::Type)
416    where
417        K: ValueKey,
418    {
419        self.0.insert(TypeId::of::<K>(), Box::new(value));
420    }
421
422    /// Get the value that was stored for the specified key `K`.
423    ///
424    /// Panics if the key was not set before.
425    #[must_use]
426    pub fn get<K>(&self) -> K::Type
427    where
428        K: ValueKey,
429        K::Type: Clone,
430    {
431        self.get_ref::<K>().clone()
432    }
433
434    /// Get a reference to the value that was stored for the specified key `K`.
435    ///
436    /// Panics if the key was not set before.
437    #[must_use]
438    pub fn get_ref<K>(&self) -> &K::Type
439    where
440        K: ValueKey,
441    {
442        self.0
443            .get(&TypeId::of::<K>())
444            .unwrap()
445            .downcast_ref::<K::Type>()
446            .unwrap()
447    }
448
449    /// Get a mutable reference to the value that was stored for the specified key `K`.
450    ///
451    /// Panics if the key was not set before.
452    pub fn get_mut<K>(&mut self) -> &mut K::Type
453    where
454        K: ValueKey,
455    {
456        self.0
457            .get_mut(&TypeId::of::<K>())
458            .unwrap()
459            .downcast_mut::<K::Type>()
460            .unwrap()
461    }
462
463    /// Get a mutable reference to the value that was stored for the specified key `K`.
464    /// If no value is available a new one is created.
465    pub fn get_or_create<K>(&mut self) -> &mut K::Type
466    where
467        K: ValueKey,
468        K::Type: Default,
469    {
470        self.get_or_create_with::<K, _>(Default::default)
471    }
472
473    /// Get a mutable reference to the value that was stored for the specified key `K`.
474    /// If no value is available a new one is created with the provided function `f`.
475    pub fn get_or_create_with<K, F>(&mut self, f: F) -> &mut K::Type
476    where
477        K: ValueKey,
478        F: FnOnce() -> K::Type,
479    {
480        match self.0.entry(TypeId::of::<K>()) {
481            Entry::Vacant(e) => e.insert(Box::new(f())),
482            Entry::Occupied(e) => e.into_mut(),
483        }
484        .downcast_mut::<K::Type>()
485        .unwrap()
486    }
487
488    /// Extracts the value stored for the specified key `K`.
489    ///
490    /// Panics if the key was not set before.
491    pub fn extract<K>(&mut self) -> K::Type
492    where
493        K: ValueKey,
494    {
495        *self
496            .0
497            .remove(&TypeId::of::<K>())
498            .unwrap()
499            .downcast::<K::Type>()
500            .unwrap()
501    }
502
503    /// Removes any values for the specified key `K`.
504    pub fn unset<K>(&mut self)
505    where
506        K: ValueKey,
507    {
508        self.0.remove(&TypeId::of::<K>());
509    }
510}