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