solid_core/
encode.rs

1/// Declares a type to be encodable as a Solidity type
2pub trait Encode {
3    fn encode(&self) -> Vec<u8>;
4
5    /// The number of bytes required to encode the current type.
6    ///
7    /// This can be a static or dynamic value based on the type. The value should be 32 bytes
8    /// aligned, and does not include the 32 bytes required for the offset.
9    fn required_len(&self) -> u64 {
10        32
11    }
12
13    /// Is this type considered `dynamic` by solidity
14    ///
15    /// If the type is dynamic then the `value` of this field is actually the offset
16    fn is_dynamic() -> bool {
17        false
18    }
19}
20
21impl<T> Encode for &T
22where
23    T: Encode,
24{
25    fn encode(&self) -> Vec<u8> {
26        T::encode(self)
27    }
28
29    fn required_len(&self) -> u64 {
30        T::required_len(self)
31    }
32
33    fn is_dynamic() -> bool {
34        T::is_dynamic()
35    }
36}
37
38impl<T> Encode for Vec<T>
39where
40    T: Encode,
41{
42    fn encode(&self) -> Vec<u8> {
43        let len = self.required_len();
44
45        let mut buf = vec![0u8; len as usize];
46        buf[24..32].copy_from_slice(&(self.len() as u64).to_be_bytes());
47
48        let mut offset = self.len() * 32;
49
50        for (index, bytes) in self.into_iter().map(Encode::encode).enumerate() {
51            if T::is_dynamic() {
52                buf[32 + index * 32 + 24..32 + (index + 1) * 32]
53                    .copy_from_slice(&(offset as u64).to_be_bytes());
54                buf[32 + offset..32 + offset + bytes.len()].copy_from_slice(&bytes);
55                offset += bytes.len()
56            } else {
57                buf[32 + index * 32..32 + (index + 1) * 32].copy_from_slice(&bytes);
58            }
59        }
60
61        buf
62    }
63
64    fn required_len(&self) -> u64 {
65        self.iter().map(Encode::required_len).sum::<u64>()
66            + if T::is_dynamic() {
67                32 * self.len() + 32
68            } else {
69                32
70            } as u64
71    }
72
73    fn is_dynamic() -> bool {
74        true
75    }
76}
77
78impl<'a, T> Encode for &'a [T]
79where
80    T: Encode,
81{
82    fn encode(&self) -> Vec<u8> {
83        let len = self.required_len();
84
85        let mut buf = vec![0u8; len as usize];
86        buf[24..32].copy_from_slice(&(self.len() as u64).to_be_bytes());
87
88        let mut offset = self.len() * 32;
89
90        for (index, bytes) in (*self).into_iter().map(Encode::encode).enumerate() {
91            if T::is_dynamic() {
92                buf[32 + index * 32 + 24..32 + (index + 1) * 32]
93                    .copy_from_slice(&(offset as u64).to_be_bytes());
94                buf[32 + offset..32 + offset + bytes.len()].copy_from_slice(&bytes);
95                offset += bytes.len()
96            } else {
97                buf[32 + index * 32..32 + (index + 1) * 32].copy_from_slice(&bytes);
98            }
99        }
100
101        buf
102    }
103
104    fn required_len(&self) -> u64 {
105        self.iter().map(Encode::required_len).sum::<u64>()
106            + if T::is_dynamic() {
107                32 * self.len() + 32
108            } else {
109                32
110            } as u64
111    }
112
113    fn is_dynamic() -> bool {
114        true
115    }
116}