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