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