]> git.proxmox.com Git - cargo.git/blob - vendor/serde_derive-1.0.15/src/ser.rs
New upstream version 0.23.0
[cargo.git] / vendor / serde_derive-1.0.15 / src / ser.rs
1 // Copyright 2017 Serde Developers
2 //
3 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6 // option. This file may not be copied, modified, or distributed
7 // except according to those terms.
8
9 use syn::{self, Ident};
10 use quote::Tokens;
11
12 use bound;
13 use fragment::{Fragment, Stmts, Match};
14 use internals::ast::{Body, Container, Field, Style, Variant};
15 use internals::{attr, Ctxt};
16
17 use std::u32;
18
19 pub fn expand_derive_serialize(input: &syn::DeriveInput) -> Result<Tokens, String> {
20 let ctxt = Ctxt::new();
21 let cont = Container::from_ast(&ctxt, input);
22 precondition(&ctxt, &cont);
23 try!(ctxt.check());
24
25 let ident = &cont.ident;
26 let params = Parameters::new(&cont);
27 let (impl_generics, ty_generics, where_clause) = params.generics.split_for_impl();
28 let dummy_const = Ident::new(format!("_IMPL_SERIALIZE_FOR_{}", ident));
29 let body = Stmts(serialize_body(&cont, &params));
30
31 let impl_block = if let Some(remote) = cont.attrs.remote() {
32 let vis = &input.vis;
33 quote! {
34 impl #impl_generics #ident #ty_generics #where_clause {
35 #vis fn serialize<__S>(__self: &#remote #ty_generics, __serializer: __S) -> _serde::export::Result<__S::Ok, __S::Error>
36 where __S: _serde::Serializer
37 {
38 #body
39 }
40 }
41 }
42 } else {
43 quote! {
44 #[automatically_derived]
45 impl #impl_generics _serde::Serialize for #ident #ty_generics #where_clause {
46 fn serialize<__S>(&self, __serializer: __S) -> _serde::export::Result<__S::Ok, __S::Error>
47 where __S: _serde::Serializer
48 {
49 #body
50 }
51 }
52 }
53 };
54
55 let generated = quote! {
56 #[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
57 const #dummy_const: () = {
58 extern crate serde as _serde;
59 #impl_block
60 };
61 };
62 Ok(generated)
63 }
64
65 fn precondition(cx: &Ctxt, cont: &Container) {
66 match cont.attrs.identifier() {
67 attr::Identifier::No => {}
68 attr::Identifier::Field => {
69 cx.error("field identifiers cannot be serialized");
70 }
71 attr::Identifier::Variant => {
72 cx.error("variant identifiers cannot be serialized");
73 }
74 }
75 }
76
77 struct Parameters {
78 /// Variable holding the value being serialized. Either `self` for local
79 /// types or `__self` for remote types.
80 self_var: Ident,
81
82 /// Path to the type the impl is for. Either a single `Ident` for local
83 /// types or `some::remote::Ident` for remote types. Does not include
84 /// generic parameters.
85 this: syn::Path,
86
87 /// Generics including any explicit and inferred bounds for the impl.
88 generics: syn::Generics,
89
90 /// Type has a `serde(remote = "...")` attribute.
91 is_remote: bool,
92 }
93
94 impl Parameters {
95 fn new(cont: &Container) -> Self {
96 let is_remote = cont.attrs.remote().is_some();
97 let self_var = if is_remote {
98 Ident::new("__self")
99 } else {
100 Ident::new("self")
101 };
102
103 let this = match cont.attrs.remote() {
104 Some(remote) => remote.clone(),
105 None => cont.ident.clone().into(),
106 };
107
108 let generics = build_generics(cont);
109
110 Parameters {
111 self_var: self_var,
112 this: this,
113 generics: generics,
114 is_remote: is_remote,
115 }
116 }
117
118 /// Type name to use in error messages and `&'static str` arguments to
119 /// various Serializer methods.
120 fn type_name(&self) -> &str {
121 self.this.segments.last().unwrap().ident.as_ref()
122 }
123 }
124
125 // All the generics in the input, plus a bound `T: Serialize` for each generic
126 // field type that will be serialized by us.
127 fn build_generics(cont: &Container) -> syn::Generics {
128 let generics = bound::without_defaults(cont.generics);
129
130 let generics =
131 bound::with_where_predicates_from_fields(cont, &generics, attr::Field::ser_bound);
132
133 match cont.attrs.ser_bound() {
134 Some(predicates) => bound::with_where_predicates(&generics, predicates),
135 None => {
136 bound::with_bound(
137 cont,
138 &generics,
139 needs_serialize_bound,
140 &path!(_serde::Serialize),
141 )
142 }
143 }
144 }
145
146 // Fields with a `skip_serializing` or `serialize_with` attribute, or which
147 // belong to a variant with a `serialize_with` attribute, are not serialized by
148 // us so we do not generate a bound. Fields with a `bound` attribute specify
149 // their own bound so we do not generate one. All other fields may need a `T:
150 // Serialize` bound where T is the type of the field.
151 fn needs_serialize_bound(field: &attr::Field, variant: Option<&attr::Variant>) -> bool {
152 !field.skip_serializing() &&
153 field.serialize_with().is_none() &&
154 field.ser_bound().is_none() &&
155 variant.map_or(true, |variant| variant.serialize_with().is_none())
156 }
157
158 fn serialize_body(cont: &Container, params: &Parameters) -> Fragment {
159 if let Some(into_type) = cont.attrs.into_type() {
160 serialize_into(params, into_type)
161 } else {
162 match cont.body {
163 Body::Enum(ref variants) => serialize_enum(params, variants, &cont.attrs),
164 Body::Struct(Style::Struct, ref fields) => {
165 if fields.iter().any(|field| field.ident.is_none()) {
166 panic!("struct has unnamed fields");
167 }
168 serialize_struct(params, fields, &cont.attrs)
169 }
170 Body::Struct(Style::Tuple, ref fields) => {
171 if fields.iter().any(|field| field.ident.is_some()) {
172 panic!("tuple struct has named fields");
173 }
174 serialize_tuple_struct(params, fields, &cont.attrs)
175 }
176 Body::Struct(Style::Newtype, ref fields) => {
177 serialize_newtype_struct(params, &fields[0], &cont.attrs)
178 }
179 Body::Struct(Style::Unit, _) => serialize_unit_struct(&cont.attrs),
180 }
181 }
182 }
183
184 fn serialize_into(params: &Parameters, into_type: &syn::Ty) -> Fragment {
185 let self_var = &params.self_var;
186 quote_block! {
187 _serde::Serialize::serialize(
188 &_serde::export::Into::<#into_type>::into(_serde::export::Clone::clone(#self_var)),
189 __serializer)
190 }
191 }
192
193 fn serialize_unit_struct(cattrs: &attr::Container) -> Fragment {
194 let type_name = cattrs.name().serialize_name();
195
196 quote_expr! {
197 _serde::Serializer::serialize_unit_struct(__serializer, #type_name)
198 }
199 }
200
201 fn serialize_newtype_struct(
202 params: &Parameters,
203 field: &Field,
204 cattrs: &attr::Container,
205 ) -> Fragment {
206 let type_name = cattrs.name().serialize_name();
207
208 let mut field_expr = get_field(params, field, 0);
209 if let Some(path) = field.attrs.serialize_with() {
210 field_expr = wrap_serialize_field_with(params, field.ty, path, field_expr);
211 }
212
213 quote_expr! {
214 _serde::Serializer::serialize_newtype_struct(__serializer, #type_name, #field_expr)
215 }
216 }
217
218 fn serialize_tuple_struct(
219 params: &Parameters,
220 fields: &[Field],
221 cattrs: &attr::Container,
222 ) -> Fragment {
223 let serialize_stmts = serialize_tuple_struct_visitor(
224 fields,
225 params,
226 false,
227 quote!(_serde::ser::SerializeTupleStruct::serialize_field),
228 );
229
230 let type_name = cattrs.name().serialize_name();
231 let len = serialize_stmts.len();
232 let let_mut = mut_if(len > 0);
233
234 quote_block! {
235 let #let_mut __serde_state = try!(_serde::Serializer::serialize_tuple_struct(__serializer, #type_name, #len));
236 #(#serialize_stmts)*
237 _serde::ser::SerializeTupleStruct::end(__serde_state)
238 }
239 }
240
241 fn serialize_struct(params: &Parameters, fields: &[Field], cattrs: &attr::Container) -> Fragment {
242 assert!(fields.len() as u64 <= u32::MAX as u64);
243
244 let serialize_fields = serialize_struct_visitor(
245 fields,
246 params,
247 false,
248 quote!(_serde::ser::SerializeStruct::serialize_field),
249 quote!(_serde::ser::SerializeStruct::skip_field),
250 );
251
252 let type_name = cattrs.name().serialize_name();
253
254 let mut serialized_fields = fields
255 .iter()
256 .filter(|&field| !field.attrs.skip_serializing())
257 .peekable();
258
259 let let_mut = mut_if(serialized_fields.peek().is_some());
260
261 let len = serialized_fields
262 .map(
263 |field| match field.attrs.skip_serializing_if() {
264 None => quote!(1),
265 Some(path) => {
266 let ident = field.ident.clone().expect("struct has unnamed fields");
267 let field_expr = get_field(params, field, ident);
268 quote!(if #path(#field_expr) { 0 } else { 1 })
269 }
270 },
271 )
272 .fold(quote!(0), |sum, expr| quote!(#sum + #expr));
273
274 quote_block! {
275 let #let_mut __serde_state = try!(_serde::Serializer::serialize_struct(__serializer, #type_name, #len));
276 #(#serialize_fields)*
277 _serde::ser::SerializeStruct::end(__serde_state)
278 }
279 }
280
281 fn serialize_enum(params: &Parameters, variants: &[Variant], cattrs: &attr::Container) -> Fragment {
282 assert!(variants.len() as u64 <= u32::MAX as u64);
283
284 let self_var = &params.self_var;
285
286 let arms: Vec<_> = variants
287 .iter()
288 .enumerate()
289 .map(
290 |(variant_index, variant)| {
291 serialize_variant(params, variant, variant_index as u32, cattrs)
292 },
293 )
294 .collect();
295
296 quote_expr! {
297 match *#self_var {
298 #(#arms)*
299 }
300 }
301 }
302
303 fn serialize_variant(
304 params: &Parameters,
305 variant: &Variant,
306 variant_index: u32,
307 cattrs: &attr::Container,
308 ) -> Tokens {
309 let this = &params.this;
310 let variant_ident = variant.ident.clone();
311
312 if variant.attrs.skip_serializing() {
313 let skipped_msg = format!(
314 "the enum variant {}::{} cannot be serialized",
315 params.type_name(),
316 variant_ident
317 );
318 let skipped_err = quote! {
319 _serde::export::Err(_serde::ser::Error::custom(#skipped_msg))
320 };
321 let fields_pat = match variant.style {
322 Style::Unit => quote!(),
323 Style::Newtype | Style::Tuple => quote!((..)),
324 Style::Struct => {
325 quote!(
326 {
327 ..
328 }
329 )
330 }
331 };
332 quote! {
333 #this::#variant_ident #fields_pat => #skipped_err,
334 }
335 } else {
336 // variant wasn't skipped
337 let case = match variant.style {
338 Style::Unit => {
339 quote! {
340 #this::#variant_ident
341 }
342 }
343 Style::Newtype => {
344 quote! {
345 #this::#variant_ident(ref __field0)
346 }
347 }
348 Style::Tuple => {
349 let field_names =
350 (0..variant.fields.len()).map(|i| Ident::new(format!("__field{}", i)));
351 quote! {
352 #this::#variant_ident(#(ref #field_names),*)
353 }
354 }
355 Style::Struct => {
356 let fields = variant
357 .fields
358 .iter()
359 .map(
360 |f| {
361 f.ident
362 .clone()
363 .expect("struct variant has unnamed fields")
364 },
365 );
366 quote! {
367 #this::#variant_ident { #(ref #fields),* }
368 }
369 }
370 };
371
372 let body = Match(
373 match *cattrs.tag() {
374 attr::EnumTag::External => {
375 serialize_externally_tagged_variant(params, variant, variant_index, cattrs)
376 }
377 attr::EnumTag::Internal { ref tag } => {
378 serialize_internally_tagged_variant(params, variant, cattrs, tag)
379 }
380 attr::EnumTag::Adjacent {
381 ref tag,
382 ref content,
383 } => serialize_adjacently_tagged_variant(params, variant, cattrs, tag, content),
384 attr::EnumTag::None => serialize_untagged_variant(params, variant, cattrs),
385 },
386 );
387
388 quote! {
389 #case => #body
390 }
391 }
392 }
393
394 fn serialize_externally_tagged_variant(
395 params: &Parameters,
396 variant: &Variant,
397 variant_index: u32,
398 cattrs: &attr::Container,
399 ) -> Fragment {
400 let type_name = cattrs.name().serialize_name();
401 let variant_name = variant.attrs.name().serialize_name();
402
403 if let Some(path) = variant.attrs.serialize_with() {
404 let ser = wrap_serialize_variant_with(params, path, &variant);
405 return quote_expr! {
406 _serde::Serializer::serialize_newtype_variant(
407 __serializer,
408 #type_name,
409 #variant_index,
410 #variant_name,
411 #ser,
412 )
413 };
414 }
415
416 match variant.style {
417 Style::Unit => {
418 quote_expr! {
419 _serde::Serializer::serialize_unit_variant(
420 __serializer,
421 #type_name,
422 #variant_index,
423 #variant_name,
424 )
425 }
426 }
427 Style::Newtype => {
428 let field = &variant.fields[0];
429 let mut field_expr = quote!(__field0);
430 if let Some(path) = field.attrs.serialize_with() {
431 field_expr = wrap_serialize_field_with(params, field.ty, path, field_expr);
432 }
433
434 quote_expr! {
435 _serde::Serializer::serialize_newtype_variant(
436 __serializer,
437 #type_name,
438 #variant_index,
439 #variant_name,
440 #field_expr,
441 )
442 }
443 }
444 Style::Tuple => {
445 serialize_tuple_variant(
446 TupleVariant::ExternallyTagged {
447 type_name: type_name,
448 variant_index: variant_index,
449 variant_name: variant_name,
450 },
451 params,
452 &variant.fields,
453 )
454 }
455 Style::Struct => {
456 serialize_struct_variant(
457 StructVariant::ExternallyTagged {
458 variant_index: variant_index,
459 variant_name: variant_name,
460 },
461 params,
462 &variant.fields,
463 &type_name,
464 )
465 }
466 }
467 }
468
469 fn serialize_internally_tagged_variant(
470 params: &Parameters,
471 variant: &Variant,
472 cattrs: &attr::Container,
473 tag: &str,
474 ) -> Fragment {
475 let type_name = cattrs.name().serialize_name();
476 let variant_name = variant.attrs.name().serialize_name();
477
478 let enum_ident_str = params.type_name();
479 let variant_ident_str = variant.ident.as_ref();
480
481 if let Some(path) = variant.attrs.serialize_with() {
482 let ser = wrap_serialize_variant_with(params, path, &variant);
483 return quote_expr! {
484 _serde::private::ser::serialize_tagged_newtype(
485 __serializer,
486 #enum_ident_str,
487 #variant_ident_str,
488 #tag,
489 #variant_name,
490 #ser,
491 )
492 };
493 }
494
495 match variant.style {
496 Style::Unit => {
497 quote_block! {
498 let mut __struct = try!(_serde::Serializer::serialize_struct(
499 __serializer, #type_name, 1));
500 try!(_serde::ser::SerializeStruct::serialize_field(
501 &mut __struct, #tag, #variant_name));
502 _serde::ser::SerializeStruct::end(__struct)
503 }
504 }
505 Style::Newtype => {
506 let field = &variant.fields[0];
507 let mut field_expr = quote!(__field0);
508 if let Some(path) = field.attrs.serialize_with() {
509 field_expr = wrap_serialize_field_with(params, field.ty, path, field_expr);
510 }
511
512 quote_expr! {
513 _serde::private::ser::serialize_tagged_newtype(
514 __serializer,
515 #enum_ident_str,
516 #variant_ident_str,
517 #tag,
518 #variant_name,
519 #field_expr,
520 )
521 }
522 }
523 Style::Struct => {
524 serialize_struct_variant(
525 StructVariant::InternallyTagged {
526 tag: tag,
527 variant_name: variant_name,
528 },
529 params,
530 &variant.fields,
531 &type_name,
532 )
533 }
534 Style::Tuple => unreachable!("checked in serde_derive_internals"),
535 }
536 }
537
538 fn serialize_adjacently_tagged_variant(
539 params: &Parameters,
540 variant: &Variant,
541 cattrs: &attr::Container,
542 tag: &str,
543 content: &str,
544 ) -> Fragment {
545 let this = &params.this;
546 let type_name = cattrs.name().serialize_name();
547 let variant_name = variant.attrs.name().serialize_name();
548
549 let inner = Stmts(
550 if let Some(path) = variant.attrs.serialize_with() {
551 let ser = wrap_serialize_variant_with(params, path, &variant);
552 quote_expr! {
553 _serde::Serialize::serialize(#ser, __serializer)
554 }
555 } else {
556 match variant.style {
557 Style::Unit => {
558 return quote_block! {
559 let mut __struct = try!(_serde::Serializer::serialize_struct(
560 __serializer, #type_name, 1));
561 try!(_serde::ser::SerializeStruct::serialize_field(
562 &mut __struct, #tag, #variant_name));
563 _serde::ser::SerializeStruct::end(__struct)
564 };
565 }
566 Style::Newtype => {
567 let field = &variant.fields[0];
568 let mut field_expr = quote!(__field0);
569 if let Some(path) = field.attrs.serialize_with() {
570 field_expr = wrap_serialize_field_with(params, field.ty, path, field_expr);
571 }
572
573 quote_expr! {
574 _serde::Serialize::serialize(#field_expr, __serializer)
575 }
576 }
577 Style::Tuple => {
578 serialize_tuple_variant(TupleVariant::Untagged, params, &variant.fields)
579 }
580 Style::Struct => {
581 serialize_struct_variant(
582 StructVariant::Untagged,
583 params,
584 &variant.fields,
585 &variant_name,
586 )
587 }
588 }
589 },
590 );
591
592 let fields_ty = variant.fields.iter().map(|f| &f.ty);
593 let ref fields_ident: Vec<_> = match variant.style {
594 Style::Unit => {
595 if variant.attrs.serialize_with().is_some() {
596 vec![]
597 } else {
598 unreachable!()
599 }
600 }
601 Style::Newtype => vec![Ident::new("__field0")],
602 Style::Tuple => {
603 (0..variant.fields.len())
604 .map(|i| Ident::new(format!("__field{}", i)))
605 .collect()
606 }
607 Style::Struct => {
608 variant
609 .fields
610 .iter()
611 .map(
612 |f| {
613 f.ident
614 .clone()
615 .expect("struct variant has unnamed fields")
616 },
617 )
618 .collect()
619 }
620 };
621
622 let (_, ty_generics, where_clause) = params.generics.split_for_impl();
623
624 let wrapper_generics = if let Style::Unit = variant.style {
625 params.generics.clone()
626 } else {
627 bound::with_lifetime_bound(&params.generics, "'__a")
628 };
629 let (wrapper_impl_generics, wrapper_ty_generics, _) = wrapper_generics.split_for_impl();
630
631 quote_block! {
632 struct __AdjacentlyTagged #wrapper_generics #where_clause {
633 data: (#(&'__a #fields_ty,)*),
634 phantom: _serde::export::PhantomData<#this #ty_generics>,
635 }
636
637 impl #wrapper_impl_generics _serde::Serialize for __AdjacentlyTagged #wrapper_ty_generics #where_clause {
638 fn serialize<__S>(&self, __serializer: __S) -> _serde::export::Result<__S::Ok, __S::Error>
639 where __S: _serde::Serializer
640 {
641 let (#(#fields_ident,)*) = self.data;
642 #inner
643 }
644 }
645
646 let mut __struct = try!(_serde::Serializer::serialize_struct(
647 __serializer, #type_name, 2));
648 try!(_serde::ser::SerializeStruct::serialize_field(
649 &mut __struct, #tag, #variant_name));
650 try!(_serde::ser::SerializeStruct::serialize_field(
651 &mut __struct, #content, &__AdjacentlyTagged {
652 data: (#(#fields_ident,)*),
653 phantom: _serde::export::PhantomData::<#this #ty_generics>,
654 }));
655 _serde::ser::SerializeStruct::end(__struct)
656 }
657 }
658
659 fn serialize_untagged_variant(
660 params: &Parameters,
661 variant: &Variant,
662 cattrs: &attr::Container,
663 ) -> Fragment {
664 if let Some(path) = variant.attrs.serialize_with() {
665 let ser = wrap_serialize_variant_with(params, path, &variant);
666 return quote_expr! {
667 _serde::Serialize::serialize(#ser, __serializer)
668 };
669 }
670
671 match variant.style {
672 Style::Unit => {
673 quote_expr! {
674 _serde::Serializer::serialize_unit(__serializer)
675 }
676 }
677 Style::Newtype => {
678 let field = &variant.fields[0];
679 let mut field_expr = quote!(__field0);
680 if let Some(path) = field.attrs.serialize_with() {
681 field_expr = wrap_serialize_field_with(params, field.ty, path, field_expr);
682 }
683
684 quote_expr! {
685 _serde::Serialize::serialize(#field_expr, __serializer)
686 }
687 }
688 Style::Tuple => serialize_tuple_variant(TupleVariant::Untagged, params, &variant.fields),
689 Style::Struct => {
690 let type_name = cattrs.name().serialize_name();
691 serialize_struct_variant(StructVariant::Untagged, params, &variant.fields, &type_name)
692 }
693 }
694 }
695
696 enum TupleVariant {
697 ExternallyTagged {
698 type_name: String,
699 variant_index: u32,
700 variant_name: String,
701 },
702 Untagged,
703 }
704
705 fn serialize_tuple_variant(
706 context: TupleVariant,
707 params: &Parameters,
708 fields: &[Field],
709 ) -> Fragment {
710 let method = match context {
711 TupleVariant::ExternallyTagged { .. } => {
712 quote!(_serde::ser::SerializeTupleVariant::serialize_field)
713 }
714 TupleVariant::Untagged => quote!(_serde::ser::SerializeTuple::serialize_element),
715 };
716
717 let serialize_stmts = serialize_tuple_struct_visitor(fields, params, true, method);
718
719 let len = serialize_stmts.len();
720 let let_mut = mut_if(len > 0);
721
722 match context {
723 TupleVariant::ExternallyTagged {
724 type_name,
725 variant_index,
726 variant_name,
727 } => {
728 quote_block! {
729 let #let_mut __serde_state = try!(_serde::Serializer::serialize_tuple_variant(
730 __serializer,
731 #type_name,
732 #variant_index,
733 #variant_name,
734 #len));
735 #(#serialize_stmts)*
736 _serde::ser::SerializeTupleVariant::end(__serde_state)
737 }
738 }
739 TupleVariant::Untagged => {
740 quote_block! {
741 let #let_mut __serde_state = try!(_serde::Serializer::serialize_tuple(
742 __serializer,
743 #len));
744 #(#serialize_stmts)*
745 _serde::ser::SerializeTuple::end(__serde_state)
746 }
747 }
748 }
749 }
750
751 enum StructVariant<'a> {
752 ExternallyTagged {
753 variant_index: u32,
754 variant_name: String,
755 },
756 InternallyTagged { tag: &'a str, variant_name: String },
757 Untagged,
758 }
759
760 fn serialize_struct_variant<'a>(
761 context: StructVariant<'a>,
762 params: &Parameters,
763 fields: &[Field],
764 name: &str,
765 ) -> Fragment {
766 let (method, skip_method) = match context {
767 StructVariant::ExternallyTagged { .. } => {
768 (
769 quote!(_serde::ser::SerializeStructVariant::serialize_field),
770 quote!(_serde::ser::SerializeStructVariant::skip_field),
771 )
772 }
773 StructVariant::InternallyTagged { .. } |
774 StructVariant::Untagged => {
775 (
776 quote!(_serde::ser::SerializeStruct::serialize_field),
777 quote!(_serde::ser::SerializeStruct::skip_field),
778 )
779 }
780 };
781
782 let serialize_fields = serialize_struct_visitor(fields, params, true, method, skip_method);
783
784 let mut serialized_fields = fields
785 .iter()
786 .filter(|&field| !field.attrs.skip_serializing())
787 .peekable();
788
789 let let_mut = mut_if(serialized_fields.peek().is_some());
790
791 let len = serialized_fields
792 .map(
793 |field| {
794 let ident = field.ident.clone().expect("struct has unnamed fields");
795
796 match field.attrs.skip_serializing_if() {
797 Some(path) => quote!(if #path(#ident) { 0 } else { 1 }),
798 None => quote!(1),
799 }
800 },
801 )
802 .fold(quote!(0), |sum, expr| quote!(#sum + #expr));
803
804 match context {
805 StructVariant::ExternallyTagged {
806 variant_index,
807 variant_name,
808 } => {
809 quote_block! {
810 let #let_mut __serde_state = try!(_serde::Serializer::serialize_struct_variant(
811 __serializer,
812 #name,
813 #variant_index,
814 #variant_name,
815 #len,
816 ));
817 #(#serialize_fields)*
818 _serde::ser::SerializeStructVariant::end(__serde_state)
819 }
820 }
821 StructVariant::InternallyTagged { tag, variant_name } => {
822 quote_block! {
823 let mut __serde_state = try!(_serde::Serializer::serialize_struct(
824 __serializer,
825 #name,
826 #len + 1,
827 ));
828 try!(_serde::ser::SerializeStruct::serialize_field(
829 &mut __serde_state,
830 #tag,
831 #variant_name,
832 ));
833 #(#serialize_fields)*
834 _serde::ser::SerializeStruct::end(__serde_state)
835 }
836 }
837 StructVariant::Untagged => {
838 quote_block! {
839 let #let_mut __serde_state = try!(_serde::Serializer::serialize_struct(
840 __serializer,
841 #name,
842 #len,
843 ));
844 #(#serialize_fields)*
845 _serde::ser::SerializeStruct::end(__serde_state)
846 }
847 }
848 }
849 }
850
851 fn serialize_tuple_struct_visitor(
852 fields: &[Field],
853 params: &Parameters,
854 is_enum: bool,
855 func: Tokens,
856 ) -> Vec<Tokens> {
857 fields
858 .iter()
859 .enumerate()
860 .map(
861 |(i, field)| {
862 let mut field_expr = if is_enum {
863 let id = Ident::new(format!("__field{}", i));
864 quote!(#id)
865 } else {
866 get_field(params, field, i)
867 };
868
869 let skip = field
870 .attrs
871 .skip_serializing_if()
872 .map(|path| quote!(#path(#field_expr)));
873
874 if let Some(path) = field.attrs.serialize_with() {
875 field_expr = wrap_serialize_field_with(params, field.ty, path, field_expr);
876 }
877
878 let ser = quote! {
879 try!(#func(&mut __serde_state, #field_expr));
880 };
881
882 match skip {
883 None => ser,
884 Some(skip) => quote!(if !#skip { #ser }),
885 }
886 },
887 )
888 .collect()
889 }
890
891 fn serialize_struct_visitor(
892 fields: &[Field],
893 params: &Parameters,
894 is_enum: bool,
895 func: Tokens,
896 skip_func: Tokens,
897 ) -> Vec<Tokens> {
898 fields
899 .iter()
900 .filter(|&field| !field.attrs.skip_serializing())
901 .map(
902 |field| {
903 let field_ident = field.ident.clone().expect("struct has unnamed field");
904 let mut field_expr = if is_enum {
905 quote!(#field_ident)
906 } else {
907 get_field(params, field, field_ident)
908 };
909
910 let key_expr = field.attrs.name().serialize_name();
911
912 let skip = field
913 .attrs
914 .skip_serializing_if()
915 .map(|path| quote!(#path(#field_expr)));
916
917 if let Some(path) = field.attrs.serialize_with() {
918 field_expr = wrap_serialize_field_with(params, field.ty, path, field_expr);
919 }
920
921 let ser = quote! {
922 try!(#func(&mut __serde_state, #key_expr, #field_expr));
923 };
924
925 match skip {
926 None => ser,
927 Some(skip) => {
928 quote! {
929 if !#skip {
930 #ser
931 } else {
932 try!(#skip_func(&mut __serde_state, #key_expr));
933 }
934 }
935 }
936 }
937 },
938 )
939 .collect()
940 }
941
942 fn wrap_serialize_field_with(
943 params: &Parameters,
944 field_ty: &syn::Ty,
945 serialize_with: &syn::Path,
946 field_expr: Tokens,
947 ) -> Tokens {
948 wrap_serialize_with(params,
949 serialize_with,
950 &[field_ty],
951 &[quote!(#field_expr)])
952 }
953
954 fn wrap_serialize_variant_with(
955 params: &Parameters,
956 serialize_with: &syn::Path,
957 variant: &Variant,
958 ) -> Tokens {
959 let field_tys: Vec<_> = variant.fields.iter().map(|field| field.ty).collect();
960 let field_exprs: Vec<_> = variant.fields.iter()
961 .enumerate()
962 .map(|(i, field)| {
963 let id = field.ident.as_ref().map_or_else(|| Ident::new(format!("__field{}", i)),
964 |id| id.clone());
965 quote!(#id)
966 })
967 .collect();
968 wrap_serialize_with(params, serialize_with, field_tys.as_slice(), field_exprs.as_slice())
969 }
970
971 fn wrap_serialize_with(
972 params: &Parameters,
973 serialize_with: &syn::Path,
974 field_tys: &[&syn::Ty],
975 field_exprs: &[Tokens],
976 ) -> Tokens {
977 let this = &params.this;
978 let (_, ty_generics, where_clause) = params.generics.split_for_impl();
979
980 let wrapper_generics = if field_exprs.len() == 0 {
981 params.generics.clone()
982 } else {
983 bound::with_lifetime_bound(&params.generics, "'__a")
984 };
985 let (wrapper_impl_generics, wrapper_ty_generics, _) = wrapper_generics.split_for_impl();
986
987 let field_access = (0..field_exprs.len()).map(|n| Ident::new(format!("{}", n)));
988
989 quote!({
990 struct __SerializeWith #wrapper_impl_generics #where_clause {
991 values: (#(&'__a #field_tys, )*),
992 phantom: _serde::export::PhantomData<#this #ty_generics>,
993 }
994
995 impl #wrapper_impl_generics _serde::Serialize for __SerializeWith #wrapper_ty_generics #where_clause {
996 fn serialize<__S>(&self, __s: __S) -> _serde::export::Result<__S::Ok, __S::Error>
997 where __S: _serde::Serializer
998 {
999 #serialize_with(#(self.values.#field_access, )* __s)
1000 }
1001 }
1002
1003 &__SerializeWith {
1004 values: (#(#field_exprs, )*),
1005 phantom: _serde::export::PhantomData::<#this #ty_generics>,
1006 }
1007 })
1008 }
1009
1010 // Serialization of an empty struct results in code like:
1011 //
1012 // let mut __serde_state = try!(serializer.serialize_struct("S", 0));
1013 // _serde::ser::SerializeStruct::end(__serde_state)
1014 //
1015 // where we want to omit the `mut` to avoid a warning.
1016 fn mut_if(is_mut: bool) -> Option<Tokens> {
1017 if is_mut { Some(quote!(mut)) } else { None }
1018 }
1019
1020 fn get_field<I>(params: &Parameters, field: &Field, ident: I) -> Tokens
1021 where
1022 I: Into<Ident>,
1023 {
1024 let self_var = &params.self_var;
1025 match (params.is_remote, field.attrs.getter()) {
1026 (false, None) => {
1027 let ident = ident.into();
1028 quote!(&#self_var.#ident)
1029 }
1030 (true, None) => {
1031 let ty = field.ty;
1032 let ident = ident.into();
1033 quote!(_serde::private::ser::constrain::<#ty>(&#self_var.#ident))
1034 }
1035 (true, Some(getter)) => {
1036 let ty = field.ty;
1037 quote!(_serde::private::ser::constrain::<#ty>(&#getter(#self_var)))
1038 }
1039 (false, Some(_)) => {
1040 unreachable!("getter is only allowed for remote impls");
1041 }
1042 }
1043 }