xsd_parser/pipeline/renderer/
context.rs1use std::any::{Any, TypeId};
2use std::collections::HashMap;
3use std::ops::Deref;
4
5use parking_lot::Mutex;
6use proc_macro2::TokenStream;
7use quote::format_ident;
8
9use crate::config::GeneratorFlags;
10use crate::models::code::ModuleIdent;
11use crate::models::{
12 code::{Module, ModulePath},
13 data::{DataType, PathData},
14 Ident,
15};
16
17use super::MetaData;
18
19#[derive(Debug)]
25pub struct Context<'a, 'types> {
26 pub meta: &'a MetaData<'types>,
28
29 pub data: &'a DataType<'types>,
31
32 pub ident: &'a Ident,
34
35 module: Mutex<&'a mut Module>,
36
37 module_path: ModulePath,
38 serialize_module_path: ModulePath,
39 deserialize_module_path: ModulePath,
40
41 values: HashMap<TypeId, Box<dyn Any>>,
42}
43
44pub trait ValueKey: Any {
45 type Type: Any + Clone;
46}
47
48impl<'a, 'types> Context<'a, 'types> {
49 pub fn resolve_type_for_module(&self, target_type: &PathData) -> TokenStream {
51 self.add_usings(&target_type.usings);
52
53 target_type.resolve_relative_to(&self.module_path)
54 }
55
56 pub fn add_usings<I>(&self, usings: I)
58 where
59 I: IntoIterator,
60 I::Item: ToString,
61 {
62 let usings = self.patch_usings(usings);
63 let mut root = self.module.lock();
64 Self::get_current_module(&self.module_path.0, &mut root).usings(usings);
65 }
66
67 pub fn add_root_usings<I>(&self, usings: I)
69 where
70 I: IntoIterator,
71 I::Item: ToString,
72 {
73 let usings = self.patch_usings(usings);
74 self.module.lock().usings(usings);
75 }
76
77 pub fn main_module(&mut self) -> &mut Module {
82 self.module.get_mut()
83 }
84
85 pub fn current_module(&mut self) -> &mut Module {
87 let root = self.module.get_mut();
88
89 Self::get_current_module(&self.module_path.0, root)
90 }
91
92 pub fn set<K>(&mut self, value: K::Type)
94 where
95 K: ValueKey,
96 {
97 self.values.insert(TypeId::of::<K>(), Box::new(value));
98 }
99
100 pub fn get<K>(&self) -> K::Type
104 where
105 K: ValueKey,
106 {
107 self.get_ref::<K>().clone()
108 }
109
110 pub fn get_ref<K>(&self) -> &K::Type
114 where
115 K: ValueKey,
116 {
117 self.values
118 .get(&TypeId::of::<K>())
119 .unwrap()
120 .downcast_ref::<K::Type>()
121 .unwrap()
122 }
123
124 pub fn get_mut<K>(&mut self) -> &mut K::Type
128 where
129 K: ValueKey,
130 {
131 self.values
132 .get_mut(&TypeId::of::<K>())
133 .unwrap()
134 .downcast_mut::<K::Type>()
135 .unwrap()
136 }
137
138 pub fn unset<K>(&mut self)
140 where
141 K: ValueKey,
142 {
143 self.values.remove(&TypeId::of::<K>());
144 }
145
146 pub fn patch_usings<I>(&self, usings: I) -> impl Iterator<Item = String> + use<'_, I>
158 where
159 I: IntoIterator,
160 I::Item: ToString,
161 {
162 let xsd_parser = &self.xsd_parser_crate;
163
164 usings.into_iter().map(move |s| {
165 let s = s.to_string();
166
167 if let Some(s) = s.strip_prefix("xsd_parser::") {
168 format!("{xsd_parser}::{s}")
169 } else {
170 s
171 }
172 })
173 }
174
175 pub(crate) fn resolve_type_for_serialize_module(&self, target_type: &PathData) -> TokenStream {
176 self.add_quick_xml_serialize_usings(&target_type.usings);
177
178 target_type.resolve_relative_to(&self.serialize_module_path)
179 }
180
181 pub(crate) fn resolve_type_for_deserialize_module(
182 &self,
183 target_type: &PathData,
184 ) -> TokenStream {
185 self.add_quick_xml_deserialize_usings(&target_type.usings);
186
187 target_type.resolve_relative_to(&self.deserialize_module_path)
188 }
189
190 pub(crate) fn quick_xml_serialize(&mut self) -> &mut Module {
191 self.current_module().module_mut("quick_xml_serialize")
192 }
193
194 pub(crate) fn quick_xml_deserialize(&mut self) -> &mut Module {
195 self.current_module().module_mut("quick_xml_deserialize")
196 }
197
198 pub(crate) fn add_quick_xml_serialize_usings<I>(&self, usings: I)
199 where
200 I: IntoIterator,
201 I::Item: ToString,
202 {
203 let usings = self.patch_usings(usings);
204
205 let mut root = self.module.lock();
206 Self::get_current_module(&self.module_path.0, &mut root)
207 .module_mut("quick_xml_serialize")
208 .usings(usings);
209 }
210
211 pub(crate) fn add_quick_xml_deserialize_usings<I>(&self, usings: I)
212 where
213 I: IntoIterator,
214 I::Item: ToString,
215 {
216 let usings = self.patch_usings(usings);
217
218 let mut root = self.module.lock();
219 Self::get_current_module(&self.module_path.0, &mut root)
220 .module_mut("quick_xml_deserialize")
221 .usings(usings);
222 }
223
224 pub(super) fn new(
225 meta: &'a MetaData<'types>,
226 data: &'a DataType<'types>,
227 ident: &'a Ident,
228 module: &'a mut Module,
229 ) -> Self {
230 let module_ident = ModuleIdent::new(
231 meta.types,
232 ident,
233 meta.check_generator_flags(GeneratorFlags::USE_NAMESPACE_MODULES),
234 meta.check_generator_flags(GeneratorFlags::USE_SCHEMA_MODULES),
235 );
236 let module_path = ModulePath::from_ident(meta.types.meta.types, module_ident);
237 let serialize_module_path = module_path
238 .clone()
239 .join(format_ident!("quick_xml_serialize"));
240 let deserialize_module_path = module_path
241 .clone()
242 .join(format_ident!("quick_xml_deserialize"));
243
244 Self {
245 meta,
246 data,
247 ident,
248 module: Mutex::new(module),
249
250 module_path,
251 serialize_module_path,
252 deserialize_module_path,
253
254 values: HashMap::new(),
255 }
256 }
257
258 fn get_current_module<I>(idents: I, root: &mut Module) -> &mut Module
259 where
260 I: IntoIterator,
261 I::Item: ToString,
262 {
263 let mut module = root;
264
265 for ident in idents {
266 module = module.module_mut(ident.to_string());
267 }
268
269 module
270 }
271}
272
273impl<'types> Deref for Context<'_, 'types> {
274 type Target = MetaData<'types>;
275
276 fn deref(&self) -> &Self::Target {
277 self.meta
278 }
279}