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