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 TypeIdent,
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 TypeIdent,
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 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 pub fn extract<K>(&mut self) -> K::Type
203 where
204 K: ValueKey,
205 {
206 self.values.extract::<K>()
207 }
208
209 pub fn unset<K>(&mut self)
211 where
212 K: ValueKey,
213 {
214 self.values.unset::<K>();
215 }
216
217 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 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
405impl Values {
408 #[must_use]
410 pub fn new() -> Self {
411 Self::default()
412 }
413
414 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 #[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 #[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 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 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 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 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 pub fn unset<K>(&mut self)
505 where
506 K: ValueKey,
507 {
508 self.0.remove(&TypeId::of::<K>());
509 }
510}