Skip to main content

solabi/
bytes.rs

1//! Solidity bytes type.
2
3use crate::{
4    decode::{Decode, DecodeError, Decoder},
5    encode::{Encode, Encoder, Size},
6    encode_packed::EncodePacked,
7    fmt::Hex,
8    log::{FromTopic, ToTopic, TopicHash},
9    primitive::{Primitive, Word},
10};
11use ethprim::Hasher;
12use std::{
13    borrow::{Borrow, Cow},
14    fmt::{self, Debug, Formatter},
15    mem,
16    ops::{Deref, DerefMut},
17};
18
19/// A wrapper type for bytes.
20#[derive(Clone, Copy, Default, Eq, PartialEq)]
21#[repr(transparent)]
22pub struct Bytes<T>(pub T)
23where
24    T: ?Sized;
25
26impl Bytes<[u8]> {
27    /// Returns a borrowed `Bytes` from a slice of bytes.
28    #[allow(clippy::needless_lifetimes)]
29    pub const fn new<'a>(bytes: &'a [u8]) -> &'a Bytes<[u8]> {
30        // SAFETY: DSTs are a bit of a mystery to me... To my understanding
31        // this should be safe because `Bytes` has a transparent layout, so
32        // `&[u8]` and `&Bytes<[u8]>`. Either way, we should get a fat pointer
33        // with the correct length and pointing to the start of the slice and
34        // transmuting between them should be safe.
35        unsafe { mem::transmute(bytes) }
36    }
37
38    /// Returns a new `Cow::Borrowed` slice of bytes.
39    #[allow(clippy::needless_lifetimes)]
40    pub const fn borrowed<'a>(bytes: &'a [u8]) -> Cow<'a, Bytes<[u8]>> {
41        Cow::Borrowed(Self::new(bytes))
42    }
43}
44
45impl<T> Bytes<T>
46where
47    T: AsRef<[u8]> + ?Sized,
48{
49    /// Returns the underlying slice of bytes.
50    pub fn as_bytes(&self) -> &[u8] {
51        self.as_ref()
52    }
53}
54
55impl<T> Bytes<T>
56where
57    T: AsMut<[u8]> + ?Sized,
58{
59    /// Returns a mutable reference to the underlying slice of bytes.
60    pub fn as_bytes_mut(&mut self) -> &[u8] {
61        self.as_mut()
62    }
63}
64
65impl Bytes<Vec<u8>> {
66    /// Returns a borrowed `Bytes`.
67    pub fn as_borrowed(&self) -> &Bytes<[u8]> {
68        Bytes::new(&self[..])
69    }
70}
71
72impl<T> AsRef<[u8]> for Bytes<T>
73where
74    T: AsRef<[u8]> + ?Sized,
75{
76    fn as_ref(&self) -> &[u8] {
77        self.0.as_ref()
78    }
79}
80
81impl<T> AsMut<[u8]> for Bytes<T>
82where
83    T: AsMut<[u8]> + ?Sized,
84{
85    fn as_mut(&mut self) -> &mut [u8] {
86        self.0.as_mut()
87    }
88}
89
90impl<T> Debug for Bytes<T>
91where
92    T: AsRef<[u8]> + ?Sized,
93{
94    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
95        f.debug_tuple("Bytes").field(&Hex(self.0.as_ref())).finish()
96    }
97}
98
99impl<T> Deref for Bytes<T>
100where
101    T: ?Sized,
102{
103    type Target = T;
104
105    fn deref(&self) -> &Self::Target {
106        &self.0
107    }
108}
109
110impl<T> DerefMut for Bytes<T>
111where
112    T: ?Sized,
113{
114    fn deref_mut(&mut self) -> &mut Self::Target {
115        &mut self.0
116    }
117}
118
119impl Borrow<Bytes<[u8]>> for Bytes<Vec<u8>> {
120    fn borrow(&self) -> &Bytes<[u8]> {
121        self.as_borrowed()
122    }
123}
124
125impl ToOwned for Bytes<[u8]> {
126    type Owned = Bytes<Vec<u8>>;
127
128    fn to_owned(&self) -> Self::Owned {
129        Bytes(self.0.to_owned())
130    }
131}
132
133macro_rules! impl_fixed_bytes {
134    ($($n:literal,)*) => {$(
135        impl Primitive for Bytes<[u8; $n]> {
136            fn to_word(&self) -> Word {
137                let mut word = Word::default();
138                word[..$n].copy_from_slice(self.as_ref());
139                word
140            }
141
142            fn from_word(word: Word) -> Option<Self> {
143                if word[$n..] != [0; 32 - $n] {
144                    return None;
145                }
146                let mut bytes = Self::default();
147                bytes.copy_from_slice(&word[..$n]);
148                Some(bytes)
149            }
150        }
151
152        impl EncodePacked for Bytes<[u8; $n]> {
153            fn packed_size(&self) -> usize {
154                $n
155            }
156
157            fn encode_packed(&self, out: &mut [u8]) {
158                out.copy_from_slice(self.as_ref())
159            }
160        }
161    )*};
162}
163
164impl_fixed_bytes! {
165     1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16,
166    17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
167}
168
169impl Encode for Bytes<[u8]> {
170    fn size(&self) -> Size {
171        Bytes(&self.0).size()
172    }
173
174    fn encode(&self, encoder: &mut Encoder) {
175        Bytes(&self.0).encode(encoder)
176    }
177}
178
179impl EncodePacked for Bytes<[u8]> {
180    fn packed_size(&self) -> usize {
181        Bytes(&self.0).packed_size()
182    }
183
184    fn encode_packed(&self, out: &mut [u8]) {
185        Bytes(&self.0).encode_packed(out)
186    }
187}
188
189impl ToTopic for Bytes<[u8]> {
190    fn to_topic(&self) -> Word {
191        Bytes(&self.0).to_topic()
192    }
193}
194
195impl TopicHash for Bytes<[u8]> {
196    fn update_hash(&self, hasher: &mut Hasher) {
197        Bytes(&self.0).update_hash(hasher);
198    }
199}
200
201impl Encode for Bytes<&'_ [u8]> {
202    fn size(&self) -> Size {
203        let words = self.len().div_ceil(32);
204        Size::Dynamic(1 + words, 0)
205    }
206
207    fn encode(&self, encoder: &mut Encoder) {
208        encoder.write(&self.len());
209        encoder.write_bytes(self);
210    }
211}
212
213impl EncodePacked for Bytes<&'_ [u8]> {
214    fn packed_size(&self) -> usize {
215        self.len()
216    }
217
218    fn encode_packed(&self, out: &mut [u8]) {
219        out.copy_from_slice(self);
220    }
221}
222
223impl ToTopic for Bytes<&'_ [u8]> {
224    fn to_topic(&self) -> Word {
225        let mut hasher = Hasher::new();
226        hasher.update(self);
227        *hasher.finalize()
228    }
229}
230
231impl TopicHash for Bytes<&'_ [u8]> {
232    fn update_hash(&self, hasher: &mut Hasher) {
233        hasher.update(self);
234
235        static ZEROS: Word = [0; 32];
236        let padding = (32 - (self.len() % 32)) % 32;
237        hasher.update(&ZEROS[..padding]);
238    }
239}
240
241impl Encode for Bytes<Vec<u8>> {
242    fn size(&self) -> Size {
243        Bytes(&self[..]).size()
244    }
245
246    fn encode(&self, encoder: &mut Encoder) {
247        Bytes(&self[..]).encode(encoder)
248    }
249}
250
251impl EncodePacked for Bytes<Vec<u8>> {
252    fn packed_size(&self) -> usize {
253        Bytes(&self[..]).packed_size()
254    }
255
256    fn encode_packed(&self, out: &mut [u8]) {
257        Bytes(&self[..]).encode_packed(out)
258    }
259}
260
261impl Decode for Bytes<Vec<u8>> {
262    fn is_dynamic() -> bool {
263        true
264    }
265
266    fn decode(decoder: &mut Decoder) -> Result<Self, DecodeError> {
267        let len = decoder.read_size()?;
268        Ok(Self(decoder.read_bytes(len)?.to_owned()))
269    }
270}
271
272impl ToTopic for Bytes<Vec<u8>> {
273    fn to_topic(&self) -> Word {
274        Bytes(&self[..]).to_topic()
275    }
276}
277
278impl FromTopic for Bytes<Vec<u8>> {
279    fn from_topic(_: Word) -> Option<Self> {
280        Some(Self::default())
281    }
282}
283
284impl TopicHash for Bytes<Vec<u8>> {
285    fn update_hash(&self, hasher: &mut Hasher) {
286        Bytes(&self[..]).update_hash(hasher);
287    }
288}