xsd_parser/pipeline/renderer/steps/serde/
serde_xml_rs_v7.rs1use proc_macro2::{Ident as Ident2, TokenStream};
2use quote::quote;
3
4use crate::config::{RendererFlags, TypedefMode};
5use crate::models::{
6 data::{
7 ComplexData, ComplexDataAttribute, ComplexDataContent, ComplexDataElement, ComplexDataEnum,
8 ComplexDataStruct, DynamicData, EnumerationData, EnumerationDataVariant, Occurs,
9 ReferenceData, SimpleData, UnionData, UnionTypeVariant,
10 },
11 schema::xs::Use,
12};
13
14use super::super::super::{Context, DataTypeVariant, RenderStep, RenderStepType};
15use super::super::{format_traits, render_trait_impls};
16use super::{get_derive, get_dyn_type_traits};
17
18#[derive(Debug, Clone, Copy)]
21pub struct SerdeXmlRsV7TypesRenderStep;
22
23impl RenderStep for SerdeXmlRsV7TypesRenderStep {
24 fn render_step_type(&self) -> RenderStepType {
25 RenderStepType::Types
26 }
27
28 fn render_type(&mut self, ctx: &mut Context<'_, '_>) {
29 match &ctx.data.variant {
30 DataTypeVariant::BuildIn(_) | DataTypeVariant::Custom(_) => (),
31 DataTypeVariant::Union(x) => x.render_type_serde_xml_rs_v7(ctx),
32 DataTypeVariant::Dynamic(x) => x.render_type_serde_xml_rs_v7(ctx),
33 DataTypeVariant::Reference(x) => x.render_type_serde_xml_rs_v7(ctx),
34 DataTypeVariant::Enumeration(x) => x.render_type_serde_xml_rs_v7(ctx),
35 DataTypeVariant::Simple(x) => x.render_type_serde_xml_rs_v7(ctx),
36 DataTypeVariant::Complex(x) => x.render_type_serde_xml_rs_v7(ctx),
37 }
38 }
39}
40
41impl UnionData<'_> {
44 fn render_type_serde_xml_rs_v7(&self, ctx: &mut Context<'_, '_>) {
45 let Self {
46 type_ident,
47 trait_impls,
48 variants,
49 ..
50 } = self;
51 let docs = ctx.render_type_docs();
52 let derive = get_derive(ctx, []);
53 let trait_impls = render_trait_impls(type_ident, trait_impls);
54 let variants = variants
55 .iter()
56 .map(|x| x.render_variant_serde_xml_rs_v7(ctx));
57 let extra_attributes = &ctx.data.extra_attributes;
58
59 let code = quote! {
60 #docs
61 #derive
62 #( #[#extra_attributes] )*
63 pub enum #type_ident {
64 #( #variants )*
65 }
66
67 #( #trait_impls )*
68 };
69
70 ctx.current_module().append(code);
71
72 self.render_common_impls(ctx);
73 }
74}
75
76impl UnionTypeVariant<'_> {
79 fn render_variant_serde_xml_rs_v7(&self, ctx: &Context<'_, '_>) -> TokenStream {
80 let Self {
81 target_type,
82 variant_ident,
83 extra_attributes,
84 ..
85 } = self;
86
87 let target_type = ctx.resolve_type_for_module(target_type);
88
89 quote! {
90 #( #[#extra_attributes] )*
91 #variant_ident ( #target_type ),
92 }
93 }
94}
95
96impl DynamicData<'_> {
99 fn render_type_serde_xml_rs_v7(&self, ctx: &mut Context<'_, '_>) {
100 let Self {
101 type_ident,
102 trait_ident,
103 sub_traits,
104 ..
105 } = self;
106
107 let docs = ctx.render_type_docs();
108 let derive = get_derive(ctx, []);
109 let trait_impls = render_trait_impls(type_ident, &[]);
110 let dyn_traits = sub_traits.as_ref().map_or_else(
111 || get_dyn_type_traits(ctx),
112 |traits| format_traits(traits.iter().map(|x| ctx.resolve_type_for_module(x))),
113 );
114 let extra_attributes = &ctx.data.extra_attributes;
115
116 let box_ = ctx.resolve_build_in("::alloc::boxed::Box");
117
118 let code = quote! {
119 #docs
120 #derive
121 #( #[#extra_attributes] )*
122 pub struct #type_ident(pub #box_<dyn #trait_ident>);
123
124 pub trait #trait_ident: #dyn_traits { }
125
126 #( #trait_impls )*
127 };
128
129 ctx.current_module().append(code);
130 }
131}
132
133impl ReferenceData<'_> {
136 fn render_type_serde_xml_rs_v7(&self, ctx: &mut Context<'_, '_>) {
137 let Self {
138 mode,
139 occurs,
140 type_ident,
141 target_type,
142 trait_impls,
143 ..
144 } = self;
145
146 let docs = ctx.render_type_docs();
147 let target_type = ctx.resolve_type_for_module(target_type);
148
149 let code = match mode {
150 TypedefMode::Auto => crate::unreachable!(),
151 TypedefMode::Typedef => {
152 let target_type = occurs.make_type(ctx, &target_type, false);
153
154 quote! {
155 #docs
156 pub type #type_ident = #target_type;
157 }
158 }
159 TypedefMode::NewType => {
160 let target_type = occurs.make_type(ctx, &target_type, false);
161 let extra_derive =
162 matches!(occurs, Occurs::Optional | Occurs::DynamicList).then_some("Default");
163 let derive = get_derive(ctx, extra_derive);
164 let trait_impls = render_trait_impls(type_ident, trait_impls);
165 let extra_attributes = &ctx.data.extra_attributes;
166
167 quote! {
168 #docs
169 #derive
170 #( #[#extra_attributes] )*
171 pub struct #type_ident(pub #target_type);
172
173 #( #trait_impls )*
174 }
175 }
176 };
177
178 ctx.current_module().append(code);
179 }
180}
181
182impl EnumerationData<'_> {
185 fn render_type_serde_xml_rs_v7(&self, ctx: &mut Context<'_, '_>) {
186 let Self {
187 type_ident,
188 variants,
189 trait_impls,
190 ..
191 } = self;
192
193 let docs = ctx.render_type_docs();
194 let derive = get_derive(ctx, []);
195 let trait_impls = render_trait_impls(type_ident, trait_impls);
196 let extra_attributes = &ctx.data.extra_attributes;
197
198 let variants = variants
199 .iter()
200 .map(|d| d.render_variant_serde_xml_rs_v7(ctx))
201 .collect::<Vec<_>>();
202
203 let code = quote! {
204 #docs
205 #derive
206 #( #[#extra_attributes] )*
207 pub enum #type_ident {
208 #( #variants )*
209 }
210
211 #( #trait_impls )*
212 };
213
214 ctx.current_module().append(code);
215
216 self.render_common_impls(ctx);
217 }
218}
219
220impl EnumerationDataVariant<'_> {
221 fn render_variant_serde_xml_rs_v7(&self, ctx: &Context<'_, '_>) -> TokenStream {
222 let Self {
223 meta,
224 s_name,
225 variant_ident,
226 target_type,
227 extra_attributes,
228 ..
229 } = self;
230
231 let docs = ctx.render_docs(RendererFlags::RENDER_VARIANT_DOCS, &meta.documentation[..]);
232
233 let serde = if meta.type_.is_some() {
234 quote!(#[serde(other)])
235 } else {
236 quote!(#[serde(rename = #s_name)])
237 };
238
239 let target_type = target_type.as_ref().map(|target_type| {
240 let target_type = ctx.resolve_type_for_module(target_type);
241
242 quote!((#target_type))
243 });
244
245 quote! {
246 #docs
247 #serde
248 #( #[#extra_attributes] )*
249 #variant_ident #target_type,
250 }
251 }
252}
253
254impl SimpleData<'_> {
257 fn render_type_serde_xml_rs_v7(&self, ctx: &mut Context<'_, '_>) {
258 let Self {
259 occurs,
260 type_ident,
261 target_type,
262 trait_impls,
263 ..
264 } = self;
265
266 let docs = ctx.render_type_docs();
267 let target_type = ctx.resolve_type_for_module(target_type);
268 let target_type = occurs.make_type(ctx, &target_type, false);
269 let extra_attributes = &ctx.data.extra_attributes;
270
271 let derive = get_derive(ctx, []);
272 let trait_impls = render_trait_impls(type_ident, trait_impls);
273
274 let code = quote! {
275 #docs
276 #derive
277 #( #[#extra_attributes] )*
278 pub struct #type_ident(pub #target_type);
279
280 #( #trait_impls )*
281 };
282
283 ctx.current_module().append(code);
284
285 self.render_common_impls(ctx);
286 }
287}
288
289impl ComplexData<'_> {
292 fn render_type_serde_xml_rs_v7(&self, ctx: &mut Context<'_, '_>) {
293 match self {
294 Self::Enum {
295 type_,
296 content_type,
297 } => {
298 type_.render_type_serde_xml_rs_v7(ctx);
299
300 if let Some(content_type) = content_type {
301 content_type.render_type_serde_xml_rs_v7(ctx);
302 }
303 }
304 Self::Struct {
305 type_,
306 content_type,
307 } => {
308 type_.render_type_serde_xml_rs_v7(ctx);
309
310 if let Some(content_type) = content_type {
311 content_type.render_type_serde_xml_rs_v7(ctx);
312 }
313 }
314 }
315 }
316}
317
318impl ComplexDataEnum<'_> {
319 fn render_type_serde_xml_rs_v7(&self, ctx: &mut Context<'_, '_>) {
320 let docs = ctx.render_type_docs();
321 let derive = get_derive(ctx, []);
322 let type_ident = &self.type_ident;
323 let trait_impls = render_trait_impls(type_ident, &self.trait_impls);
324 let extra_attributes = &ctx.data.extra_attributes;
325
326 let variants = self
327 .elements
328 .iter()
329 .map(|x| x.render_variant_serde_xml_rs_v7(ctx));
330
331 let code = quote! {
332 #docs
333 #derive
334 #( #[#extra_attributes] )*
335 pub enum #type_ident {
336 #( #variants )*
337 }
338
339 #( #trait_impls )*
340 };
341
342 ctx.current_module().append(code);
343 }
344}
345
346impl ComplexDataStruct<'_> {
347 fn render_type_serde_xml_rs_v7(&self, ctx: &mut Context<'_, '_>) {
348 let docs = ctx.render_type_docs();
349 let derive = get_derive(ctx, []);
350 let type_ident = &self.type_ident;
351 let trait_impls = render_trait_impls(type_ident, &self.trait_impls);
352 let extra_attributes = &ctx.data.extra_attributes;
353
354 let attributes = self
355 .attributes
356 .iter()
357 .map(|x| x.render_field_serde_xml_rs_v7(ctx, type_ident));
358 let fields = self
359 .elements()
360 .iter()
361 .map(|x| x.render_field_serde_xml_rs_v7(ctx));
362 let content = self
363 .content()
364 .as_ref()
365 .and_then(|x| x.render_field_serde_xml_rs_v7(ctx));
366
367 let struct_data = if self.is_unit_struct() {
368 quote!(;)
369 } else {
370 quote! {
371 {
372 #( #attributes )*
373 #( #fields )*
374 #content
375 }
376 }
377 };
378
379 let code = quote! {
380 #docs
381 #derive
382 #( #[#extra_attributes] )*
383 pub struct #type_ident
384 #struct_data
385
386 #( #trait_impls )*
387 };
388
389 ctx.current_module().append(code);
390 }
391}
392
393impl ComplexDataContent<'_> {
394 fn render_field_serde_xml_rs_v7(&self, ctx: &Context<'_, '_>) -> Option<TokenStream> {
395 let target_type = ctx.resolve_type_for_module(&self.target_type);
396 let target_type = self.occurs.make_type(ctx, &target_type, false)?;
397 let extra_attributes = &self.extra_attributes;
398
399 let default =
400 (self.is_empty_string_content(ctx) || self.min_occurs == 0).then(|| quote!(default,));
401
402 Some(quote! {
403 #( #[#extra_attributes] )*
404 #[serde(#default rename = "$value")]
405 pub content: #target_type,
406 })
407 }
408}
409
410impl ComplexDataAttribute<'_> {
411 fn render_field_serde_xml_rs_v7(
412 &self,
413 ctx: &Context<'_, '_>,
414 type_ident: &Ident2,
415 ) -> TokenStream {
416 let Self {
417 tag_name,
418 ident: field_ident,
419 extra_attributes,
420 ..
421 } = self;
422
423 let tag_name = tag_name.get(true);
424
425 let target_type = ctx.resolve_type_for_module(&self.target_type);
426 let target_type = if self.is_option {
427 let option = ctx.resolve_build_in("::core::option::Option");
428
429 quote!(#option<#target_type>)
430 } else {
431 target_type
432 };
433
434 let default = if self.default_value.is_some() {
435 let default_path = format!("{type_ident}::default_{field_ident}");
436
437 quote!(default = #default_path,)
438 } else if self.meta.use_ == Use::Optional {
439 quote!(default,)
440 } else {
441 quote!()
442 };
443
444 let docs = ctx.render_docs(
445 RendererFlags::RENDER_ATTRIBUTE_DOCS,
446 &self.meta.documentation[..],
447 );
448
449 quote! {
450 #docs
451 #( #[#extra_attributes] )*
452 #[serde(#default rename = #tag_name)]
453 pub #field_ident: #target_type,
454 }
455 }
456}
457
458impl ComplexDataElement<'_> {
459 fn render_field_serde_xml_rs_v7(&self, ctx: &Context<'_, '_>) -> TokenStream {
460 let Self {
461 s_name,
462 field_ident,
463 extra_attributes,
464 ..
465 } = self;
466
467 let name = if self.meta().is_text() {
468 "#text"
469 } else {
470 s_name
471 };
472
473 let target_type = ctx.resolve_type_for_module(&self.target_type);
474 let target_type = self
475 .occurs
476 .make_type(ctx, &target_type, self.need_indirection)
477 .unwrap();
478
479 let docs = ctx.render_docs(
480 RendererFlags::RENDER_ELEMENT_DOCS,
481 &self.meta().documentation[..],
482 );
483
484 let default = match self.occurs {
485 Occurs::None | Occurs::Single | Occurs::StaticList(_) => quote!(),
486 Occurs::Optional | Occurs::DynamicList => quote!(default,),
487 };
488
489 quote! {
490 #docs
491 #( #[#extra_attributes] )*
492 #[serde(#default rename = #name)]
493 pub #field_ident: #target_type,
494 }
495 }
496
497 fn render_variant_serde_xml_rs_v7(&self, ctx: &Context<'_, '_>) -> TokenStream {
498 let Self {
499 s_name,
500 variant_ident,
501 extra_attributes,
502 ..
503 } = self;
504
505 let name = if self.meta().is_text() {
506 "#text"
507 } else {
508 s_name
509 };
510
511 let target_type = ctx.resolve_type_for_module(&self.target_type);
512 let target_type = self
513 .occurs
514 .make_type(ctx, &target_type, self.need_indirection);
515
516 let docs = ctx.render_docs(
517 RendererFlags::RENDER_ELEMENT_DOCS,
518 &self.meta().documentation[..],
519 );
520
521 quote! {
522 #docs
523 #( #[#extra_attributes] )*
524 #[serde(rename = #name)]
525 #variant_ident(#target_type),
526 }
527 }
528}