From e46e9332d9574790ccf41ae56ffa1010c4267ba1 Mon Sep 17 00:00:00 2001
From: Alex Crichton <alex@alexcrichton.com>
Date: Sat, 22 Mar 2014 21:58:51 -0700
Subject: [PATCH] serialize: Read/emit tuples with {read,emit}_tuple

This commit moves from {read,emit}_seq for tuples to {read,emit}_tuple, as well
as providing a generalized macro for generating these implementations from one
invocation.

Closes #13086
---
 src/libserialize/serialize.rs | 170 ++++++----------------------------
 1 file changed, 30 insertions(+), 140 deletions(-)

diff --git a/src/libserialize/serialize.rs b/src/libserialize/serialize.rs
index 60de03a7b43..036b580cc5f 100644
--- a/src/libserialize/serialize.rs
+++ b/src/libserialize/serialize.rs
@@ -477,153 +477,43 @@ impl<D:Decoder,T:Decodable<D>> Decodable<D> for Option<T> {
     }
 }
 
-impl<S:Encoder,T0:Encodable<S>,T1:Encodable<S>> Encodable<S> for (T0, T1) {
-    fn encode(&self, s: &mut S) {
-        match *self {
-            (ref t0, ref t1) => {
-                s.emit_seq(2, |s| {
-                    s.emit_seq_elt(0, |s| t0.encode(s));
-                    s.emit_seq_elt(1, |s| t1.encode(s));
+macro_rules! peel(($name:ident, $($other:ident,)*) => (tuple!($($other,)*)))
+
+macro_rules! tuple (
+    () => ();
+    ( $($name:ident,)+ ) => (
+        impl<D:Decoder,$($name:Decodable<D>),*> Decodable<D> for ($($name,)*) {
+            #[allow(uppercase_variables)]
+            fn decode(d: &mut D) -> ($($name,)*) {
+                d.read_tuple(|d, amt| {
+                    let mut i = 0;
+                    let ret = ($(d.read_tuple_arg({ i+=1; i-1 }, |d| -> $name {
+                        Decodable::decode(d)
+                    }),)*);
+                    assert!(amt == i,
+                            "expected tuple of length `{}`, found tuple \
+                             of length `{}`", i, amt);
+                    return ret;
                 })
             }
         }
-    }
-}
-
-impl<D:Decoder,T0:Decodable<D>,T1:Decodable<D>> Decodable<D> for (T0, T1) {
-    fn decode(d: &mut D) -> (T0, T1) {
-        d.read_seq(|d, len| {
-            assert_eq!(len, 2);
-            (
-                d.read_seq_elt(0, |d| Decodable::decode(d)),
-                d.read_seq_elt(1, |d| Decodable::decode(d))
-            )
-        })
-    }
-}
-
-impl<
-    S: Encoder,
-    T0: Encodable<S>,
-    T1: Encodable<S>,
-    T2: Encodable<S>
-> Encodable<S> for (T0, T1, T2) {
-    fn encode(&self, s: &mut S) {
-        match *self {
-            (ref t0, ref t1, ref t2) => {
-                s.emit_seq(3, |s| {
-                    s.emit_seq_elt(0, |s| t0.encode(s));
-                    s.emit_seq_elt(1, |s| t1.encode(s));
-                    s.emit_seq_elt(2, |s| t2.encode(s));
+        impl<S:Encoder,$($name:Encodable<S>),*> Encodable<S> for ($($name,)*) {
+            #[allow(uppercase_variables)]
+            fn encode(&self, s: &mut S) {
+                let ($(ref $name,)*) = *self;
+                let mut n = 0;
+                $(let $name = $name; n += 1;)*
+                s.emit_tuple(n, |s| {
+                    let mut i = 0;
+                    $(s.emit_seq_elt({ i+=1; i-1 }, |s| $name.encode(s));)*
                 })
             }
         }
-    }
-}
+        peel!($($name,)*)
+    )
+)
 
-impl<
-    D: Decoder,
-    T0: Decodable<D>,
-    T1: Decodable<D>,
-    T2: Decodable<D>
-> Decodable<D> for (T0, T1, T2) {
-    fn decode(d: &mut D) -> (T0, T1, T2) {
-        d.read_seq(|d, len| {
-            assert_eq!(len, 3);
-            (
-                d.read_seq_elt(0, |d| Decodable::decode(d)),
-                d.read_seq_elt(1, |d| Decodable::decode(d)),
-                d.read_seq_elt(2, |d| Decodable::decode(d))
-            )
-        })
-    }
-}
-
-impl<
-    S: Encoder,
-    T0: Encodable<S>,
-    T1: Encodable<S>,
-    T2: Encodable<S>,
-    T3: Encodable<S>
-> Encodable<S> for (T0, T1, T2, T3) {
-    fn encode(&self, s: &mut S) {
-        match *self {
-            (ref t0, ref t1, ref t2, ref t3) => {
-                s.emit_seq(4, |s| {
-                    s.emit_seq_elt(0, |s| t0.encode(s));
-                    s.emit_seq_elt(1, |s| t1.encode(s));
-                    s.emit_seq_elt(2, |s| t2.encode(s));
-                    s.emit_seq_elt(3, |s| t3.encode(s));
-                })
-            }
-        }
-    }
-}
-
-impl<
-    D: Decoder,
-    T0: Decodable<D>,
-    T1: Decodable<D>,
-    T2: Decodable<D>,
-    T3: Decodable<D>
-> Decodable<D> for (T0, T1, T2, T3) {
-    fn decode(d: &mut D) -> (T0, T1, T2, T3) {
-        d.read_seq(|d, len| {
-            assert_eq!(len, 4);
-            (
-                d.read_seq_elt(0, |d| Decodable::decode(d)),
-                d.read_seq_elt(1, |d| Decodable::decode(d)),
-                d.read_seq_elt(2, |d| Decodable::decode(d)),
-                d.read_seq_elt(3, |d| Decodable::decode(d))
-            )
-        })
-    }
-}
-
-impl<
-    S: Encoder,
-    T0: Encodable<S>,
-    T1: Encodable<S>,
-    T2: Encodable<S>,
-    T3: Encodable<S>,
-    T4: Encodable<S>
-> Encodable<S> for (T0, T1, T2, T3, T4) {
-    fn encode(&self, s: &mut S) {
-        match *self {
-            (ref t0, ref t1, ref t2, ref t3, ref t4) => {
-                s.emit_seq(5, |s| {
-                    s.emit_seq_elt(0, |s| t0.encode(s));
-                    s.emit_seq_elt(1, |s| t1.encode(s));
-                    s.emit_seq_elt(2, |s| t2.encode(s));
-                    s.emit_seq_elt(3, |s| t3.encode(s));
-                    s.emit_seq_elt(4, |s| t4.encode(s));
-                })
-            }
-        }
-    }
-}
-
-impl<
-    D: Decoder,
-    T0: Decodable<D>,
-    T1: Decodable<D>,
-    T2: Decodable<D>,
-    T3: Decodable<D>,
-    T4: Decodable<D>
-> Decodable<D> for (T0, T1, T2, T3, T4) {
-    fn decode(d: &mut D) -> (T0, T1, T2, T3, T4) {
-        d.read_seq(|d, len| {
-            assert_eq!(len, 5);
-            (
-                d.read_seq_elt(0, |d| Decodable::decode(d)),
-                d.read_seq_elt(1, |d| Decodable::decode(d)),
-                d.read_seq_elt(2, |d| Decodable::decode(d)),
-                d.read_seq_elt(3, |d| Decodable::decode(d)),
-                d.read_seq_elt(4, |d| Decodable::decode(d))
-            )
-        })
-    }
-}
+tuple! { T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, }
 
 impl<E: Encoder> Encodable<E> for path::posix::Path {
     fn encode(&self, e: &mut E) {