1use proc_macro2::{Ident as Ident2, TokenStream};
2use quote::{format_ident, quote};
3
4use crate::config::{RendererFlags, TypedefMode};
5use crate::models::{
6 data::{
7 ComplexData, ComplexDataAttribute, ComplexDataContent, ComplexDataElement, ComplexDataEnum,
8 ComplexDataStruct, DynamicData, EnumerationData, EnumerationTypeVariant, Occurs,
9 ReferenceData, SimpleData, UnionData, UnionTypeVariant,
10 },
11 meta::{MetaType, MetaTypeVariant},
12 schema::xs::Use,
13 Ident,
14};
15use crate::traits::Naming;
16
17use super::super::super::{Context, DataTypeVariant, RenderStep, RenderStepType};
18use super::super::{format_traits, render_trait_impls};
19use super::{get_derive, get_dyn_type_traits};
20
21#[derive(Debug, Clone, Copy)]
24pub struct SerdeXmlRsV8TypesRenderStep;
25
26impl RenderStep for SerdeXmlRsV8TypesRenderStep {
27 fn render_step_type(&self) -> RenderStepType {
28 RenderStepType::Types
29 }
30
31 fn render_type(&mut self, ctx: &mut Context<'_, '_>) {
32 match &ctx.data.variant {
33 DataTypeVariant::BuildIn(_) | DataTypeVariant::Custom(_) => (),
34 DataTypeVariant::Union(x) => x.render_type_serde_xml_rs_v8(ctx),
35 DataTypeVariant::Dynamic(x) => x.render_type_serde_xml_rs_v8(ctx),
36 DataTypeVariant::Reference(x) => x.render_type_serde_xml_rs_v8(ctx),
37 DataTypeVariant::Enumeration(x) => x.render_type_serde_xml_rs_v8(ctx),
38 DataTypeVariant::Simple(x) => x.render_type_serde_xml_rs_v8(ctx),
39 DataTypeVariant::Complex(x) => x.render_type_serde_xml_rs_v8(ctx),
40 }
41 }
42}
43
44impl<'types> Context<'_, 'types> {
47 fn get_resolved_complex_content(&self) -> Option<(&'types Ident, &'types MetaType)> {
48 let MetaTypeVariant::ComplexType(cm) = &self.data.meta.variant else {
49 return None;
50 };
51
52 let content_ident = cm.content.as_ref()?;
53
54 self.meta.types.meta.types.get_resolved(content_ident)
55 }
56}
57
58impl Occurs {
61 fn array_to_vec(self) -> Self {
62 match self {
63 Self::StaticList(_) => Self::DynamicList,
64 x => x,
65 }
66 }
67}
68
69impl UnionData<'_> {
72 fn render_type_serde_xml_rs_v8(&self, ctx: &mut Context<'_, '_>) {
73 let Self {
74 type_ident,
75 trait_impls,
76 variants,
77 ..
78 } = self;
79 let docs = ctx.render_type_docs();
80 let derive = get_derive(ctx, []);
81 let trait_impls = render_trait_impls(type_ident, trait_impls);
82 let variants = variants
83 .iter()
84 .map(|x| x.render_variant_serde_xml_rs_v8(ctx));
85 let extra_attributes = &ctx.data.extra_attributes;
86
87 let code = quote! {
88 #docs
89 #derive
90 #( #[#extra_attributes] )*
91 pub enum #type_ident {
92 #( #variants )*
93 }
94
95 #( #trait_impls )*
96 };
97
98 ctx.current_module().append(code);
99
100 self.render_common_impls(ctx);
101 }
102}
103
104impl UnionTypeVariant<'_> {
107 fn render_variant_serde_xml_rs_v8(&self, ctx: &Context<'_, '_>) -> TokenStream {
108 let Self {
109 target_type,
110 variant_ident,
111 extra_attributes,
112 ..
113 } = self;
114
115 let target_type = ctx.resolve_type_for_module(target_type);
116
117 quote! {
118 #( #[#extra_attributes] )*
119 #variant_ident ( #target_type ),
120 }
121 }
122}
123
124impl DynamicData<'_> {
127 fn render_type_serde_xml_rs_v8(&self, ctx: &mut Context<'_, '_>) {
128 let Self {
129 type_ident,
130 trait_ident,
131 sub_traits,
132 ..
133 } = self;
134
135 let docs = ctx.render_type_docs();
136 let derive = get_derive(ctx, []);
137 let trait_impls = render_trait_impls(type_ident, &[]);
138 let dyn_traits = sub_traits.as_ref().map_or_else(
139 || get_dyn_type_traits(ctx),
140 |traits| format_traits(traits.iter().map(|x| ctx.resolve_type_for_module(x))),
141 );
142 let extra_attributes = &ctx.data.extra_attributes;
143
144 let box_ = ctx.resolve_build_in("::alloc::boxed::Box");
145
146 let code = quote! {
147 #docs
148 #derive
149 #( #[#extra_attributes] )*
150 pub struct #type_ident(pub #box_<dyn #trait_ident>);
151
152 pub trait #trait_ident: #dyn_traits { }
153
154 #( #trait_impls )*
155 };
156
157 ctx.current_module().append(code);
158 }
159}
160
161impl ReferenceData<'_> {
164 fn render_type_serde_xml_rs_v8(&self, ctx: &mut Context<'_, '_>) {
165 let Self {
166 mode,
167 occurs,
168 type_ident,
169 target_type,
170 trait_impls,
171 ..
172 } = self;
173
174 let docs = ctx.render_type_docs();
175 let occurs = occurs.array_to_vec();
176 let target_type = ctx.resolve_type_for_module(target_type);
177
178 let code = match mode {
179 TypedefMode::Auto => crate::unreachable!(),
180 TypedefMode::Typedef => {
181 let target_type = occurs.make_type(ctx, &target_type, false);
182 let trait_impls = render_trait_impls(type_ident, trait_impls);
183
184 quote! {
185 #docs
186 pub type #type_ident = #target_type;
187
188 #( #trait_impls )*
189 }
190 }
191 TypedefMode::NewType => {
192 let target_type = occurs.make_type(ctx, &target_type, false);
193 let extra_derive =
194 matches!(occurs, Occurs::Optional | Occurs::DynamicList).then_some("Default");
195 let derive = get_derive(ctx, extra_derive);
196 let trait_impls = render_trait_impls(type_ident, trait_impls);
197 let extra_attributes = &ctx.data.extra_attributes;
198
199 quote! {
200 #docs
201 #derive
202 #( #[#extra_attributes] )*
203 pub struct #type_ident(pub #target_type);
204
205 #( #trait_impls )*
206 }
207 }
208 };
209
210 ctx.current_module().append(code);
211 }
212}
213
214impl EnumerationData<'_> {
217 fn render_type_serde_xml_rs_v8(&self, ctx: &mut Context<'_, '_>) {
218 let Self {
219 type_ident,
220 variants,
221 trait_impls,
222 ..
223 } = self;
224
225 let values_ident = format_enum_values_ident(&*ctx.meta.types.naming, ctx.ident);
226
227 let docs = ctx.render_type_docs();
228 let derive = get_derive(ctx, []);
229 let trait_impls = render_trait_impls(type_ident, trait_impls);
230 let extra_attributes = &ctx.data.extra_attributes;
231
232 let variants = variants
233 .iter()
234 .map(|d| d.render_variant_serde_xml_rs_v8(ctx))
235 .collect::<Vec<_>>();
236
237 let from = ctx.resolve_build_in("::core::convert::From");
238 let deref = ctx.resolve_build_in("::core::ops::Deref");
239 let deref_mut = ctx.resolve_build_in("::core::ops::DerefMut");
240
241 ctx.add_usings(["::core::ops::Deref", "::core::ops::DerefMut"]);
242
243 let code = quote! {
244 #docs
245 #derive
246 pub struct #type_ident {
247 #[serde(rename = "#text")]
248 pub value: #values_ident,
249 }
250
251 impl #from<#values_ident> for #type_ident {
252 fn from(value: #values_ident) -> Self {
253 Self { value }
254 }
255 }
256
257 impl #from<#type_ident> for #values_ident {
258 fn from(value: #type_ident) -> Self {
259 value.value
260 }
261 }
262
263 impl #deref for #type_ident {
264 type Target = #values_ident;
265
266 fn deref(&self) -> &Self::Target {
267 &self.value
268 }
269 }
270
271 impl #deref_mut for #type_ident {
272 fn deref_mut(&mut self) -> &mut Self::Target {
273 &mut self.value
274 }
275 }
276
277 #derive
278 #( #[#extra_attributes] )*
279 pub enum #values_ident {
280 #( #variants )*
281 }
282
283 #( #trait_impls )*
284 };
285
286 ctx.current_module().append(code);
287
288 self.render_common_impls(ctx);
289 }
290}
291
292impl EnumerationTypeVariant<'_> {
293 fn render_variant_serde_xml_rs_v8(&self, ctx: &Context<'_, '_>) -> TokenStream {
294 let Self {
295 meta,
296 s_name,
297 variant_ident,
298 target_type,
299 extra_attributes,
300 ..
301 } = self;
302
303 let docs = ctx.render_docs(RendererFlags::RENDER_VARIANT_DOCS, &meta.documentation[..]);
304
305 let target_type = target_type.as_ref().map(|target_type| {
306 let target_type = ctx.resolve_type_for_module(target_type);
307
308 quote!((#target_type))
309 });
310
311 quote! {
312 #docs
313 #( #[#extra_attributes] )*
314 #[serde(rename = #s_name)]
315 #variant_ident #target_type,
316 }
317 }
318}
319
320impl SimpleData<'_> {
323 fn render_type_serde_xml_rs_v8(&self, ctx: &mut Context<'_, '_>) {
324 let Self {
325 occurs,
326 type_ident,
327 target_type,
328 trait_impls,
329 ..
330 } = self;
331
332 let docs = ctx.render_type_docs();
333 let target_type = ctx.resolve_type_for_module(target_type);
334 let target_type = occurs.make_type(ctx, &target_type, false);
335 let extra_attributes = &ctx.data.extra_attributes;
336
337 let derive = get_derive(ctx, []);
338 let trait_impls = render_trait_impls(type_ident, trait_impls);
339
340 let code = quote! {
341 #docs
342 #derive
343 #( #[#extra_attributes] )*
344 pub struct #type_ident(pub #target_type);
345
346 #( #trait_impls )*
347 };
348
349 ctx.current_module().append(code);
350
351 self.render_common_impls(ctx);
352 }
353}
354
355impl ComplexData<'_> {
358 fn render_type_serde_xml_rs_v8(&self, ctx: &mut Context<'_, '_>) {
359 match self {
360 Self::Enum {
361 type_,
362 content_type,
363 } => {
364 type_.render_type_serde_xml_rs_v8(ctx);
365
366 if let Some(content_type) = content_type {
367 content_type.render_type_serde_xml_rs_v8(ctx);
368 }
369 }
370 Self::Struct {
371 type_,
372 content_type,
373 } => {
374 type_.render_type_serde_xml_rs_v8(ctx);
375
376 if let Some(content_type) = content_type {
377 content_type.render_type_serde_xml_rs_v8(ctx);
378 }
379 }
380 }
381 }
382}
383
384impl ComplexDataEnum<'_> {
385 fn render_type_serde_xml_rs_v8(&self, ctx: &mut Context<'_, '_>) {
386 let docs = ctx.render_type_docs();
387 let derive = get_derive(ctx, []);
388 let type_ident = &self.type_ident;
389 let trait_impls = render_trait_impls(type_ident, &self.trait_impls);
390 let extra_attributes = &ctx.data.extra_attributes;
391
392 let variants = self
393 .elements
394 .iter()
395 .map(|x| x.render_variant_serde_xml_rs_v8(ctx));
396
397 let code = quote! {
398 #docs
399 #derive
400 #( #[#extra_attributes] )*
401 pub enum #type_ident {
402 #( #variants )*
403 }
404
405 #( #trait_impls )*
406 };
407
408 ctx.current_module().append(code);
409 }
410}
411
412impl ComplexDataStruct<'_> {
413 fn render_type_serde_xml_rs_v8(&self, ctx: &mut Context<'_, '_>) {
414 let docs = ctx.render_type_docs();
415 let derive = get_derive(ctx, []);
416 let type_ident = &self.type_ident;
417 let trait_impls = render_trait_impls(type_ident, &self.trait_impls);
418 let extra_attributes = &ctx.data.extra_attributes;
419
420 let attributes = self
421 .attributes
422 .iter()
423 .map(|x| x.render_field_serde_xml_rs_v8(ctx, type_ident));
424 let fields = self
425 .elements()
426 .iter()
427 .map(|x| x.render_field_serde_xml_rs_v8(ctx));
428 let content = self
429 .content()
430 .as_ref()
431 .and_then(|x| x.render_field_serde_xml_rs_v8(ctx));
432
433 let struct_data = if self.is_unit_struct() {
434 quote!(;)
435 } else {
436 quote! {
437 {
438 #( #attributes )*
439 #( #fields )*
440 #content
441 }
442 }
443 };
444
445 let code = quote! {
446 #docs
447 #derive
448 #( #[#extra_attributes] )*
449 pub struct #type_ident
450 #struct_data
451
452 #( #trait_impls )*
453 };
454
455 ctx.current_module().append(code);
456 }
457}
458
459impl ComplexDataContent<'_> {
460 fn render_field_serde_xml_rs_v8(&self, ctx: &Context<'_, '_>) -> Option<TokenStream> {
461 let target_type = ctx.resolve_type_for_module(&self.target_type);
462 let target_type = self
463 .occurs
464 .array_to_vec()
465 .make_type(ctx, &target_type, false)?;
466 let extra_attributes = &self.extra_attributes;
467
468 let default =
469 (self.is_empty_string_content(ctx) || self.min_occurs == 0).then(|| quote!(default,));
470
471 match ctx
472 .get_resolved_complex_content()
473 .map(|(ident, meta)| (ident, &meta.variant))
474 {
475 Some((ident, MetaTypeVariant::Enumeration(_))) => {
476 let enum_values_type = format_enum_values_ident(&*ctx.meta.types.naming, ident);
477
478 Some(quote! {
479 #( #[#extra_attributes] )*
480 #[serde(#default rename = "#text")]
481 pub content: #enum_values_type,
482 })
483 }
484 Some((_, MetaTypeVariant::BuildIn(_) | MetaTypeVariant::Reference(_))) => {
485 Some(quote! {
486 #( #[#extra_attributes] )*
487 #[serde(#default rename = "#text")]
488 pub content: #target_type,
489 })
490 }
491 None | Some((_, _)) => Some(quote! {
492 #( #[#extra_attributes] )*
493 #[serde(#default rename = "#content")]
494 pub content: #target_type,
495 }),
496 }
497 }
498}
499
500impl ComplexDataAttribute<'_> {
501 fn render_field_serde_xml_rs_v8(
502 &self,
503 ctx: &Context<'_, '_>,
504 type_ident: &Ident2,
505 ) -> TokenStream {
506 let Self {
507 tag_name,
508 ident: field_ident,
509 extra_attributes,
510 ..
511 } = self;
512
513 let tag_name = tag_name.get(true);
514
515 let target_type = ctx.resolve_type_for_module(&self.target_type);
516 let target_type = if self.is_option {
517 let option = ctx.resolve_build_in("::core::option::Option");
518
519 quote!(#option<#target_type>)
520 } else {
521 target_type
522 };
523
524 let default = if self.default_value.is_some() {
525 let default_path = format!("{type_ident}::default_{field_ident}");
526
527 quote!(default = #default_path,)
528 } else if self.meta.use_ == Use::Optional {
529 quote!(default,)
530 } else {
531 quote!()
532 };
533
534 let docs = ctx.render_docs(
535 RendererFlags::RENDER_ATTRIBUTE_DOCS,
536 &self.meta.documentation[..],
537 );
538
539 let name = format!("@{tag_name}");
540
541 quote! {
542 #docs
543 #( #[#extra_attributes] )*
544 #[serde(#default rename = #name)]
545 pub #field_ident: #target_type,
546 }
547 }
548}
549
550impl ComplexDataElement<'_> {
551 fn render_field_serde_xml_rs_v8(&self, ctx: &Context<'_, '_>) -> TokenStream {
552 let Self {
553 tag_name,
554 field_ident,
555 extra_attributes,
556 ..
557 } = self;
558
559 let name = if self.meta().is_text() {
560 "#text".to_owned()
561 } else {
562 tag_name.get(true)
563 };
564
565 let target_type = ctx.resolve_type_for_module(&self.target_type);
566 let target_type = self
567 .occurs
568 .array_to_vec()
569 .make_type(ctx, &target_type, self.need_indirection)
570 .unwrap();
571
572 let docs = ctx.render_docs(
573 RendererFlags::RENDER_ELEMENT_DOCS,
574 &self.meta().documentation[..],
575 );
576
577 let default = match self.occurs.array_to_vec() {
578 Occurs::None | Occurs::Single | Occurs::StaticList(_) => quote!(),
579 Occurs::Optional | Occurs::DynamicList => quote!(default,),
580 };
581
582 quote! {
583 #docs
584 #( #[#extra_attributes] )*
585 #[serde(#default rename = #name)]
586 pub #field_ident: #target_type,
587 }
588 }
589
590 fn render_variant_serde_xml_rs_v8(&self, ctx: &Context<'_, '_>) -> TokenStream {
591 let Self {
592 tag_name,
593 variant_ident,
594 extra_attributes,
595 ..
596 } = self;
597
598 let name = if self.meta().is_text() {
599 "#text".to_owned()
600 } else {
601 tag_name.get(true)
602 };
603
604 let target_type = ctx.resolve_type_for_module(&self.target_type);
605 let target_type =
606 self.occurs
607 .array_to_vec()
608 .make_type(ctx, &target_type, self.need_indirection);
609
610 let docs = ctx.render_docs(
611 RendererFlags::RENDER_ELEMENT_DOCS,
612 &self.meta().documentation[..],
613 );
614
615 quote! {
616 #docs
617 #( #[#extra_attributes] )*
618 #[serde(rename = #name)]
619 #variant_ident(#target_type),
620 }
621 }
622}
623
624fn format_enum_values_ident(naming: &dyn Naming, ident: &Ident) -> Ident2 {
625 let values_ident = naming.format_type_name(ident.name.as_str());
626
627 format_ident!("{values_ident}Value")
628}