Erick Tryzelaar | 5841564 | 2013-04-10 23:31:51 | [diff] [blame] | 1 | // Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT |
| 2 | // file at the top-level directory of this distribution and at |
| 3 | // http://rust-lang.org/COPYRIGHT. |
| 4 | // |
| 5 | // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or |
| 6 | // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license |
| 7 | // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your |
| 8 | // option. This file may not be copied, modified, or distributed |
| 9 | // except according to those terms. |
| 10 | |
Jorge Aparicio | 351409a | 2015-01-04 03:54:18 | [diff] [blame] | 11 | //! The compiler code necessary to implement the `#[derive(Encodable)]` |
Corey Richardson | 4989a56 | 2014-06-09 20:12:30 | [diff] [blame] | 12 | //! (and `Decodable`, in decodable.rs) extension. The idea here is that |
Jorge Aparicio | 351409a | 2015-01-04 03:54:18 | [diff] [blame] | 13 | //! type-defining items may be tagged with `#[derive(Encodable, Decodable)]`. |
Corey Richardson | 4989a56 | 2014-06-09 20:12:30 | [diff] [blame] | 14 | //! |
| 15 | //! For example, a type like: |
| 16 | //! |
| 17 | //! ```ignore |
Jorge Aparicio | 351409a | 2015-01-04 03:54:18 | [diff] [blame] | 18 | //! #[derive(Encodable, Decodable)] |
Paul Collier | a32249d | 2015-01-17 23:33:05 | [diff] [blame] | 19 | //! struct Node { id: usize } |
Corey Richardson | 4989a56 | 2014-06-09 20:12:30 | [diff] [blame] | 20 | //! ``` |
| 21 | //! |
| 22 | //! would generate two implementations like: |
| 23 | //! |
| 24 | //! ```ignore |
Barosl Lee | 9416935 | 2014-11-14 08:14:44 | [diff] [blame] | 25 | //! impl<S: Encoder<E>, E> Encodable<S, E> for Node { |
| 26 | //! fn encode(&self, s: &mut S) -> Result<(), E> { |
| 27 | //! s.emit_struct("Node", 1, |this| { |
| 28 | //! this.emit_struct_field("id", 0, |this| { |
| 29 | //! Encodable::encode(&self.id, this) |
Paul Collier | d5c8365 | 2015-01-17 23:49:08 | [diff] [blame] | 30 | //! /* this.emit_usize(self.id) can also be used */ |
Barosl Lee | 9416935 | 2014-11-14 08:14:44 | [diff] [blame] | 31 | //! }) |
Corey Richardson | 4989a56 | 2014-06-09 20:12:30 | [diff] [blame] | 32 | //! }) |
| 33 | //! } |
| 34 | //! } |
| 35 | //! |
Barosl Lee | 9416935 | 2014-11-14 08:14:44 | [diff] [blame] | 36 | //! impl<D: Decoder<E>, E> Decodable<D, E> for Node { |
| 37 | //! fn decode(d: &mut D) -> Result<Node, E> { |
| 38 | //! d.read_struct("Node", 1, |this| { |
| 39 | //! match this.read_struct_field("id", 0, |this| Decodable::decode(this)) { |
| 40 | //! Ok(id) => Ok(Node { id: id }), |
| 41 | //! Err(e) => Err(e), |
Corey Richardson | 4989a56 | 2014-06-09 20:12:30 | [diff] [blame] | 42 | //! } |
| 43 | //! }) |
| 44 | //! } |
| 45 | //! } |
| 46 | //! ``` |
| 47 | //! |
Joseph Crail | ad06dfe | 2014-08-01 23:40:21 | [diff] [blame] | 48 | //! Other interesting scenarios are when the item has type parameters or |
Corey Richardson | 4989a56 | 2014-06-09 20:12:30 | [diff] [blame] | 49 | //! references other non-built-in types. A type definition like: |
| 50 | //! |
| 51 | //! ```ignore |
Jorge Aparicio | 351409a | 2015-01-04 03:54:18 | [diff] [blame] | 52 | //! #[derive(Encodable, Decodable)] |
Barosl Lee | 9416935 | 2014-11-14 08:14:44 | [diff] [blame] | 53 | //! struct Spanned<T> { node: T, span: Span } |
Corey Richardson | 4989a56 | 2014-06-09 20:12:30 | [diff] [blame] | 54 | //! ``` |
| 55 | //! |
| 56 | //! would yield functions like: |
| 57 | //! |
| 58 | //! ```ignore |
Barosl Lee | 9416935 | 2014-11-14 08:14:44 | [diff] [blame] | 59 | //! impl< |
| 60 | //! S: Encoder<E>, |
| 61 | //! E, |
| 62 | //! T: Encodable<S, E> |
| 63 | //! > Encodable<S, E> for Spanned<T> { |
| 64 | //! fn encode(&self, s: &mut S) -> Result<(), E> { |
| 65 | //! s.emit_struct("Spanned", 2, |this| { |
| 66 | //! this.emit_struct_field("node", 0, |this| self.node.encode(this)) |
Oliver Schneider | b4a1e59 | 2015-03-20 07:19:13 | [diff] [blame] | 67 | //! .unwrap(); |
Barosl Lee | 9416935 | 2014-11-14 08:14:44 | [diff] [blame] | 68 | //! this.emit_struct_field("span", 1, |this| self.span.encode(this)) |
| 69 | //! }) |
Corey Richardson | 4989a56 | 2014-06-09 20:12:30 | [diff] [blame] | 70 | //! } |
Barosl Lee | 9416935 | 2014-11-14 08:14:44 | [diff] [blame] | 71 | //! } |
Corey Richardson | 4989a56 | 2014-06-09 20:12:30 | [diff] [blame] | 72 | //! |
Barosl Lee | 9416935 | 2014-11-14 08:14:44 | [diff] [blame] | 73 | //! impl< |
| 74 | //! D: Decoder<E>, |
| 75 | //! E, |
| 76 | //! T: Decodable<D, E> |
| 77 | //! > Decodable<D, E> for Spanned<T> { |
| 78 | //! fn decode(d: &mut D) -> Result<Spanned<T>, E> { |
| 79 | //! d.read_struct("Spanned", 2, |this| { |
| 80 | //! Ok(Spanned { |
| 81 | //! node: this.read_struct_field("node", 0, |this| Decodable::decode(this)) |
Oliver Schneider | b4a1e59 | 2015-03-20 07:19:13 | [diff] [blame] | 82 | //! .unwrap(), |
Barosl Lee | 9416935 | 2014-11-14 08:14:44 | [diff] [blame] | 83 | //! span: this.read_struct_field("span", 1, |this| Decodable::decode(this)) |
Oliver Schneider | b4a1e59 | 2015-03-20 07:19:13 | [diff] [blame] | 84 | //! .unwrap(), |
Corey Richardson | 4989a56 | 2014-06-09 20:12:30 | [diff] [blame] | 85 | //! }) |
Barosl Lee | 9416935 | 2014-11-14 08:14:44 | [diff] [blame] | 86 | //! }) |
Corey Richardson | 4989a56 | 2014-06-09 20:12:30 | [diff] [blame] | 87 | //! } |
Barosl Lee | 9416935 | 2014-11-14 08:14:44 | [diff] [blame] | 88 | //! } |
Corey Richardson | 4989a56 | 2014-06-09 20:12:30 | [diff] [blame] | 89 | //! ``` |
Huon Wilson | 5dc5efe | 2013-05-15 22:55:57 | [diff] [blame] | 90 | |
Alex Burka | 8355389 | 2016-03-08 18:24:28 | [diff] [blame] | 91 | use deriving; |
Seo Sanghyeon | f9ba107 | 2015-12-10 14:23:14 | [diff] [blame] | 92 | use deriving::generic::*; |
| 93 | use deriving::generic::ty::*; |
| 94 | |
Srinivas Reddy Thatiparthy | 9652fcb | 2016-07-19 17:32:06 | [diff] [blame] | 95 | use syntax::ast::{Expr, ExprKind, MetaItem, Mutability}; |
| 96 | use syntax::ext::base::{Annotatable, ExtCtxt}; |
Seo Sanghyeon | f9ba107 | 2015-12-10 14:23:14 | [diff] [blame] | 97 | use syntax::ext::build::AstBuilder; |
Seo Sanghyeon | f9ba107 | 2015-12-10 14:23:14 | [diff] [blame] | 98 | use syntax::ptr::P; |
Jeffrey Seyfried | e85a0d7 | 2016-11-16 10:52:37 | [diff] [blame^] | 99 | use syntax::symbol::Symbol; |
Jonathan Turner | 6ae35021 | 2016-06-21 22:08:13 | [diff] [blame] | 100 | use syntax_pos::Span; |
Alex Crichton | 53ad426 | 2014-05-16 07:16:13 | [diff] [blame] | 101 | |
Erick Tryzelaar | 9edc7de | 2015-03-27 01:07:49 | [diff] [blame] | 102 | pub fn expand_deriving_rustc_encodable(cx: &mut ExtCtxt, |
| 103 | span: Span, |
| 104 | mitem: &MetaItem, |
Manish Goregaokar | 6bc5a92 | 2015-05-22 15:40:14 | [diff] [blame] | 105 | item: &Annotatable, |
Srinivas Reddy Thatiparthy | 9652fcb | 2016-07-19 17:32:06 | [diff] [blame] | 106 | push: &mut FnMut(Annotatable)) { |
Alex Crichton | a76a802 | 2014-12-19 06:52:48 | [diff] [blame] | 107 | expand_deriving_encodable_imp(cx, span, mitem, item, push, "rustc_serialize") |
| 108 | } |
| 109 | |
Erick Tryzelaar | 9edc7de | 2015-03-27 01:07:49 | [diff] [blame] | 110 | pub fn expand_deriving_encodable(cx: &mut ExtCtxt, |
| 111 | span: Span, |
| 112 | mitem: &MetaItem, |
Manish Goregaokar | 6bc5a92 | 2015-05-22 15:40:14 | [diff] [blame] | 113 | item: &Annotatable, |
Srinivas Reddy Thatiparthy | 9652fcb | 2016-07-19 17:32:06 | [diff] [blame] | 114 | push: &mut FnMut(Annotatable)) { |
Alex Crichton | a76a802 | 2014-12-19 06:52:48 | [diff] [blame] | 115 | expand_deriving_encodable_imp(cx, span, mitem, item, push, "serialize") |
| 116 | } |
| 117 | |
Erick Tryzelaar | 9edc7de | 2015-03-27 01:07:49 | [diff] [blame] | 118 | fn expand_deriving_encodable_imp(cx: &mut ExtCtxt, |
| 119 | span: Span, |
| 120 | mitem: &MetaItem, |
Manish Goregaokar | 6bc5a92 | 2015-05-22 15:40:14 | [diff] [blame] | 121 | item: &Annotatable, |
Nick Cameron | c0a42ae | 2015-04-28 05:34:39 | [diff] [blame] | 122 | push: &mut FnMut(Annotatable), |
Srinivas Reddy Thatiparthy | 9652fcb | 2016-07-19 17:32:06 | [diff] [blame] | 123 | krate: &'static str) { |
Alex Crichton | 5cccf3c | 2015-07-30 00:01:14 | [diff] [blame] | 124 | if cx.crate_root != Some("std") { |
Keegan McAllister | 67350bc | 2014-09-07 21:57:26 | [diff] [blame] | 125 | // FIXME(#21880): lift this requirement. |
Srinivas Reddy Thatiparthy | 9652fcb | 2016-07-19 17:32:06 | [diff] [blame] | 126 | cx.span_err(span, |
| 127 | "this trait cannot be derived with #![no_std] \ |
Alex Crichton | 5cccf3c | 2015-07-30 00:01:14 | [diff] [blame] | 128 | or #![no_core]"); |
Keegan McAllister | 67350bc | 2014-09-07 21:57:26 | [diff] [blame] | 129 | return; |
| 130 | } |
| 131 | |
Alex Burka | 8355389 | 2016-03-08 18:24:28 | [diff] [blame] | 132 | let typaram = &*deriving::hygienic_type_parameter(item, "__S"); |
| 133 | |
Alex Crichton | a25c704 | 2013-05-30 21:58:16 | [diff] [blame] | 134 | let trait_def = TraitDef { |
Niko Matsakis | eb774f6 | 2014-02-09 00:39:53 | [diff] [blame] | 135 | span: span, |
Patrick Walton | 58fd6ab9 | 2014-02-28 21:09:09 | [diff] [blame] | 136 | attributes: Vec::new(), |
Srinivas Reddy Thatiparthy | 9652fcb | 2016-07-19 17:32:06 | [diff] [blame] | 137 | path: Path::new_(vec![krate, "Encodable"], None, vec![], true), |
Patrick Walton | 58fd6ab9 | 2014-02-28 21:09:09 | [diff] [blame] | 138 | additional_bounds: Vec::new(), |
Alex Crichton | 0cb7a40 | 2015-01-04 06:24:50 | [diff] [blame] | 139 | generics: LifetimeBounds::empty(), |
Michael Layzell | 38d450f | 2015-08-29 18:50:05 | [diff] [blame] | 140 | is_unsafe: false, |
Jeffrey Seyfried | 02f081c | 2016-08-29 11:14:25 | [diff] [blame] | 141 | supports_unions: false, |
iirelu | e593c3b | 2016-10-29 21:54:04 | [diff] [blame] | 142 | methods: vec![ |
Alex Crichton | a25c704 | 2013-05-30 21:58:16 | [diff] [blame] | 143 | MethodDef { |
| 144 | name: "encode", |
Alex Crichton | 0cb7a40 | 2015-01-04 06:24:50 | [diff] [blame] | 145 | generics: LifetimeBounds { |
| 146 | lifetimes: Vec::new(), |
Alex Burka | 8355389 | 2016-03-08 18:24:28 | [diff] [blame] | 147 | bounds: vec![(typaram, |
iirelu | e593c3b | 2016-10-29 21:54:04 | [diff] [blame] | 148 | vec![Path::new_(vec![krate, "Encoder"], None, vec![], true)])] |
Alex Crichton | 0cb7a40 | 2015-01-04 06:24:50 | [diff] [blame] | 149 | }, |
Eduard Burtescu | b2d30b7 | 2014-02-06 22:38:33 | [diff] [blame] | 150 | explicit_self: borrowed_explicit_self(), |
iirelu | e593c3b | 2016-10-29 21:54:04 | [diff] [blame] | 151 | args: vec![Ptr(Box::new(Literal(Path::new_local(typaram))), |
| 152 | Borrowed(None, Mutability::Mutable))], |
Alex Crichton | 0cb7a40 | 2015-01-04 06:24:50 | [diff] [blame] | 153 | ret_ty: Literal(Path::new_( |
Keegan McAllister | 67350bc | 2014-09-07 21:57:26 | [diff] [blame] | 154 | pathvec_std!(cx, core::result::Result), |
Alex Crichton | 0cb7a40 | 2015-01-04 06:24:50 | [diff] [blame] | 155 | None, |
iirelu | e593c3b | 2016-10-29 21:54:04 | [diff] [blame] | 156 | vec![Box::new(Tuple(Vec::new())), Box::new(Literal(Path::new_( |
Alex Burka | 8355389 | 2016-03-08 18:24:28 | [diff] [blame] | 157 | vec![typaram, "Error"], None, vec![], false |
iirelu | e593c3b | 2016-10-29 21:54:04 | [diff] [blame] | 158 | )))], |
Alex Crichton | 0cb7a40 | 2015-01-04 06:24:50 | [diff] [blame] | 159 | true |
| 160 | )), |
Edward Wang | 2cf1e4b | 2014-04-23 14:43:45 | [diff] [blame] | 161 | attributes: Vec::new(), |
Manish Goregaokar | 5b63841 | 2015-05-17 05:58:19 | [diff] [blame] | 162 | is_unsafe: false, |
Björn Steinbrink | 0eeb14e | 2016-05-12 15:54:05 | [diff] [blame] | 163 | unify_fieldless_variants: false, |
Felix S. Klock II | 0d5bcb1 | 2015-02-15 08:52:21 | [diff] [blame] | 164 | combine_substructure: combine_substructure(Box::new(|a, b, c| { |
Oliver Schneider | 2fd2210 | 2016-04-12 13:41:46 | [diff] [blame] | 165 | encodable_substructure(a, b, c, krate) |
Felix S. Klock II | 0d5bcb1 | 2015-02-15 08:52:21 | [diff] [blame] | 166 | })), |
Dzmitry Malyshau | e563215 | 2015-01-25 05:29:24 | [diff] [blame] | 167 | } |
iirelu | e593c3b | 2016-10-29 21:54:04 | [diff] [blame] | 168 | ], |
Dzmitry Malyshau | e563215 | 2015-01-25 05:29:24 | [diff] [blame] | 169 | associated_types: Vec::new(), |
Erick Tryzelaar | 5841564 | 2013-04-10 23:31:51 | [diff] [blame] | 170 | }; |
| 171 | |
Manish Goregaokar | 6bc5a92 | 2015-05-22 15:40:14 | [diff] [blame] | 172 | trait_def.expand(cx, mitem, item, push) |
Erick Tryzelaar | 5841564 | 2013-04-10 23:31:51 | [diff] [blame] | 173 | } |
Huon Wilson | 5dc5efe | 2013-05-15 22:55:57 | [diff] [blame] | 174 | |
Srinivas Reddy Thatiparthy | 9652fcb | 2016-07-19 17:32:06 | [diff] [blame] | 175 | fn encodable_substructure(cx: &mut ExtCtxt, |
| 176 | trait_span: Span, |
| 177 | substr: &Substructure, |
| 178 | krate: &'static str) |
| 179 | -> P<Expr> { |
Eduard Burtescu | ccd8498 | 2014-09-13 16:06:01 | [diff] [blame] | 180 | let encoder = substr.nonself_args[0].clone(); |
Alex Crichton | a25c704 | 2013-05-30 21:58:16 | [diff] [blame] | 181 | // throw an underscore in front to suppress unused variable warnings |
| 182 | let blkarg = cx.ident_of("_e"); |
Huon Wilson | b079ebe | 2014-01-27 04:25:37 | [diff] [blame] | 183 | let blkencoder = cx.expr_ident(trait_span, blkarg); |
Srinivas Reddy Thatiparthy | 9652fcb | 2016-07-19 17:32:06 | [diff] [blame] | 184 | let fn_path = cx.expr_path(cx.path_global(trait_span, |
| 185 | vec![cx.ident_of(krate), |
| 186 | cx.ident_of("Encodable"), |
| 187 | cx.ident_of("encode")])); |
Huon Wilson | 5dc5efe | 2013-05-15 22:55:57 | [diff] [blame] | 188 | |
Alex Crichton | a25c704 | 2013-05-30 21:58:16 | [diff] [blame] | 189 | return match *substr.fields { |
Vadim Petrochenkov | 4e8e607 | 2016-02-22 18:24:32 | [diff] [blame] | 190 | Struct(_, ref fields) => { |
Alex Crichton | a25c704 | 2013-05-30 21:58:16 | [diff] [blame] | 191 | let emit_struct_field = cx.ident_of("emit_struct_field"); |
Patrick Walton | 58fd6ab9 | 2014-02-28 21:09:09 | [diff] [blame] | 192 | let mut stmts = Vec::new(); |
Srinivas Reddy Thatiparthy | 9652fcb | 2016-07-19 17:32:06 | [diff] [blame] | 193 | for (i, &FieldInfo { name, ref self_, span, .. }) in fields.iter().enumerate() { |
Huon Wilson | b079ebe | 2014-01-27 04:25:37 | [diff] [blame] | 194 | let name = match name { |
Jeffrey Seyfried | e85a0d7 | 2016-11-16 10:52:37 | [diff] [blame^] | 195 | Some(id) => id.name, |
| 196 | None => Symbol::intern(&format!("_field{}", i)), |
Alex Crichton | a25c704 | 2013-05-30 21:58:16 | [diff] [blame] | 197 | }; |
Oliver Schneider | 2fd2210 | 2016-04-12 13:41:46 | [diff] [blame] | 198 | let self_ref = cx.expr_addr_of(span, self_.clone()); |
| 199 | let enc = cx.expr_call(span, fn_path.clone(), vec![self_ref, blkencoder.clone()]); |
Eduard Burtescu | 49772fb | 2016-10-25 23:17:29 | [diff] [blame] | 200 | let lambda = cx.lambda1(span, enc, blkarg); |
Srinivas Reddy Thatiparthy | 9652fcb | 2016-07-19 17:32:06 | [diff] [blame] | 201 | let call = cx.expr_method_call(span, |
| 202 | blkencoder.clone(), |
Alex Crichton | a25c704 | 2013-05-30 21:58:16 | [diff] [blame] | 203 | emit_struct_field, |
Srinivas Reddy Thatiparthy | 9652fcb | 2016-07-19 17:32:06 | [diff] [blame] | 204 | vec![cx.expr_str(span, name), |
| 205 | cx.expr_usize(span, i), |
| 206 | lambda]); |
Sean McArthur | f1739b1 | 2014-03-18 17:58:26 | [diff] [blame] | 207 | |
| 208 | // last call doesn't need a try! |
Felix S. Klock II | faf3bcd | 2015-02-20 12:10:54 | [diff] [blame] | 209 | let last = fields.len() - 1; |
Sean McArthur | f1739b1 | 2014-03-18 17:58:26 | [diff] [blame] | 210 | let call = if i != last { |
| 211 | cx.expr_try(span, call) |
| 212 | } else { |
Oliver Schneider | 80bf9ae | 2016-02-08 15:05:05 | [diff] [blame] | 213 | cx.expr(span, ExprKind::Ret(Some(call))) |
Sean McArthur | f1739b1 | 2014-03-18 17:58:26 | [diff] [blame] | 214 | }; |
Alex Crichton | a25c704 | 2013-05-30 21:58:16 | [diff] [blame] | 215 | stmts.push(cx.stmt_expr(call)); |
| 216 | } |
Huon Wilson | 5dc5efe | 2013-05-15 22:55:57 | [diff] [blame] | 217 | |
Piotr Jawniak | 1dc13e4 | 2014-06-01 12:16:11 | [diff] [blame] | 218 | // unit structs have no fields and need to return Ok() |
| 219 | if stmts.is_empty() { |
Oliver Schneider | 80bf9ae | 2016-02-08 15:05:05 | [diff] [blame] | 220 | let ok = cx.expr_ok(trait_span, cx.expr_tuple(trait_span, vec![])); |
| 221 | let ret_ok = cx.expr(trait_span, ExprKind::Ret(Some(ok))); |
Piotr Jawniak | 1dc13e4 | 2014-06-01 12:16:11 | [diff] [blame] | 222 | stmts.push(cx.stmt_expr(ret_ok)); |
| 223 | } |
| 224 | |
Huon Wilson | b079ebe | 2014-01-27 04:25:37 | [diff] [blame] | 225 | let blk = cx.lambda_stmts_1(trait_span, stmts, blkarg); |
Patrick Walton | 8e52b85 | 2014-01-10 22:02:36 | [diff] [blame] | 226 | cx.expr_method_call(trait_span, |
| 227 | encoder, |
| 228 | cx.ident_of("emit_struct"), |
Jeffrey Seyfried | e85a0d7 | 2016-11-16 10:52:37 | [diff] [blame^] | 229 | vec![cx.expr_str(trait_span, substr.type_ident.name), |
Srinivas Reddy Thatiparthy | 9652fcb | 2016-07-19 17:32:06 | [diff] [blame] | 230 | cx.expr_usize(trait_span, fields.len()), |
| 231 | blk]) |
Huon Wilson | 5dc5efe | 2013-05-15 22:55:57 | [diff] [blame] | 232 | } |
| 233 | |
Alex Crichton | a25c704 | 2013-05-30 21:58:16 | [diff] [blame] | 234 | EnumMatching(idx, variant, ref fields) => { |
| 235 | // We're not generating an AST that the borrow checker is expecting, |
| 236 | // so we need to generate a unique local variable to take the |
| 237 | // mutable loan out on, otherwise we get conflicts which don't |
| 238 | // actually exist. |
Huon Wilson | b079ebe | 2014-01-27 04:25:37 | [diff] [blame] | 239 | let me = cx.stmt_let(trait_span, false, blkarg, encoder); |
| 240 | let encoder = cx.expr_ident(trait_span, blkarg); |
Alex Crichton | a25c704 | 2013-05-30 21:58:16 | [diff] [blame] | 241 | let emit_variant_arg = cx.ident_of("emit_enum_variant_arg"); |
Patrick Walton | 58fd6ab9 | 2014-02-28 21:09:09 | [diff] [blame] | 242 | let mut stmts = Vec::new(); |
Tamir Duberstein | 10f15e7 | 2015-03-24 23:54:09 | [diff] [blame] | 243 | if !fields.is_empty() { |
James Miller | 1246d40 | 2015-01-09 03:10:57 | [diff] [blame] | 244 | let last = fields.len() - 1; |
| 245 | for (i, &FieldInfo { ref self_, span, .. }) in fields.iter().enumerate() { |
Srinivas Reddy Thatiparthy | 9652fcb | 2016-07-19 17:32:06 | [diff] [blame] | 246 | let self_ref = cx.expr_addr_of(span, self_.clone()); |
| 247 | let enc = |
| 248 | cx.expr_call(span, fn_path.clone(), vec![self_ref, blkencoder.clone()]); |
Eduard Burtescu | 49772fb | 2016-10-25 23:17:29 | [diff] [blame] | 249 | let lambda = cx.lambda1(span, enc, blkarg); |
Srinivas Reddy Thatiparthy | 9652fcb | 2016-07-19 17:32:06 | [diff] [blame] | 250 | let call = cx.expr_method_call(span, |
| 251 | blkencoder.clone(), |
James Miller | 1246d40 | 2015-01-09 03:10:57 | [diff] [blame] | 252 | emit_variant_arg, |
Srinivas Reddy Thatiparthy | 9652fcb | 2016-07-19 17:32:06 | [diff] [blame] | 253 | vec![cx.expr_usize(span, i), lambda]); |
James Miller | 1246d40 | 2015-01-09 03:10:57 | [diff] [blame] | 254 | let call = if i != last { |
| 255 | cx.expr_try(span, call) |
| 256 | } else { |
Oliver Schneider | 80bf9ae | 2016-02-08 15:05:05 | [diff] [blame] | 257 | cx.expr(span, ExprKind::Ret(Some(call))) |
James Miller | 1246d40 | 2015-01-09 03:10:57 | [diff] [blame] | 258 | }; |
| 259 | stmts.push(cx.stmt_expr(call)); |
| 260 | } |
| 261 | } else { |
Oliver Schneider | 80bf9ae | 2016-02-08 15:05:05 | [diff] [blame] | 262 | let ok = cx.expr_ok(trait_span, cx.expr_tuple(trait_span, vec![])); |
| 263 | let ret_ok = cx.expr(trait_span, ExprKind::Ret(Some(ok))); |
Sean McArthur | f1739b1 | 2014-03-18 17:58:26 | [diff] [blame] | 264 | stmts.push(cx.stmt_expr(ret_ok)); |
| 265 | } |
| 266 | |
Huon Wilson | b079ebe | 2014-01-27 04:25:37 | [diff] [blame] | 267 | let blk = cx.lambda_stmts_1(trait_span, stmts, blkarg); |
Jeffrey Seyfried | e85a0d7 | 2016-11-16 10:52:37 | [diff] [blame^] | 268 | let name = cx.expr_str(trait_span, variant.node.name.name); |
Srinivas Reddy Thatiparthy | 9652fcb | 2016-07-19 17:32:06 | [diff] [blame] | 269 | let call = cx.expr_method_call(trait_span, |
| 270 | blkencoder, |
Alex Crichton | a25c704 | 2013-05-30 21:58:16 | [diff] [blame] | 271 | cx.ident_of("emit_enum_variant"), |
Srinivas Reddy Thatiparthy | 9652fcb | 2016-07-19 17:32:06 | [diff] [blame] | 272 | vec![name, |
| 273 | cx.expr_usize(trait_span, idx), |
| 274 | cx.expr_usize(trait_span, fields.len()), |
| 275 | blk]); |
Eduard Burtescu | 49772fb | 2016-10-25 23:17:29 | [diff] [blame] | 276 | let blk = cx.lambda1(trait_span, call, blkarg); |
Patrick Walton | 8e52b85 | 2014-01-10 22:02:36 | [diff] [blame] | 277 | let ret = cx.expr_method_call(trait_span, |
| 278 | encoder, |
Alex Crichton | a25c704 | 2013-05-30 21:58:16 | [diff] [blame] | 279 | cx.ident_of("emit_enum"), |
Jeffrey Seyfried | e85a0d7 | 2016-11-16 10:52:37 | [diff] [blame^] | 280 | vec![cx.expr_str(trait_span ,substr.type_ident.name), |
Srinivas Reddy Thatiparthy | 9652fcb | 2016-07-19 17:32:06 | [diff] [blame] | 281 | blk]); |
Jeffrey Seyfried | b7da35a | 2016-06-23 09:51:18 | [diff] [blame] | 282 | cx.expr_block(cx.block(trait_span, vec![me, cx.stmt_expr(ret)])) |
Huon Wilson | 5dc5efe | 2013-05-15 22:55:57 | [diff] [blame] | 283 | } |
| 284 | |
Srinivas Reddy Thatiparthy | 9652fcb | 2016-07-19 17:32:06 | [diff] [blame] | 285 | _ => cx.bug("expected Struct or EnumMatching in derive(Encodable)"), |
Alex Crichton | a25c704 | 2013-05-30 21:58:16 | [diff] [blame] | 286 | }; |
Huon Wilson | 5dc5efe | 2013-05-15 22:55:57 | [diff] [blame] | 287 | } |