1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
use crate::{
    decode::Decode,
    encode::Encode,
    into_type::IntoType,
};
use std::borrow::Cow;

macro_rules! impl_encode_and_into_types_for_tuples {
	  ($(($index:tt => $ident:ident) ),+) => {
        #[allow(unused)]
        impl<$($ident: Encode, )+> Encode for ($($ident, )+) {
            fn encode(&self) -> Vec<u8> {
                let len = self.required_len();

                let mut buf: Vec<u8> = vec![0; len as usize];

                let mut count = 0usize;

                $(
                    count += if $ident::is_dynamic() { 1 } else { 1 };
                )+

                let mut offset: usize = count * 32;

                let mut index = 0;

                $(
                    let bytes = self.$index.encode();

                    if $ident::is_dynamic() {
                        buf[index * 32 + 24..(index + 1) * 32]
                            .copy_from_slice(&(offset as u64).to_be_bytes());
                        buf[offset..offset + bytes.len()]
                            .copy_from_slice(&bytes);
                        offset += bytes.len()
                    } else {
                        buf[index * 32..(index + 1) * 32]
                            .copy_from_slice(&bytes);
                    }

                    index += 1;
                )+

                buf
            }

            fn required_len(&self) -> u64 {
                let mut len = 0u64;

                $(
                    len += self.$index.required_len();
                    len += if $ident::is_dynamic() {
                        32
                    } else {
                        0
                    };
                )+

                len
            }

            fn is_dynamic() -> bool {
                true
            }
        }

        impl<$($ident: IntoType, )+> IntoType for ($($ident,) +) {
            fn into_type() -> Cow<'static, str> {
                let mut ty = Vec::new();
                $(
                    ty.push($ident::into_type());
                )+

                Cow::Owned(format!("({})", ty.join(",")))
            }
        }

        #[allow(unused)]
        impl<'a, $($ident: Encode + Decode<'a>, )+> Decode<'a> for ($($ident,) +)
        {
            fn decode(buf: &'a [u8]) -> Self {
                let mut index = 0;


                (
                    $(
                        {
                            let value = if $ident::is_dynamic() {
                                $ident::decode(&buf[index * 32..(index + 1) * 32])
                            } else {
                                let offset = u64::decode(&buf[index * 32..(index + 1) * 32]);
                                $ident::decode(&buf[offset as usize..])
                            };
                            index += 1;
                            value
                        },
                    )+
                )
            }
        }
	  };
}

impl_encode_and_into_types_for_tuples!(
    (0 => T0),
    (1 => T1)
);
impl_encode_and_into_types_for_tuples!(
    (0 => T0),
    (1 => T1),
    (2 => T2)
);

impl_encode_and_into_types_for_tuples!(
    (0 => T0),
    (1 => T1),
    (2 => T2),
    (3 => T3)
);

impl_encode_and_into_types_for_tuples!(
    (0 => T0),
    (1 => T1),
    (2 => T2),
    (3 => T3),
    (4 => T4)
);

impl_encode_and_into_types_for_tuples!(
    (0 => T0),
    (1 => T1),
    (2 => T2),
    (3 => T3),
    (4 => T4),
    (5 => T5)
);

impl_encode_and_into_types_for_tuples!(
    (0 => T0),
    (1 => T1),
    (2 => T2),
    (3 => T3),
    (4 => T4),
    (5 => T5),
    (6 => T6)
);