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