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
/// Declares a type to be encodable as a Solidity type
pub trait Encode {
    fn encode(&self) -> Vec<u8>;

    /// The number of bytes required to encode the current type.
    ///
    /// This can be a static or dynamic value based on the type. The value should be 32 bytes
    /// aligned, and does not include the 32 bytes required for the offset.
    fn required_len(&self) -> u64 {
        32
    }

    /// Is this type considered `dynamic` by solidity
    ///
    /// If the type is dynamic then the `value` of this field is actually the offset
    fn is_dynamic() -> bool {
        false
    }
}

impl<T> Encode for &T
where
    T: Encode,
{
    fn encode(&self) -> Vec<u8> {
        T::encode(self)
    }

    fn required_len(&self) -> u64 {
        T::required_len(self)
    }

    fn is_dynamic() -> bool {
        T::is_dynamic()
    }
}

impl<T> Encode for Vec<T>
where
    T: Encode,
{
    fn encode(&self) -> Vec<u8> {
        let len = self.required_len();

        let mut buf = vec![0u8; len as usize];
        buf[24..32].copy_from_slice(&(self.len() as u64).to_be_bytes());

        let mut offset = self.len() * 32;

        for (index, bytes) in self.into_iter().map(Encode::encode).enumerate() {
            if T::is_dynamic() {
                buf[32 + index * 32 + 24..32 + (index + 1) * 32]
                    .copy_from_slice(&(offset as u64).to_be_bytes());
                buf[32 + offset..32 + offset + bytes.len()].copy_from_slice(&bytes);
                offset += bytes.len()
            } else {
                buf[32 + index * 32..32 + (index + 1) * 32].copy_from_slice(&bytes);
            }
        }

        buf
    }

    fn required_len(&self) -> u64 {
        self.iter().map(Encode::required_len).sum::<u64>()
            + if T::is_dynamic() {
                32 * self.len() + 32
            } else {
                32
            } as u64
    }

    fn is_dynamic() -> bool {
        true
    }
}

impl<'a, T> Encode for &'a [T]
where
    T: Encode,
{
    fn encode(&self) -> Vec<u8> {
        let len = self.required_len();

        let mut buf = vec![0u8; len as usize];
        buf[24..32].copy_from_slice(&(self.len() as u64).to_be_bytes());

        let mut offset = self.len() * 32;

        for (index, bytes) in (*self).into_iter().map(Encode::encode).enumerate() {
            if T::is_dynamic() {
                buf[32 + index * 32 + 24..32 + (index + 1) * 32]
                    .copy_from_slice(&(offset as u64).to_be_bytes());
                buf[32 + offset..32 + offset + bytes.len()].copy_from_slice(&bytes);
                offset += bytes.len()
            } else {
                buf[32 + index * 32..32 + (index + 1) * 32].copy_from_slice(&bytes);
            }
        }

        buf
    }

    fn required_len(&self) -> u64 {
        self.iter().map(Encode::required_len).sum::<u64>()
            + if T::is_dynamic() {
                32 * self.len() + 32
            } else {
                32
            } as u64
    }

    fn is_dynamic() -> bool {
        true
    }
}