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