1 | use crate::fragment::{Fragment, Match, Stmts}; |
2 | use crate::internals::ast::{Container, Data, Field, Style, Variant}; |
3 | use crate::internals::{attr, replace_receiver, Ctxt, Derive}; |
4 | use crate::{bound, dummy, pretend, this}; |
5 | use proc_macro2::{Span, TokenStream}; |
6 | use quote::{quote, quote_spanned}; |
7 | use syn::spanned::Spanned; |
8 | use syn::{parse_quote, Ident, Index, Member}; |
9 | |
10 | pub fn expand_derive_serialize(input: &mut syn::DeriveInput) -> syn::Result<TokenStream> { |
11 | replace_receiver(input); |
12 | |
13 | let ctxt = Ctxt::new(); |
14 | let cont = match Container::from_ast(&ctxt, input, Derive::Serialize) { |
15 | Some(cont) => cont, |
16 | None => return Err(ctxt.check().unwrap_err()), |
17 | }; |
18 | precondition(&ctxt, &cont); |
19 | ctxt.check()?; |
20 | |
21 | let ident = &cont.ident; |
22 | let params = Parameters::new(&cont); |
23 | let (impl_generics, ty_generics, where_clause) = params.generics.split_for_impl(); |
24 | let body = Stmts(serialize_body(&cont, ¶ms)); |
25 | let serde = cont.attrs.serde_path(); |
26 | |
27 | let impl_block = if let Some(remote) = cont.attrs.remote() { |
28 | let vis = &input.vis; |
29 | let used = pretend::pretend_used(&cont, params.is_packed); |
30 | quote! { |
31 | impl #impl_generics #ident #ty_generics #where_clause { |
32 | #vis fn serialize<__S>(__self: &#remote #ty_generics, __serializer: __S) -> #serde::__private::Result<__S::Ok, __S::Error> |
33 | where |
34 | __S: #serde::Serializer, |
35 | { |
36 | #used |
37 | #body |
38 | } |
39 | } |
40 | } |
41 | } else { |
42 | quote! { |
43 | #[automatically_derived] |
44 | impl #impl_generics #serde::Serialize for #ident #ty_generics #where_clause { |
45 | fn serialize<__S>(&self, __serializer: __S) -> #serde::__private::Result<__S::Ok, __S::Error> |
46 | where |
47 | __S: #serde::Serializer, |
48 | { |
49 | #body |
50 | } |
51 | } |
52 | } |
53 | }; |
54 | |
55 | Ok(dummy::wrap_in_const( |
56 | cont.attrs.custom_serde_path(), |
57 | impl_block, |
58 | )) |
59 | } |
60 | |
61 | fn precondition(cx: &Ctxt, cont: &Container) { |
62 | match cont.attrs.identifier() { |
63 | attr::Identifier::No => {} |
64 | attr::Identifier::Field => { |
65 | cx.error_spanned_by(obj:cont.original, msg:"field identifiers cannot be serialized" ); |
66 | } |
67 | attr::Identifier::Variant => { |
68 | cx.error_spanned_by(obj:cont.original, msg:"variant identifiers cannot be serialized" ); |
69 | } |
70 | } |
71 | } |
72 | |
73 | struct Parameters { |
74 | /// Variable holding the value being serialized. Either `self` for local |
75 | /// types or `__self` for remote types. |
76 | self_var: Ident, |
77 | |
78 | /// Path to the type the impl is for. Either a single `Ident` for local |
79 | /// types (does not include generic parameters) or `some::remote::Path` for |
80 | /// remote types. |
81 | this_type: syn::Path, |
82 | |
83 | /// Same as `this_type` but using `::<T>` for generic parameters for use in |
84 | /// expression position. |
85 | this_value: syn::Path, |
86 | |
87 | /// Generics including any explicit and inferred bounds for the impl. |
88 | generics: syn::Generics, |
89 | |
90 | /// Type has a `serde(remote = "...")` attribute. |
91 | is_remote: bool, |
92 | |
93 | /// Type has a repr(packed) attribute. |
94 | is_packed: bool, |
95 | } |
96 | |
97 | impl Parameters { |
98 | fn new(cont: &Container) -> Self { |
99 | let is_remote = cont.attrs.remote().is_some(); |
100 | let self_var = if is_remote { |
101 | Ident::new("__self" , Span::call_site()) |
102 | } else { |
103 | Ident::new("self" , Span::call_site()) |
104 | }; |
105 | |
106 | let this_type = this::this_type(cont); |
107 | let this_value = this::this_value(cont); |
108 | let is_packed = cont.attrs.is_packed(); |
109 | let generics = build_generics(cont); |
110 | |
111 | Parameters { |
112 | self_var, |
113 | this_type, |
114 | this_value, |
115 | generics, |
116 | is_remote, |
117 | is_packed, |
118 | } |
119 | } |
120 | |
121 | /// Type name to use in error messages and `&'static str` arguments to |
122 | /// various Serializer methods. |
123 | fn type_name(&self) -> String { |
124 | self.this_type.segments.last().unwrap().ident.to_string() |
125 | } |
126 | } |
127 | |
128 | // All the generics in the input, plus a bound `T: Serialize` for each generic |
129 | // field type that will be serialized by us. |
130 | fn build_generics(cont: &Container) -> syn::Generics { |
131 | let generics: Generics = bound::without_defaults(cont.generics); |
132 | |
133 | let generics: Generics = |
134 | bound::with_where_predicates_from_fields(cont, &generics, from_field:attr::Field::ser_bound); |
135 | |
136 | let generics: Generics = |
137 | bound::with_where_predicates_from_variants(cont, &generics, from_variant:attr::Variant::ser_bound); |
138 | |
139 | match cont.attrs.ser_bound() { |
140 | Some(predicates: &[WherePredicate]) => bound::with_where_predicates(&generics, predicates), |
141 | None => bound::with_bound( |
142 | cont, |
143 | &generics, |
144 | filter:needs_serialize_bound, |
145 | &parse_quote!(_serde::Serialize), |
146 | ), |
147 | } |
148 | } |
149 | |
150 | // Fields with a `skip_serializing` or `serialize_with` attribute, or which |
151 | // belong to a variant with a 'skip_serializing` or `serialize_with` attribute, |
152 | // are not serialized by us so we do not generate a bound. Fields with a `bound` |
153 | // attribute specify their own bound so we do not generate one. All other fields |
154 | // may need a `T: Serialize` bound where T is the type of the field. |
155 | fn needs_serialize_bound(field: &attr::Field, variant: Option<&attr::Variant>) -> bool { |
156 | !field.skip_serializing() |
157 | && field.serialize_with().is_none() |
158 | && field.ser_bound().is_none() |
159 | && variant.map_or(default:true, |variant: &Variant| { |
160 | !variant.skip_serializing() |
161 | && variant.serialize_with().is_none() |
162 | && variant.ser_bound().is_none() |
163 | }) |
164 | } |
165 | |
166 | fn serialize_body(cont: &Container, params: &Parameters) -> Fragment { |
167 | if cont.attrs.transparent() { |
168 | serialize_transparent(cont, params) |
169 | } else if let Some(type_into: &Type) = cont.attrs.type_into() { |
170 | serialize_into(params, type_into) |
171 | } else { |
172 | match &cont.data { |
173 | Data::Enum(variants: &Vec>) => serialize_enum(params, variants, &cont.attrs), |
174 | Data::Struct(Style::Struct, fields: &Vec>) => serialize_struct(params, fields, &cont.attrs), |
175 | Data::Struct(Style::Tuple, fields: &Vec>) => { |
176 | serialize_tuple_struct(params, fields, &cont.attrs) |
177 | } |
178 | Data::Struct(Style::Newtype, fields: &Vec>) => { |
179 | serialize_newtype_struct(params, &fields[0], &cont.attrs) |
180 | } |
181 | Data::Struct(Style::Unit, _) => serialize_unit_struct(&cont.attrs), |
182 | } |
183 | } |
184 | } |
185 | |
186 | fn serialize_transparent(cont: &Container, params: &Parameters) -> Fragment { |
187 | let fields: &Vec> = match &cont.data { |
188 | Data::Struct(_, fields: &Vec>) => fields, |
189 | Data::Enum(_) => unreachable!(), |
190 | }; |
191 | |
192 | let self_var: &Ident = ¶ms.self_var; |
193 | let transparent_field: &Field<'_> = fields.iter().find(|f: &&Field<'_>| f.attrs.transparent()).unwrap(); |
194 | let member: &Member = &transparent_field.member; |
195 | |
196 | let path: TokenStream = match transparent_field.attrs.serialize_with() { |
197 | Some(path: &ExprPath) => quote!(#path), |
198 | None => { |
199 | let span: Span = transparent_field.original.span(); |
200 | quote_spanned!(span=> _serde::Serialize::serialize) |
201 | } |
202 | }; |
203 | |
204 | quote_block! { |
205 | #path(&#self_var.#member, __serializer) |
206 | } |
207 | } |
208 | |
209 | fn serialize_into(params: &Parameters, type_into: &syn::Type) -> Fragment { |
210 | let self_var: &Ident = ¶ms.self_var; |
211 | quote_block! { |
212 | _serde::Serialize::serialize( |
213 | &_serde::__private::Into::<#type_into>::into(_serde::__private::Clone::clone(#self_var)), |
214 | __serializer) |
215 | } |
216 | } |
217 | |
218 | fn serialize_unit_struct(cattrs: &attr::Container) -> Fragment { |
219 | let type_name: &str = cattrs.name().serialize_name(); |
220 | |
221 | quote_expr! { |
222 | _serde::Serializer::serialize_unit_struct(__serializer, #type_name) |
223 | } |
224 | } |
225 | |
226 | fn serialize_newtype_struct( |
227 | params: &Parameters, |
228 | field: &Field, |
229 | cattrs: &attr::Container, |
230 | ) -> Fragment { |
231 | let type_name: &str = cattrs.name().serialize_name(); |
232 | |
233 | let mut field_expr: TokenStream = get_member( |
234 | params, |
235 | field, |
236 | &Member::Unnamed(Index { |
237 | index: 0, |
238 | span: Span::call_site(), |
239 | }), |
240 | ); |
241 | if let Some(path: &ExprPath) = field.attrs.serialize_with() { |
242 | field_expr = wrap_serialize_field_with(params, field_ty:field.ty, serialize_with:path, &field_expr); |
243 | } |
244 | |
245 | let span: Span = field.original.span(); |
246 | let func: TokenStream = quote_spanned!(span=> _serde::Serializer::serialize_newtype_struct); |
247 | quote_expr! { |
248 | #func(__serializer, #type_name, #field_expr) |
249 | } |
250 | } |
251 | |
252 | fn serialize_tuple_struct( |
253 | params: &Parameters, |
254 | fields: &[Field], |
255 | cattrs: &attr::Container, |
256 | ) -> Fragment { |
257 | let serialize_stmts = |
258 | serialize_tuple_struct_visitor(fields, params, false, &TupleTrait::SerializeTupleStruct); |
259 | |
260 | let type_name = cattrs.name().serialize_name(); |
261 | |
262 | let mut serialized_fields = fields |
263 | .iter() |
264 | .enumerate() |
265 | .filter(|(_, field)| !field.attrs.skip_serializing()) |
266 | .peekable(); |
267 | |
268 | let let_mut = mut_if(serialized_fields.peek().is_some()); |
269 | |
270 | let len = serialized_fields |
271 | .map(|(i, field)| match field.attrs.skip_serializing_if() { |
272 | None => quote!(1), |
273 | Some(path) => { |
274 | let index = syn::Index { |
275 | index: i as u32, |
276 | span: Span::call_site(), |
277 | }; |
278 | let field_expr = get_member(params, field, &Member::Unnamed(index)); |
279 | quote!(if #path(#field_expr) { 0 } else { 1 }) |
280 | } |
281 | }) |
282 | .fold(quote!(0), |sum, expr| quote!(#sum + #expr)); |
283 | |
284 | quote_block! { |
285 | let #let_mut __serde_state = _serde::Serializer::serialize_tuple_struct(__serializer, #type_name, #len)?; |
286 | #(#serialize_stmts)* |
287 | _serde::ser::SerializeTupleStruct::end(__serde_state) |
288 | } |
289 | } |
290 | |
291 | fn serialize_struct(params: &Parameters, fields: &[Field], cattrs: &attr::Container) -> Fragment { |
292 | assert!(fields.len() as u64 <= u64::from(u32::max_value())); |
293 | |
294 | if cattrs.has_flatten() { |
295 | serialize_struct_as_map(params, fields, cattrs) |
296 | } else { |
297 | serialize_struct_as_struct(params, fields, cattrs) |
298 | } |
299 | } |
300 | |
301 | fn serialize_struct_tag_field(cattrs: &attr::Container, struct_trait: &StructTrait) -> TokenStream { |
302 | match cattrs.tag() { |
303 | attr::TagType::Internal { tag: &String } => { |
304 | let type_name: &str = cattrs.name().serialize_name(); |
305 | let func: TokenStream = struct_trait.serialize_field(Span::call_site()); |
306 | quote! { |
307 | #func(&mut __serde_state, #tag, #type_name)?; |
308 | } |
309 | } |
310 | _ => quote! {}, |
311 | } |
312 | } |
313 | |
314 | fn serialize_struct_as_struct( |
315 | params: &Parameters, |
316 | fields: &[Field], |
317 | cattrs: &attr::Container, |
318 | ) -> Fragment { |
319 | let serialize_fields = |
320 | serialize_struct_visitor(fields, params, false, &StructTrait::SerializeStruct); |
321 | |
322 | let type_name = cattrs.name().serialize_name(); |
323 | |
324 | let tag_field = serialize_struct_tag_field(cattrs, &StructTrait::SerializeStruct); |
325 | let tag_field_exists = !tag_field.is_empty(); |
326 | |
327 | let mut serialized_fields = fields |
328 | .iter() |
329 | .filter(|&field| !field.attrs.skip_serializing()) |
330 | .peekable(); |
331 | |
332 | let let_mut = mut_if(serialized_fields.peek().is_some() || tag_field_exists); |
333 | |
334 | let len = serialized_fields |
335 | .map(|field| match field.attrs.skip_serializing_if() { |
336 | None => quote!(1), |
337 | Some(path) => { |
338 | let field_expr = get_member(params, field, &field.member); |
339 | quote!(if #path(#field_expr) { 0 } else { 1 }) |
340 | } |
341 | }) |
342 | .fold( |
343 | quote!(#tag_field_exists as usize), |
344 | |sum, expr| quote!(#sum + #expr), |
345 | ); |
346 | |
347 | quote_block! { |
348 | let #let_mut __serde_state = _serde::Serializer::serialize_struct(__serializer, #type_name, #len)?; |
349 | #tag_field |
350 | #(#serialize_fields)* |
351 | _serde::ser::SerializeStruct::end(__serde_state) |
352 | } |
353 | } |
354 | |
355 | fn serialize_struct_as_map( |
356 | params: &Parameters, |
357 | fields: &[Field], |
358 | cattrs: &attr::Container, |
359 | ) -> Fragment { |
360 | let serialize_fields = |
361 | serialize_struct_visitor(fields, params, false, &StructTrait::SerializeMap); |
362 | |
363 | let tag_field = serialize_struct_tag_field(cattrs, &StructTrait::SerializeMap); |
364 | let tag_field_exists = !tag_field.is_empty(); |
365 | |
366 | let mut serialized_fields = fields |
367 | .iter() |
368 | .filter(|&field| !field.attrs.skip_serializing()) |
369 | .peekable(); |
370 | |
371 | let let_mut = mut_if(serialized_fields.peek().is_some() || tag_field_exists); |
372 | |
373 | let len = if cattrs.has_flatten() { |
374 | quote!(_serde::__private::None) |
375 | } else { |
376 | let len = serialized_fields |
377 | .map(|field| match field.attrs.skip_serializing_if() { |
378 | None => quote!(1), |
379 | Some(path) => { |
380 | let field_expr = get_member(params, field, &field.member); |
381 | quote!(if #path(#field_expr) { 0 } else { 1 }) |
382 | } |
383 | }) |
384 | .fold( |
385 | quote!(#tag_field_exists as usize), |
386 | |sum, expr| quote!(#sum + #expr), |
387 | ); |
388 | quote!(_serde::__private::Some(#len)) |
389 | }; |
390 | |
391 | quote_block! { |
392 | let #let_mut __serde_state = _serde::Serializer::serialize_map(__serializer, #len)?; |
393 | #tag_field |
394 | #(#serialize_fields)* |
395 | _serde::ser::SerializeMap::end(__serde_state) |
396 | } |
397 | } |
398 | |
399 | fn serialize_enum(params: &Parameters, variants: &[Variant], cattrs: &attr::Container) -> Fragment { |
400 | assert!(variants.len() as u64 <= u64::from(u32::max_value())); |
401 | |
402 | let self_var = ¶ms.self_var; |
403 | |
404 | let mut arms: Vec<_> = variants |
405 | .iter() |
406 | .enumerate() |
407 | .map(|(variant_index, variant)| { |
408 | serialize_variant(params, variant, variant_index as u32, cattrs) |
409 | }) |
410 | .collect(); |
411 | |
412 | if cattrs.remote().is_some() && cattrs.non_exhaustive() { |
413 | arms.push(quote! { |
414 | ref unrecognized => _serde::__private::Err(_serde::ser::Error::custom(_serde::__private::ser::CannotSerializeVariant(unrecognized))), |
415 | }); |
416 | } |
417 | |
418 | quote_expr! { |
419 | match *#self_var { |
420 | #(#arms)* |
421 | } |
422 | } |
423 | } |
424 | |
425 | fn serialize_variant( |
426 | params: &Parameters, |
427 | variant: &Variant, |
428 | variant_index: u32, |
429 | cattrs: &attr::Container, |
430 | ) -> TokenStream { |
431 | let this_value = ¶ms.this_value; |
432 | let variant_ident = &variant.ident; |
433 | |
434 | if variant.attrs.skip_serializing() { |
435 | let skipped_msg = format!( |
436 | "the enum variant {}:: {} cannot be serialized" , |
437 | params.type_name(), |
438 | variant_ident |
439 | ); |
440 | let skipped_err = quote! { |
441 | _serde::__private::Err(_serde::ser::Error::custom(#skipped_msg)) |
442 | }; |
443 | let fields_pat = match variant.style { |
444 | Style::Unit => quote!(), |
445 | Style::Newtype | Style::Tuple => quote!((..)), |
446 | Style::Struct => quote!({ .. }), |
447 | }; |
448 | quote! { |
449 | #this_value::#variant_ident #fields_pat => #skipped_err, |
450 | } |
451 | } else { |
452 | // variant wasn't skipped |
453 | let case = match variant.style { |
454 | Style::Unit => { |
455 | quote! { |
456 | #this_value::#variant_ident |
457 | } |
458 | } |
459 | Style::Newtype => { |
460 | quote! { |
461 | #this_value::#variant_ident(ref __field0) |
462 | } |
463 | } |
464 | Style::Tuple => { |
465 | let field_names = (0..variant.fields.len()) |
466 | .map(|i| Ident::new(&format!("__field {}" , i), Span::call_site())); |
467 | quote! { |
468 | #this_value::#variant_ident(#(ref #field_names),*) |
469 | } |
470 | } |
471 | Style::Struct => { |
472 | let members = variant.fields.iter().map(|f| &f.member); |
473 | quote! { |
474 | #this_value::#variant_ident { #(ref #members),* } |
475 | } |
476 | } |
477 | }; |
478 | |
479 | let body = Match(match (cattrs.tag(), variant.attrs.untagged()) { |
480 | (attr::TagType::External, false) => { |
481 | serialize_externally_tagged_variant(params, variant, variant_index, cattrs) |
482 | } |
483 | (attr::TagType::Internal { tag }, false) => { |
484 | serialize_internally_tagged_variant(params, variant, cattrs, tag) |
485 | } |
486 | (attr::TagType::Adjacent { tag, content }, false) => { |
487 | serialize_adjacently_tagged_variant( |
488 | params, |
489 | variant, |
490 | cattrs, |
491 | variant_index, |
492 | tag, |
493 | content, |
494 | ) |
495 | } |
496 | (attr::TagType::None, _) | (_, true) => { |
497 | serialize_untagged_variant(params, variant, cattrs) |
498 | } |
499 | }); |
500 | |
501 | quote! { |
502 | #case => #body |
503 | } |
504 | } |
505 | } |
506 | |
507 | fn serialize_externally_tagged_variant( |
508 | params: &Parameters, |
509 | variant: &Variant, |
510 | variant_index: u32, |
511 | cattrs: &attr::Container, |
512 | ) -> Fragment { |
513 | let type_name = cattrs.name().serialize_name(); |
514 | let variant_name = variant.attrs.name().serialize_name(); |
515 | |
516 | if let Some(path) = variant.attrs.serialize_with() { |
517 | let ser = wrap_serialize_variant_with(params, path, variant); |
518 | return quote_expr! { |
519 | _serde::Serializer::serialize_newtype_variant( |
520 | __serializer, |
521 | #type_name, |
522 | #variant_index, |
523 | #variant_name, |
524 | #ser, |
525 | ) |
526 | }; |
527 | } |
528 | |
529 | match effective_style(variant) { |
530 | Style::Unit => { |
531 | quote_expr! { |
532 | _serde::Serializer::serialize_unit_variant( |
533 | __serializer, |
534 | #type_name, |
535 | #variant_index, |
536 | #variant_name, |
537 | ) |
538 | } |
539 | } |
540 | Style::Newtype => { |
541 | let field = &variant.fields[0]; |
542 | let mut field_expr = quote!(__field0); |
543 | if let Some(path) = field.attrs.serialize_with() { |
544 | field_expr = wrap_serialize_field_with(params, field.ty, path, &field_expr); |
545 | } |
546 | |
547 | let span = field.original.span(); |
548 | let func = quote_spanned!(span=> _serde::Serializer::serialize_newtype_variant); |
549 | quote_expr! { |
550 | #func( |
551 | __serializer, |
552 | #type_name, |
553 | #variant_index, |
554 | #variant_name, |
555 | #field_expr, |
556 | ) |
557 | } |
558 | } |
559 | Style::Tuple => serialize_tuple_variant( |
560 | TupleVariant::ExternallyTagged { |
561 | type_name, |
562 | variant_index, |
563 | variant_name, |
564 | }, |
565 | params, |
566 | &variant.fields, |
567 | ), |
568 | Style::Struct => serialize_struct_variant( |
569 | StructVariant::ExternallyTagged { |
570 | variant_index, |
571 | variant_name, |
572 | }, |
573 | params, |
574 | &variant.fields, |
575 | type_name, |
576 | ), |
577 | } |
578 | } |
579 | |
580 | fn serialize_internally_tagged_variant( |
581 | params: &Parameters, |
582 | variant: &Variant, |
583 | cattrs: &attr::Container, |
584 | tag: &str, |
585 | ) -> Fragment { |
586 | let type_name = cattrs.name().serialize_name(); |
587 | let variant_name = variant.attrs.name().serialize_name(); |
588 | |
589 | let enum_ident_str = params.type_name(); |
590 | let variant_ident_str = variant.ident.to_string(); |
591 | |
592 | if let Some(path) = variant.attrs.serialize_with() { |
593 | let ser = wrap_serialize_variant_with(params, path, variant); |
594 | return quote_expr! { |
595 | _serde::__private::ser::serialize_tagged_newtype( |
596 | __serializer, |
597 | #enum_ident_str, |
598 | #variant_ident_str, |
599 | #tag, |
600 | #variant_name, |
601 | #ser, |
602 | ) |
603 | }; |
604 | } |
605 | |
606 | match effective_style(variant) { |
607 | Style::Unit => { |
608 | quote_block! { |
609 | let mut __struct = _serde::Serializer::serialize_struct( |
610 | __serializer, #type_name, 1)?; |
611 | _serde::ser::SerializeStruct::serialize_field( |
612 | &mut __struct, #tag, #variant_name)?; |
613 | _serde::ser::SerializeStruct::end(__struct) |
614 | } |
615 | } |
616 | Style::Newtype => { |
617 | let field = &variant.fields[0]; |
618 | let mut field_expr = quote!(__field0); |
619 | if let Some(path) = field.attrs.serialize_with() { |
620 | field_expr = wrap_serialize_field_with(params, field.ty, path, &field_expr); |
621 | } |
622 | |
623 | let span = field.original.span(); |
624 | let func = quote_spanned!(span=> _serde::__private::ser::serialize_tagged_newtype); |
625 | quote_expr! { |
626 | #func( |
627 | __serializer, |
628 | #enum_ident_str, |
629 | #variant_ident_str, |
630 | #tag, |
631 | #variant_name, |
632 | #field_expr, |
633 | ) |
634 | } |
635 | } |
636 | Style::Struct => serialize_struct_variant( |
637 | StructVariant::InternallyTagged { tag, variant_name }, |
638 | params, |
639 | &variant.fields, |
640 | type_name, |
641 | ), |
642 | Style::Tuple => unreachable!("checked in serde_derive_internals" ), |
643 | } |
644 | } |
645 | |
646 | fn serialize_adjacently_tagged_variant( |
647 | params: &Parameters, |
648 | variant: &Variant, |
649 | cattrs: &attr::Container, |
650 | variant_index: u32, |
651 | tag: &str, |
652 | content: &str, |
653 | ) -> Fragment { |
654 | let this_type = ¶ms.this_type; |
655 | let type_name = cattrs.name().serialize_name(); |
656 | let variant_name = variant.attrs.name().serialize_name(); |
657 | let serialize_variant = quote! { |
658 | &_serde::__private::ser::AdjacentlyTaggedEnumVariant { |
659 | enum_name: #type_name, |
660 | variant_index: #variant_index, |
661 | variant_name: #variant_name, |
662 | } |
663 | }; |
664 | |
665 | let inner = Stmts(if let Some(path) = variant.attrs.serialize_with() { |
666 | let ser = wrap_serialize_variant_with(params, path, variant); |
667 | quote_expr! { |
668 | _serde::Serialize::serialize(#ser, __serializer) |
669 | } |
670 | } else { |
671 | match effective_style(variant) { |
672 | Style::Unit => { |
673 | return quote_block! { |
674 | let mut __struct = _serde::Serializer::serialize_struct( |
675 | __serializer, #type_name, 1)?; |
676 | _serde::ser::SerializeStruct::serialize_field( |
677 | &mut __struct, #tag, #serialize_variant)?; |
678 | _serde::ser::SerializeStruct::end(__struct) |
679 | }; |
680 | } |
681 | Style::Newtype => { |
682 | let field = &variant.fields[0]; |
683 | let mut field_expr = quote!(__field0); |
684 | if let Some(path) = field.attrs.serialize_with() { |
685 | field_expr = wrap_serialize_field_with(params, field.ty, path, &field_expr); |
686 | } |
687 | |
688 | let span = field.original.span(); |
689 | let func = quote_spanned!(span=> _serde::ser::SerializeStruct::serialize_field); |
690 | return quote_block! { |
691 | let mut __struct = _serde::Serializer::serialize_struct( |
692 | __serializer, #type_name, 2)?; |
693 | _serde::ser::SerializeStruct::serialize_field( |
694 | &mut __struct, #tag, #serialize_variant)?; |
695 | #func( |
696 | &mut __struct, #content, #field_expr)?; |
697 | _serde::ser::SerializeStruct::end(__struct) |
698 | }; |
699 | } |
700 | Style::Tuple => { |
701 | serialize_tuple_variant(TupleVariant::Untagged, params, &variant.fields) |
702 | } |
703 | Style::Struct => serialize_struct_variant( |
704 | StructVariant::Untagged, |
705 | params, |
706 | &variant.fields, |
707 | variant_name, |
708 | ), |
709 | } |
710 | }); |
711 | |
712 | let fields_ty = variant.fields.iter().map(|f| &f.ty); |
713 | let fields_ident: &[_] = &match variant.style { |
714 | Style::Unit => { |
715 | if variant.attrs.serialize_with().is_some() { |
716 | vec![] |
717 | } else { |
718 | unreachable!() |
719 | } |
720 | } |
721 | Style::Newtype => vec![Member::Named(Ident::new("__field0" , Span::call_site()))], |
722 | Style::Tuple => (0..variant.fields.len()) |
723 | .map(|i| Member::Named(Ident::new(&format!("__field {}" , i), Span::call_site()))) |
724 | .collect(), |
725 | Style::Struct => variant.fields.iter().map(|f| f.member.clone()).collect(), |
726 | }; |
727 | |
728 | let (_, ty_generics, where_clause) = params.generics.split_for_impl(); |
729 | |
730 | let wrapper_generics = if fields_ident.is_empty() { |
731 | params.generics.clone() |
732 | } else { |
733 | bound::with_lifetime_bound(¶ms.generics, "'__a" ) |
734 | }; |
735 | let (wrapper_impl_generics, wrapper_ty_generics, _) = wrapper_generics.split_for_impl(); |
736 | |
737 | quote_block! { |
738 | #[doc(hidden)] |
739 | struct __AdjacentlyTagged #wrapper_generics #where_clause { |
740 | data: (#(&'__a #fields_ty,)*), |
741 | phantom: _serde::__private::PhantomData<#this_type #ty_generics>, |
742 | } |
743 | |
744 | impl #wrapper_impl_generics _serde::Serialize for __AdjacentlyTagged #wrapper_ty_generics #where_clause { |
745 | fn serialize<__S>(&self, __serializer: __S) -> _serde::__private::Result<__S::Ok, __S::Error> |
746 | where |
747 | __S: _serde::Serializer, |
748 | { |
749 | // Elements that have skip_serializing will be unused. |
750 | #[allow(unused_variables)] |
751 | let (#(#fields_ident,)*) = self.data; |
752 | #inner |
753 | } |
754 | } |
755 | |
756 | let mut __struct = _serde::Serializer::serialize_struct( |
757 | __serializer, #type_name, 2)?; |
758 | _serde::ser::SerializeStruct::serialize_field( |
759 | &mut __struct, #tag, #serialize_variant)?; |
760 | _serde::ser::SerializeStruct::serialize_field( |
761 | &mut __struct, #content, &__AdjacentlyTagged { |
762 | data: (#(#fields_ident,)*), |
763 | phantom: _serde::__private::PhantomData::<#this_type #ty_generics>, |
764 | })?; |
765 | _serde::ser::SerializeStruct::end(__struct) |
766 | } |
767 | } |
768 | |
769 | fn serialize_untagged_variant( |
770 | params: &Parameters, |
771 | variant: &Variant, |
772 | cattrs: &attr::Container, |
773 | ) -> Fragment { |
774 | if let Some(path) = variant.attrs.serialize_with() { |
775 | let ser = wrap_serialize_variant_with(params, path, variant); |
776 | return quote_expr! { |
777 | _serde::Serialize::serialize(#ser, __serializer) |
778 | }; |
779 | } |
780 | |
781 | match effective_style(variant) { |
782 | Style::Unit => { |
783 | quote_expr! { |
784 | _serde::Serializer::serialize_unit(__serializer) |
785 | } |
786 | } |
787 | Style::Newtype => { |
788 | let field = &variant.fields[0]; |
789 | let mut field_expr = quote!(__field0); |
790 | if let Some(path) = field.attrs.serialize_with() { |
791 | field_expr = wrap_serialize_field_with(params, field.ty, path, &field_expr); |
792 | } |
793 | |
794 | let span = field.original.span(); |
795 | let func = quote_spanned!(span=> _serde::Serialize::serialize); |
796 | quote_expr! { |
797 | #func(#field_expr, __serializer) |
798 | } |
799 | } |
800 | Style::Tuple => serialize_tuple_variant(TupleVariant::Untagged, params, &variant.fields), |
801 | Style::Struct => { |
802 | let type_name = cattrs.name().serialize_name(); |
803 | serialize_struct_variant(StructVariant::Untagged, params, &variant.fields, type_name) |
804 | } |
805 | } |
806 | } |
807 | |
808 | enum TupleVariant<'a> { |
809 | ExternallyTagged { |
810 | type_name: &'a str, |
811 | variant_index: u32, |
812 | variant_name: &'a str, |
813 | }, |
814 | Untagged, |
815 | } |
816 | |
817 | fn serialize_tuple_variant( |
818 | context: TupleVariant, |
819 | params: &Parameters, |
820 | fields: &[Field], |
821 | ) -> Fragment { |
822 | let tuple_trait = match context { |
823 | TupleVariant::ExternallyTagged { .. } => TupleTrait::SerializeTupleVariant, |
824 | TupleVariant::Untagged => TupleTrait::SerializeTuple, |
825 | }; |
826 | |
827 | let serialize_stmts = serialize_tuple_struct_visitor(fields, params, true, &tuple_trait); |
828 | |
829 | let mut serialized_fields = fields |
830 | .iter() |
831 | .enumerate() |
832 | .filter(|(_, field)| !field.attrs.skip_serializing()) |
833 | .peekable(); |
834 | |
835 | let let_mut = mut_if(serialized_fields.peek().is_some()); |
836 | |
837 | let len = serialized_fields |
838 | .map(|(i, field)| match field.attrs.skip_serializing_if() { |
839 | None => quote!(1), |
840 | Some(path) => { |
841 | let field_expr = Ident::new(&format!("__field {}" , i), Span::call_site()); |
842 | quote!(if #path(#field_expr) { 0 } else { 1 }) |
843 | } |
844 | }) |
845 | .fold(quote!(0), |sum, expr| quote!(#sum + #expr)); |
846 | |
847 | match context { |
848 | TupleVariant::ExternallyTagged { |
849 | type_name, |
850 | variant_index, |
851 | variant_name, |
852 | } => { |
853 | quote_block! { |
854 | let #let_mut __serde_state = _serde::Serializer::serialize_tuple_variant( |
855 | __serializer, |
856 | #type_name, |
857 | #variant_index, |
858 | #variant_name, |
859 | #len)?; |
860 | #(#serialize_stmts)* |
861 | _serde::ser::SerializeTupleVariant::end(__serde_state) |
862 | } |
863 | } |
864 | TupleVariant::Untagged => { |
865 | quote_block! { |
866 | let #let_mut __serde_state = _serde::Serializer::serialize_tuple( |
867 | __serializer, |
868 | #len)?; |
869 | #(#serialize_stmts)* |
870 | _serde::ser::SerializeTuple::end(__serde_state) |
871 | } |
872 | } |
873 | } |
874 | } |
875 | |
876 | enum StructVariant<'a> { |
877 | ExternallyTagged { |
878 | variant_index: u32, |
879 | variant_name: &'a str, |
880 | }, |
881 | InternallyTagged { |
882 | tag: &'a str, |
883 | variant_name: &'a str, |
884 | }, |
885 | Untagged, |
886 | } |
887 | |
888 | fn serialize_struct_variant( |
889 | context: StructVariant, |
890 | params: &Parameters, |
891 | fields: &[Field], |
892 | name: &str, |
893 | ) -> Fragment { |
894 | if fields.iter().any(|field| field.attrs.flatten()) { |
895 | return serialize_struct_variant_with_flatten(context, params, fields, name); |
896 | } |
897 | |
898 | let struct_trait = match context { |
899 | StructVariant::ExternallyTagged { .. } => StructTrait::SerializeStructVariant, |
900 | StructVariant::InternallyTagged { .. } | StructVariant::Untagged => { |
901 | StructTrait::SerializeStruct |
902 | } |
903 | }; |
904 | |
905 | let serialize_fields = serialize_struct_visitor(fields, params, true, &struct_trait); |
906 | |
907 | let mut serialized_fields = fields |
908 | .iter() |
909 | .filter(|&field| !field.attrs.skip_serializing()) |
910 | .peekable(); |
911 | |
912 | let let_mut = mut_if(serialized_fields.peek().is_some()); |
913 | |
914 | let len = serialized_fields |
915 | .map(|field| { |
916 | let member = &field.member; |
917 | |
918 | match field.attrs.skip_serializing_if() { |
919 | Some(path) => quote!(if #path(#member) { 0 } else { 1 }), |
920 | None => quote!(1), |
921 | } |
922 | }) |
923 | .fold(quote!(0), |sum, expr| quote!(#sum + #expr)); |
924 | |
925 | match context { |
926 | StructVariant::ExternallyTagged { |
927 | variant_index, |
928 | variant_name, |
929 | } => { |
930 | quote_block! { |
931 | let #let_mut __serde_state = _serde::Serializer::serialize_struct_variant( |
932 | __serializer, |
933 | #name, |
934 | #variant_index, |
935 | #variant_name, |
936 | #len, |
937 | )?; |
938 | #(#serialize_fields)* |
939 | _serde::ser::SerializeStructVariant::end(__serde_state) |
940 | } |
941 | } |
942 | StructVariant::InternallyTagged { tag, variant_name } => { |
943 | quote_block! { |
944 | let mut __serde_state = _serde::Serializer::serialize_struct( |
945 | __serializer, |
946 | #name, |
947 | #len + 1, |
948 | )?; |
949 | _serde::ser::SerializeStruct::serialize_field( |
950 | &mut __serde_state, |
951 | #tag, |
952 | #variant_name, |
953 | )?; |
954 | #(#serialize_fields)* |
955 | _serde::ser::SerializeStruct::end(__serde_state) |
956 | } |
957 | } |
958 | StructVariant::Untagged => { |
959 | quote_block! { |
960 | let #let_mut __serde_state = _serde::Serializer::serialize_struct( |
961 | __serializer, |
962 | #name, |
963 | #len, |
964 | )?; |
965 | #(#serialize_fields)* |
966 | _serde::ser::SerializeStruct::end(__serde_state) |
967 | } |
968 | } |
969 | } |
970 | } |
971 | |
972 | fn serialize_struct_variant_with_flatten( |
973 | context: StructVariant, |
974 | params: &Parameters, |
975 | fields: &[Field], |
976 | name: &str, |
977 | ) -> Fragment { |
978 | let struct_trait = StructTrait::SerializeMap; |
979 | let serialize_fields = serialize_struct_visitor(fields, params, true, &struct_trait); |
980 | |
981 | let mut serialized_fields = fields |
982 | .iter() |
983 | .filter(|&field| !field.attrs.skip_serializing()) |
984 | .peekable(); |
985 | |
986 | let let_mut = mut_if(serialized_fields.peek().is_some()); |
987 | |
988 | match context { |
989 | StructVariant::ExternallyTagged { |
990 | variant_index, |
991 | variant_name, |
992 | } => { |
993 | let this_type = ¶ms.this_type; |
994 | let fields_ty = fields.iter().map(|f| &f.ty); |
995 | let members = &fields.iter().map(|f| &f.member).collect::<Vec<_>>(); |
996 | |
997 | let (_, ty_generics, where_clause) = params.generics.split_for_impl(); |
998 | let wrapper_generics = bound::with_lifetime_bound(¶ms.generics, "'__a" ); |
999 | let (wrapper_impl_generics, wrapper_ty_generics, _) = wrapper_generics.split_for_impl(); |
1000 | |
1001 | quote_block! { |
1002 | #[doc(hidden)] |
1003 | struct __EnumFlatten #wrapper_generics #where_clause { |
1004 | data: (#(&'__a #fields_ty,)*), |
1005 | phantom: _serde::__private::PhantomData<#this_type #ty_generics>, |
1006 | } |
1007 | |
1008 | impl #wrapper_impl_generics _serde::Serialize for __EnumFlatten #wrapper_ty_generics #where_clause { |
1009 | fn serialize<__S>(&self, __serializer: __S) -> _serde::__private::Result<__S::Ok, __S::Error> |
1010 | where |
1011 | __S: _serde::Serializer, |
1012 | { |
1013 | let (#(#members,)*) = self.data; |
1014 | let #let_mut __serde_state = _serde::Serializer::serialize_map( |
1015 | __serializer, |
1016 | _serde::__private::None)?; |
1017 | #(#serialize_fields)* |
1018 | _serde::ser::SerializeMap::end(__serde_state) |
1019 | } |
1020 | } |
1021 | |
1022 | _serde::Serializer::serialize_newtype_variant( |
1023 | __serializer, |
1024 | #name, |
1025 | #variant_index, |
1026 | #variant_name, |
1027 | &__EnumFlatten { |
1028 | data: (#(#members,)*), |
1029 | phantom: _serde::__private::PhantomData::<#this_type #ty_generics>, |
1030 | }) |
1031 | } |
1032 | } |
1033 | StructVariant::InternallyTagged { tag, variant_name } => { |
1034 | quote_block! { |
1035 | let #let_mut __serde_state = _serde::Serializer::serialize_map( |
1036 | __serializer, |
1037 | _serde::__private::None)?; |
1038 | _serde::ser::SerializeMap::serialize_entry( |
1039 | &mut __serde_state, |
1040 | #tag, |
1041 | #variant_name, |
1042 | )?; |
1043 | #(#serialize_fields)* |
1044 | _serde::ser::SerializeMap::end(__serde_state) |
1045 | } |
1046 | } |
1047 | StructVariant::Untagged => { |
1048 | quote_block! { |
1049 | let #let_mut __serde_state = _serde::Serializer::serialize_map( |
1050 | __serializer, |
1051 | _serde::__private::None)?; |
1052 | #(#serialize_fields)* |
1053 | _serde::ser::SerializeMap::end(__serde_state) |
1054 | } |
1055 | } |
1056 | } |
1057 | } |
1058 | |
1059 | fn serialize_tuple_struct_visitor( |
1060 | fields: &[Field], |
1061 | params: &Parameters, |
1062 | is_enum: bool, |
1063 | tuple_trait: &TupleTrait, |
1064 | ) -> Vec<TokenStream> { |
1065 | fields |
1066 | .iter() |
1067 | .enumerate() |
1068 | .filter(|(_, field)| !field.attrs.skip_serializing()) |
1069 | .map(|(i, field)| { |
1070 | let mut field_expr = if is_enum { |
1071 | let id = Ident::new(&format!("__field {}" , i), Span::call_site()); |
1072 | quote!(#id) |
1073 | } else { |
1074 | get_member( |
1075 | params, |
1076 | field, |
1077 | &Member::Unnamed(Index { |
1078 | index: i as u32, |
1079 | span: Span::call_site(), |
1080 | }), |
1081 | ) |
1082 | }; |
1083 | |
1084 | let skip = field |
1085 | .attrs |
1086 | .skip_serializing_if() |
1087 | .map(|path| quote!(#path(#field_expr))); |
1088 | |
1089 | if let Some(path) = field.attrs.serialize_with() { |
1090 | field_expr = wrap_serialize_field_with(params, field.ty, path, &field_expr); |
1091 | } |
1092 | |
1093 | let span = field.original.span(); |
1094 | let func = tuple_trait.serialize_element(span); |
1095 | let ser = quote! { |
1096 | #func(&mut __serde_state, #field_expr)?; |
1097 | }; |
1098 | |
1099 | match skip { |
1100 | None => ser, |
1101 | Some(skip) => quote!(if !#skip { #ser }), |
1102 | } |
1103 | }) |
1104 | .collect() |
1105 | } |
1106 | |
1107 | fn serialize_struct_visitor( |
1108 | fields: &[Field], |
1109 | params: &Parameters, |
1110 | is_enum: bool, |
1111 | struct_trait: &StructTrait, |
1112 | ) -> Vec<TokenStream> { |
1113 | fields |
1114 | .iter() |
1115 | .filter(|&field| !field.attrs.skip_serializing()) |
1116 | .map(|field| { |
1117 | let member = &field.member; |
1118 | |
1119 | let mut field_expr = if is_enum { |
1120 | quote!(#member) |
1121 | } else { |
1122 | get_member(params, field, member) |
1123 | }; |
1124 | |
1125 | let key_expr = field.attrs.name().serialize_name(); |
1126 | |
1127 | let skip = field |
1128 | .attrs |
1129 | .skip_serializing_if() |
1130 | .map(|path| quote!(#path(#field_expr))); |
1131 | |
1132 | if let Some(path) = field.attrs.serialize_with() { |
1133 | field_expr = wrap_serialize_field_with(params, field.ty, path, &field_expr); |
1134 | } |
1135 | |
1136 | let span = field.original.span(); |
1137 | let ser = if field.attrs.flatten() { |
1138 | let func = quote_spanned!(span=> _serde::Serialize::serialize); |
1139 | quote! { |
1140 | #func(&#field_expr, _serde::__private::ser::FlatMapSerializer(&mut __serde_state))?; |
1141 | } |
1142 | } else { |
1143 | let func = struct_trait.serialize_field(span); |
1144 | quote! { |
1145 | #func(&mut __serde_state, #key_expr, #field_expr)?; |
1146 | } |
1147 | }; |
1148 | |
1149 | match skip { |
1150 | None => ser, |
1151 | Some(skip) => { |
1152 | if let Some(skip_func) = struct_trait.skip_field(span) { |
1153 | quote! { |
1154 | if !#skip { |
1155 | #ser |
1156 | } else { |
1157 | #skip_func(&mut __serde_state, #key_expr)?; |
1158 | } |
1159 | } |
1160 | } else { |
1161 | quote! { |
1162 | if !#skip { |
1163 | #ser |
1164 | } |
1165 | } |
1166 | } |
1167 | } |
1168 | } |
1169 | }) |
1170 | .collect() |
1171 | } |
1172 | |
1173 | fn wrap_serialize_field_with( |
1174 | params: &Parameters, |
1175 | field_ty: &syn::Type, |
1176 | serialize_with: &syn::ExprPath, |
1177 | field_expr: &TokenStream, |
1178 | ) -> TokenStream { |
1179 | wrap_serialize_with(params, serialize_with, &[field_ty], &[quote!(#field_expr)]) |
1180 | } |
1181 | |
1182 | fn wrap_serialize_variant_with( |
1183 | params: &Parameters, |
1184 | serialize_with: &syn::ExprPath, |
1185 | variant: &Variant, |
1186 | ) -> TokenStream { |
1187 | let field_tys: Vec<_> = variant.fields.iter().map(|field: &Field<'_>| field.ty).collect(); |
1188 | let field_exprs: Vec<_> = variantimpl Iterator |
1189 | .fields |
1190 | .iter() |
1191 | .map(|field: &Field<'_>| { |
1192 | let id: Ident = match &field.member { |
1193 | Member::Named(ident: &Ident) => ident.clone(), |
1194 | Member::Unnamed(member: &Index) => { |
1195 | Ident::new(&format!("__field {}" , member.index), Span::call_site()) |
1196 | } |
1197 | }; |
1198 | quote!(#id) |
1199 | }) |
1200 | .collect(); |
1201 | wrap_serialize_with( |
1202 | params, |
1203 | serialize_with, |
1204 | field_tys:field_tys.as_slice(), |
1205 | field_exprs:field_exprs.as_slice(), |
1206 | ) |
1207 | } |
1208 | |
1209 | fn wrap_serialize_with( |
1210 | params: &Parameters, |
1211 | serialize_with: &syn::ExprPath, |
1212 | field_tys: &[&syn::Type], |
1213 | field_exprs: &[TokenStream], |
1214 | ) -> TokenStream { |
1215 | let this_type = ¶ms.this_type; |
1216 | let (_, ty_generics, where_clause) = params.generics.split_for_impl(); |
1217 | |
1218 | let wrapper_generics = if field_exprs.is_empty() { |
1219 | params.generics.clone() |
1220 | } else { |
1221 | bound::with_lifetime_bound(¶ms.generics, "'__a" ) |
1222 | }; |
1223 | let (wrapper_impl_generics, wrapper_ty_generics, _) = wrapper_generics.split_for_impl(); |
1224 | |
1225 | let field_access = (0..field_exprs.len()).map(|n| { |
1226 | Member::Unnamed(Index { |
1227 | index: n as u32, |
1228 | span: Span::call_site(), |
1229 | }) |
1230 | }); |
1231 | |
1232 | quote!({ |
1233 | #[doc(hidden)] |
1234 | struct __SerializeWith #wrapper_impl_generics #where_clause { |
1235 | values: (#(&'__a #field_tys, )*), |
1236 | phantom: _serde::__private::PhantomData<#this_type #ty_generics>, |
1237 | } |
1238 | |
1239 | impl #wrapper_impl_generics _serde::Serialize for __SerializeWith #wrapper_ty_generics #where_clause { |
1240 | fn serialize<__S>(&self, __s: __S) -> _serde::__private::Result<__S::Ok, __S::Error> |
1241 | where |
1242 | __S: _serde::Serializer, |
1243 | { |
1244 | #serialize_with(#(self.values.#field_access, )* __s) |
1245 | } |
1246 | } |
1247 | |
1248 | &__SerializeWith { |
1249 | values: (#(#field_exprs, )*), |
1250 | phantom: _serde::__private::PhantomData::<#this_type #ty_generics>, |
1251 | } |
1252 | }) |
1253 | } |
1254 | |
1255 | // Serialization of an empty struct results in code like: |
1256 | // |
1257 | // let mut __serde_state = serializer.serialize_struct("S", 0)?; |
1258 | // _serde::ser::SerializeStruct::end(__serde_state) |
1259 | // |
1260 | // where we want to omit the `mut` to avoid a warning. |
1261 | fn mut_if(is_mut: bool) -> Option<TokenStream> { |
1262 | if is_mut { |
1263 | Some(quote!(mut)) |
1264 | } else { |
1265 | None |
1266 | } |
1267 | } |
1268 | |
1269 | fn get_member(params: &Parameters, field: &Field, member: &Member) -> TokenStream { |
1270 | let self_var = ¶ms.self_var; |
1271 | match (params.is_remote, field.attrs.getter()) { |
1272 | (false, None) => { |
1273 | if params.is_packed { |
1274 | quote!(&{#self_var.#member}) |
1275 | } else { |
1276 | quote!(&#self_var.#member) |
1277 | } |
1278 | } |
1279 | (true, None) => { |
1280 | let inner = if params.is_packed { |
1281 | quote!(&{#self_var.#member}) |
1282 | } else { |
1283 | quote!(&#self_var.#member) |
1284 | }; |
1285 | let ty = field.ty; |
1286 | quote!(_serde::__private::ser::constrain::<#ty>(#inner)) |
1287 | } |
1288 | (true, Some(getter)) => { |
1289 | let ty = field.ty; |
1290 | quote!(_serde::__private::ser::constrain::<#ty>(&#getter(#self_var))) |
1291 | } |
1292 | (false, Some(_)) => { |
1293 | unreachable!("getter is only allowed for remote impls" ); |
1294 | } |
1295 | } |
1296 | } |
1297 | |
1298 | fn effective_style(variant: &Variant) -> Style { |
1299 | match variant.style { |
1300 | Style::Newtype if variant.fields[0].attrs.skip_serializing() => Style::Unit, |
1301 | other: Style => other, |
1302 | } |
1303 | } |
1304 | |
1305 | enum StructTrait { |
1306 | SerializeMap, |
1307 | SerializeStruct, |
1308 | SerializeStructVariant, |
1309 | } |
1310 | |
1311 | impl StructTrait { |
1312 | fn serialize_field(&self, span: Span) -> TokenStream { |
1313 | match *self { |
1314 | StructTrait::SerializeMap => { |
1315 | quote_spanned!(span=> _serde::ser::SerializeMap::serialize_entry) |
1316 | } |
1317 | StructTrait::SerializeStruct => { |
1318 | quote_spanned!(span=> _serde::ser::SerializeStruct::serialize_field) |
1319 | } |
1320 | StructTrait::SerializeStructVariant => { |
1321 | quote_spanned!(span=> _serde::ser::SerializeStructVariant::serialize_field) |
1322 | } |
1323 | } |
1324 | } |
1325 | |
1326 | fn skip_field(&self, span: Span) -> Option<TokenStream> { |
1327 | match *self { |
1328 | StructTrait::SerializeMap => None, |
1329 | StructTrait::SerializeStruct => { |
1330 | Some(quote_spanned!(span=> _serde::ser::SerializeStruct::skip_field)) |
1331 | } |
1332 | StructTrait::SerializeStructVariant => { |
1333 | Some(quote_spanned!(span=> _serde::ser::SerializeStructVariant::skip_field)) |
1334 | } |
1335 | } |
1336 | } |
1337 | } |
1338 | |
1339 | enum TupleTrait { |
1340 | SerializeTuple, |
1341 | SerializeTupleStruct, |
1342 | SerializeTupleVariant, |
1343 | } |
1344 | |
1345 | impl TupleTrait { |
1346 | fn serialize_element(&self, span: Span) -> TokenStream { |
1347 | match *self { |
1348 | TupleTrait::SerializeTuple => { |
1349 | quote_spanned!(span=> _serde::ser::SerializeTuple::serialize_element) |
1350 | } |
1351 | TupleTrait::SerializeTupleStruct => { |
1352 | quote_spanned!(span=> _serde::ser::SerializeTupleStruct::serialize_field) |
1353 | } |
1354 | TupleTrait::SerializeTupleVariant => { |
1355 | quote_spanned!(span=> _serde::ser::SerializeTupleVariant::serialize_field) |
1356 | } |
1357 | } |
1358 | } |
1359 | } |
1360 | |