xsd_parser/pipeline/renderer/
context.rs1use 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#[derive(Debug)]
27pub struct Context<'a, 'types> {
28 pub meta: &'a MetaData<'types>,
30
31 pub data: &'a DataType<'types>,
33
34 pub ident: &'a Ident,
36
37 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#[derive(Default, Debug)]
52pub struct Values(HashMap<TypeId, Box<dyn Any>>);
53
54pub trait ValueKey: Any {
57 type Type: Any;
62}
63
64impl<'a, 'types> Context<'a, 'types> {
65 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 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 pub fn resolve_ident_path(&self, path: &str) -> IdentPath {
101 self.resolve_ident_path_impl(path, Self::add_usings)
102 }
103
104 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 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 pub fn main_module(&mut self) -> &mut Module {
130 self.module.get_mut()
131 }
132
133 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 pub fn set<K>(&mut self, value: K::Type)
142 where
143 K: ValueKey,
144 {
145 self.values.set::<K>(value);
146 }
147
148 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 pub fn get_ref<K>(&self) -> &K::Type
163 where
164 K: ValueKey,
165 {
166 self.values.get_ref::<K>()
167 }
168
169 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 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 pub fn extract<K>(&mut self) -> K::Type
193 where
194 K: ValueKey,
195 {
196 self.values.extract::<K>()
197 }
198
199 pub fn unset<K>(&mut self)
201 where
202 K: ValueKey,
203 {
204 self.values.unset::<K>();
205 }
206
207 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 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
394impl Values {
397 #[must_use]
399 pub fn new() -> Self {
400 Self::default()
401 }
402
403 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 #[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 #[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 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 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 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 pub fn unset<K>(&mut self)
484 where
485 K: ValueKey,
486 {
487 self.0.remove(&TypeId::of::<K>());
488 }
489}