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