xsd_parser/pipeline/renderer/steps/serde/
quick_xml.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 SerdeQuickXmlTypesRenderStep;
22
23impl RenderStep for SerdeQuickXmlTypesRenderStep {
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_quick_xml(ctx),
32 DataTypeVariant::Dynamic(x) => x.render_type_serde_quick_xml(ctx),
33 DataTypeVariant::Reference(x) => x.render_type_serde_quick_xml(ctx),
34 DataTypeVariant::Enumeration(x) => x.render_type_serde_quick_xml(ctx),
35 DataTypeVariant::Simple(x) => x.render_type_serde_quick_xml(ctx),
36 DataTypeVariant::Complex(x) => x.render_type_serde_quick_xml(ctx),
37 }
38 }
39}
40
41impl UnionData<'_> {
44 fn render_type_serde_quick_xml(&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_quick_xml(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_quick_xml(&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_quick_xml(&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_quick_xml(&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_quick_xml(&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_quick_xml(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_quick_xml(&self, ctx: &Context<'_, '_>) -> TokenStream {
222 let Self {
223 s_name,
224 meta,
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<'_> {
255 fn render_type_serde_quick_xml(&self, ctx: &mut Context<'_, '_>) {
256 let Self {
257 occurs,
258 type_ident,
259 target_type,
260 trait_impls,
261 ..
262 } = self;
263
264 let docs = ctx.render_type_docs();
265 let target_type = ctx.resolve_type_for_module(target_type);
266 let target_type = occurs.make_type(ctx, &target_type, false);
267 let extra_attributes = &ctx.data.extra_attributes;
268
269 let derive = get_derive(ctx, []);
270 let trait_impls = render_trait_impls(type_ident, trait_impls);
271
272 let code = quote! {
273 #docs
274 #derive
275 #( #[#extra_attributes] )*
276 pub struct #type_ident(pub #target_type);
277
278 #( #trait_impls )*
279 };
280
281 ctx.current_module().append(code);
282
283 self.render_common_impls(ctx);
284 }
285}
286
287impl ComplexData<'_> {
290 fn render_type_serde_quick_xml(&self, ctx: &mut Context<'_, '_>) {
291 match self {
292 Self::Enum {
293 type_,
294 content_type,
295 } => {
296 type_.render_type_serde_quick_xml(ctx);
297
298 if let Some(content_type) = content_type {
299 content_type.render_type_serde_quick_xml(ctx);
300 }
301 }
302 Self::Struct {
303 type_,
304 content_type,
305 } => {
306 type_.render_type_serde_quick_xml(ctx);
307
308 if let Some(content_type) = content_type {
309 content_type.render_type_serde_quick_xml(ctx);
310 }
311 }
312 }
313 }
314}
315
316impl ComplexDataEnum<'_> {
317 fn render_type_serde_quick_xml(&self, ctx: &mut Context<'_, '_>) {
318 let docs = ctx.render_type_docs();
319 let derive = get_derive(ctx, []);
320 let type_ident = &self.type_ident;
321 let trait_impls = render_trait_impls(type_ident, &self.trait_impls);
322 let extra_attributes = &ctx.data.extra_attributes;
323
324 let variants = self
325 .elements
326 .iter()
327 .map(|x| x.render_variant_serde_quick_xml(ctx));
328
329 let code = quote! {
330 #docs
331 #derive
332 #( #[#extra_attributes] )*
333 pub enum #type_ident {
334 #( #variants )*
335 }
336
337 #( #trait_impls )*
338 };
339
340 ctx.current_module().append(code);
341 }
342}
343
344impl ComplexDataStruct<'_> {
345 fn render_type_serde_quick_xml(&self, ctx: &mut Context<'_, '_>) {
346 let docs = ctx.render_type_docs();
347 let derive = get_derive(ctx, []);
348 let type_ident = &self.type_ident;
349 let trait_impls = render_trait_impls(type_ident, &self.trait_impls);
350 let extra_attributes = &ctx.data.extra_attributes;
351
352 let attributes = self
353 .attributes
354 .iter()
355 .map(|x| x.render_field_serde_quick_xml(ctx, type_ident));
356 let fields = self
357 .elements()
358 .iter()
359 .map(|x| x.render_field_serde_quick_xml(ctx));
360 let content = self
361 .content()
362 .as_ref()
363 .and_then(|x| x.render_field_serde_quick_xml(ctx));
364
365 let struct_data = if self.is_unit_struct() {
366 quote!(;)
367 } else {
368 quote! {
369 {
370 #( #attributes )*
371 #( #fields )*
372 #content
373 }
374 }
375 };
376
377 let code = quote! {
378 #docs
379 #derive
380 #( #[#extra_attributes] )*
381 pub struct #type_ident
382 #struct_data
383
384 #( #trait_impls )*
385 };
386
387 ctx.current_module().append(code);
388 }
389}
390
391impl ComplexDataContent<'_> {
392 fn render_field_serde_quick_xml(&self, ctx: &Context<'_, '_>) -> Option<TokenStream> {
393 let target_type = ctx.resolve_type_for_module(&self.target_type);
394 let target_type = self.occurs.make_type(ctx, &target_type, false)?;
395 let extra_attributes = &self.extra_attributes;
396
397 let default =
398 (self.is_empty_string_content(ctx) || self.min_occurs == 0).then(|| quote!(default,));
399 let name = if self.is_simple() { "$text" } else { "$value" };
400
401 Some(quote! {
402 #( #[#extra_attributes] )*
403 #[serde(#default rename = #name)]
404 pub content: #target_type,
405 })
406 }
407}
408
409impl ComplexDataAttribute<'_> {
410 fn render_field_serde_quick_xml(
411 &self,
412 ctx: &Context<'_, '_>,
413 type_ident: &Ident2,
414 ) -> TokenStream {
415 let Self {
416 ident: field_ident,
417 s_name,
418 extra_attributes,
419 ..
420 } = self;
421
422 let name = format!("@{s_name}");
423
424 let target_type = ctx.resolve_type_for_module(&self.target_type);
425 let target_type = if self.is_option {
426 let option = ctx.resolve_build_in("::core::option::Option");
427
428 quote!(#option<#target_type>)
429 } else {
430 target_type
431 };
432
433 let default = if self.default_value.is_some() {
434 let default_path = format!("{type_ident}::default_{field_ident}");
435
436 quote!(default = #default_path,)
437 } else if self.meta.use_ == Use::Optional {
438 quote!(default,)
439 } else {
440 quote!()
441 };
442
443 let docs = ctx.render_docs(
444 RendererFlags::RENDER_ATTRIBUTE_DOCS,
445 &self.meta.documentation[..],
446 );
447
448 quote! {
449 #docs
450 #( #[#extra_attributes] )*
451 #[serde(#default rename = #name)]
452 pub #field_ident: #target_type,
453 }
454 }
455}
456
457impl ComplexDataElement<'_> {
458 fn render_field_serde_quick_xml(&self, ctx: &Context<'_, '_>) -> TokenStream {
459 let Self {
460 s_name,
461 field_ident,
462 extra_attributes,
463 ..
464 } = self;
465
466 let name = if self.meta().is_text() {
467 "$text"
468 } else {
469 s_name
470 };
471
472 let target_type = ctx.resolve_type_for_module(&self.target_type);
473 let target_type = self
474 .occurs
475 .make_type(ctx, &target_type, self.need_indirection)
476 .unwrap();
477
478 let docs = ctx.render_docs(
479 RendererFlags::RENDER_ELEMENT_DOCS,
480 &self.meta().documentation[..],
481 );
482
483 let default = match self.occurs {
484 Occurs::None | Occurs::Single | Occurs::StaticList(_) => quote!(),
485 Occurs::Optional | Occurs::DynamicList => quote!(default,),
486 };
487
488 quote! {
489 #docs
490 #( #[#extra_attributes] )*
491 #[serde(#default rename = #name)]
492 pub #field_ident: #target_type,
493 }
494 }
495
496 fn render_variant_serde_quick_xml(&self, ctx: &Context<'_, '_>) -> TokenStream {
497 let Self {
498 s_name,
499 variant_ident,
500 extra_attributes,
501 ..
502 } = self;
503
504 let name = if self.meta().is_text() {
505 "$text"
506 } else {
507 s_name
508 };
509
510 let target_type = ctx.resolve_type_for_module(&self.target_type);
511 let target_type = self
512 .occurs
513 .make_type(ctx, &target_type, self.need_indirection);
514
515 let docs = ctx.render_docs(
516 RendererFlags::RENDER_ELEMENT_DOCS,
517 &self.meta().documentation[..],
518 );
519
520 quote! {
521 #docs
522 #( #[#extra_attributes] )*
523 #[serde(rename = #name)]
524 #variant_ident(#target_type),
525 }
526 }
527}