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