Skip to main content

light_hasher/
bytes.rs

1use std::{mem, slice};
2
3/// A trait providing [`as_byte_vec()`](AsByteVec::as_byte_vec) method for types which
4/// are used inside compressed accounts.
5pub trait AsByteVec {
6    fn as_byte_vec(&self) -> Vec<Vec<u8>>;
7}
8
9macro_rules! impl_as_byte_vec_for_integer_type {
10    ($int_ty:ty) => {
11        impl AsByteVec for $int_ty {
12            fn as_byte_vec(&self) -> Vec<Vec<u8>> {
13                vec![self.to_le_bytes().to_vec()]
14            }
15        }
16    };
17}
18
19macro_rules! impl_as_byte_vec_for_primitive_type {
20    ($int_ty:ty) => {
21        impl AsByteVec for $int_ty {
22            fn as_byte_vec(&self) -> Vec<Vec<u8>> {
23                let len = mem::size_of_val(self);
24                let self_ptr: *const Self = self;
25                // SAFETY:
26                // - All the primitive types we implement this macro for have
27                //   an exact size (`len`). There is no chance of reads out of
28                //   bounds.
29                // - Casting Rust primitives to bytes works fine, there is no
30                //   chance of undefined behavior.
31                // - Unfortunately, there is no way to achieve the similar
32                //   result with fully safe code. If we tried to do anything
33                //   like `&self.to_le_bytes()` or `self.to_le_bytes().as_slice()`,
34                //   compiler would complain with "cannot return reference to
35                //   temporary value".
36                let self_byte_slice = unsafe { slice::from_raw_parts(self_ptr.cast::<u8>(), len) };
37                vec![self_byte_slice.to_vec()]
38            }
39        }
40    };
41}
42
43impl_as_byte_vec_for_integer_type!(i8);
44impl_as_byte_vec_for_integer_type!(u8);
45impl_as_byte_vec_for_integer_type!(i16);
46impl_as_byte_vec_for_integer_type!(u16);
47impl_as_byte_vec_for_integer_type!(i32);
48impl_as_byte_vec_for_integer_type!(u32);
49impl_as_byte_vec_for_integer_type!(i64);
50impl_as_byte_vec_for_integer_type!(u64);
51impl_as_byte_vec_for_integer_type!(isize);
52impl_as_byte_vec_for_integer_type!(usize);
53impl_as_byte_vec_for_integer_type!(i128);
54impl_as_byte_vec_for_integer_type!(u128);
55
56impl_as_byte_vec_for_primitive_type!(bool);
57
58impl<T> AsByteVec for Option<T>
59where
60    T: AsByteVec,
61{
62    fn as_byte_vec(&self) -> Vec<Vec<u8>> {
63        match self {
64            Some(hashable) => {
65                let mut bytes = hashable.as_byte_vec();
66                bytes.reserve(1);
67                bytes.insert(0, vec![1]);
68                bytes
69            }
70            None => vec![vec![0]],
71        }
72    }
73}
74
75impl<const N: usize> AsByteVec for [u8; N] {
76    fn as_byte_vec(&self) -> Vec<Vec<u8>> {
77        vec![self.to_vec()]
78    }
79}
80
81impl AsByteVec for String {
82    fn as_byte_vec(&self) -> Vec<Vec<u8>> {
83        vec![self.as_bytes().to_vec()]
84    }
85}
86
87impl AsByteVec for solana_program::pubkey::Pubkey {
88    fn as_byte_vec(&self) -> Vec<Vec<u8>> {
89        vec![self.to_bytes().to_vec()]
90    }
91}
92
93#[cfg(test)]
94mod test {
95    use super::*;
96
97    #[test]
98    fn test_as_byte_vec_integers() {
99        let i8_min: &dyn AsByteVec = &i8::MIN;
100        let i8_min_bytes = i8_min.as_byte_vec();
101        assert_eq!(i8_min_bytes, &[&[128]]);
102        assert_eq!(i8_min_bytes, &[i8::MIN.to_le_bytes()]);
103        let i8_max: &dyn AsByteVec = &i8::MAX;
104        let i8_max_bytes = i8_max.as_byte_vec();
105        assert_eq!(i8_max_bytes, &[&[127]]);
106        assert_eq!(i8_max_bytes, &[i8::MAX.to_le_bytes()]);
107
108        let u8_min: &dyn AsByteVec = &u8::MIN;
109        let u8_min_bytes = u8_min.as_byte_vec();
110        assert_eq!(u8_min_bytes, &[&[0]]);
111        assert_eq!(u8_min_bytes, &[u8::MIN.to_le_bytes()]);
112        let u8_max: &dyn AsByteVec = &u8::MAX;
113        let u8_max_bytes = u8_max.as_byte_vec();
114        assert_eq!(u8_max_bytes, &[&[255]]);
115        assert_eq!(u8_max_bytes, &[u8::MAX.to_le_bytes()]);
116
117        let i16_min: &dyn AsByteVec = &i16::MIN;
118        let i16_min_bytes = i16_min.as_byte_vec();
119        assert_eq!(i16_min_bytes, &[&[0, 128]]);
120        assert_eq!(i16_min_bytes, &[&i16::MIN.to_le_bytes()]);
121        let i16_max: &dyn AsByteVec = &i16::MAX;
122        let i16_max_bytes = i16_max.as_byte_vec();
123        assert_eq!(i16_max_bytes, &[&[255, 127]]);
124        assert_eq!(i16_max_bytes, &[i16::MAX.to_le_bytes()]);
125
126        let u16_min: &dyn AsByteVec = &u16::MIN;
127        let u16_min_bytes = u16_min.as_byte_vec();
128        assert_eq!(u16_min_bytes, &[&[0, 0]]);
129        assert_eq!(u16_min_bytes, &[u16::MIN.to_le_bytes()]);
130        let u16_max: &dyn AsByteVec = &u16::MAX;
131        let u16_max_bytes = u16_max.as_byte_vec();
132        assert_eq!(u16_max_bytes, &[&[255, 255]]);
133        assert_eq!(u16_max_bytes, &[u16::MAX.to_le_bytes()]);
134
135        let i32_min: &dyn AsByteVec = &i32::MIN;
136        let i32_min_bytes = i32_min.as_byte_vec();
137        assert_eq!(i32_min_bytes, &[&[0, 0, 0, 128]]);
138        assert_eq!(i32_min_bytes, &[i32::MIN.to_le_bytes()]);
139        let i32_max: &dyn AsByteVec = &i32::MAX;
140        let i32_max_bytes = i32_max.as_byte_vec();
141        assert_eq!(i32_max_bytes, &[&[255, 255, 255, 127]]);
142        assert_eq!(i32_max_bytes, &[i32::MAX.to_le_bytes()]);
143
144        let u32_min: &dyn AsByteVec = &u32::MIN;
145        let u32_min_bytes = u32_min.as_byte_vec();
146        assert_eq!(u32_min_bytes, &[&[0, 0, 0, 0]]);
147        assert_eq!(u32_min_bytes, &[u32::MIN.to_le_bytes()]);
148        let u32_max: &dyn AsByteVec = &u32::MAX;
149        let u32_max_bytes = u32_max.as_byte_vec();
150        assert_eq!(u32_max_bytes, &[&[255, 255, 255, 255]]);
151        assert_eq!(u32_max_bytes, &[u32::MAX.to_le_bytes()]);
152
153        let i64_min: &dyn AsByteVec = &i64::MIN;
154        let i64_min_bytes = i64_min.as_byte_vec();
155        assert_eq!(i64_min_bytes, &[&[0, 0, 0, 0, 0, 0, 0, 128]]);
156        assert_eq!(i64_min_bytes, &[i64::MIN.to_le_bytes()]);
157        let i64_max: &dyn AsByteVec = &i64::MAX;
158        let i64_max_bytes = i64_max.as_byte_vec();
159        assert_eq!(i64_max_bytes, &[&[255, 255, 255, 255, 255, 255, 255, 127]]);
160        assert_eq!(i64_max_bytes, &[i64::MAX.to_le_bytes()]);
161
162        let u64_min: &dyn AsByteVec = &u64::MIN;
163        let u64_min_bytes = u64_min.as_byte_vec();
164        assert_eq!(u64_min_bytes, &[[0, 0, 0, 0, 0, 0, 0, 0]]);
165        assert_eq!(i64_min_bytes, &[i64::MIN.to_le_bytes()]);
166        let u64_max: &dyn AsByteVec = &u64::MAX;
167        let u64_max_bytes = u64_max.as_byte_vec();
168        assert_eq!(u64_max_bytes, &[&[255, 255, 255, 255, 255, 255, 255, 255]]);
169        assert_eq!(u64_max_bytes, &[u64::MAX.to_le_bytes()]);
170
171        let i128_min: &dyn AsByteVec = &i128::MIN;
172        let i128_min_bytes = i128_min.as_byte_vec();
173        assert_eq!(
174            i128_min_bytes,
175            &[&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128]]
176        );
177        assert_eq!(i128_min_bytes, &[i128::MIN.to_le_bytes()]);
178        let i128_max: &dyn AsByteVec = &i128::MAX;
179        let i128_max_bytes = i128_max.as_byte_vec();
180        assert_eq!(
181            i128_max_bytes,
182            &[&[255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 127]]
183        );
184        assert_eq!(i128_max_bytes, &[i128::MAX.to_le_bytes()]);
185
186        let u128_min: &dyn AsByteVec = &u128::MIN;
187        let u128_min_bytes = u128_min.as_byte_vec();
188        assert_eq!(
189            u128_min_bytes,
190            &[&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]
191        );
192        assert_eq!(u128_min_bytes, &[u128::MIN.to_le_bytes()]);
193        let u128_max: &dyn AsByteVec = &u128::MAX;
194        let u128_max_bytes = u128_max.as_byte_vec();
195        assert_eq!(
196            u128_max_bytes,
197            &[&[255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255]]
198        );
199        assert_eq!(u128_max_bytes, &[u128::MAX.to_le_bytes()]);
200    }
201
202    #[test]
203    fn test_as_byte_vec_primitives() {
204        let bool_false: &dyn AsByteVec = &false;
205        assert_eq!(bool_false.as_byte_vec(), &[&[0]]);
206
207        let bool_true: &dyn AsByteVec = &true;
208        assert_eq!(bool_true.as_byte_vec(), &[&[1]]);
209    }
210
211    #[test]
212    fn test_as_byte_vec_option() {
213        // Very important property - `None` and `Some(0)` always have to be
214        // different and should produce different hashes!
215        let u8_none: Option<u8> = None;
216        let u8_none: &dyn AsByteVec = &u8_none;
217        assert_eq!(u8_none.as_byte_vec(), &[&[0]]);
218
219        let u8_some_zero: Option<u8> = Some(0);
220        let u8_some_zero: &dyn AsByteVec = &u8_some_zero;
221        assert_eq!(u8_some_zero.as_byte_vec(), &[&[1], &[0]]);
222
223        let u16_none: Option<u16> = None;
224        let u16_none: &dyn AsByteVec = &u16_none;
225        assert_eq!(u16_none.as_byte_vec(), &[&[0]]);
226
227        let u16_some_zero: Option<u16> = Some(0);
228        let u16_some_zero: &dyn AsByteVec = &u16_some_zero;
229        assert_eq!(u16_some_zero.as_byte_vec(), &[&[1][..], &[0, 0][..]]);
230
231        let u32_none: Option<u32> = None;
232        let u32_none: &dyn AsByteVec = &u32_none;
233        assert_eq!(u32_none.as_byte_vec(), &[&[0]]);
234
235        let u32_some_zero: Option<u32> = Some(0);
236        let u32_some_zero: &dyn AsByteVec = &u32_some_zero;
237        assert_eq!(u32_some_zero.as_byte_vec(), &[&[1][..], &[0, 0, 0, 0][..]]);
238
239        let u64_none: Option<u64> = None;
240        let u64_none: &dyn AsByteVec = &u64_none;
241        assert_eq!(u64_none.as_byte_vec(), &[&[0]]);
242
243        let u64_some_zero: Option<u64> = Some(0);
244        let u64_some_zero: &dyn AsByteVec = &u64_some_zero;
245        assert_eq!(
246            u64_some_zero.as_byte_vec(),
247            &[&[1][..], &[0, 0, 0, 0, 0, 0, 0, 0][..]]
248        );
249
250        let u128_none: Option<u128> = None;
251        let u128_none: &dyn AsByteVec = &u128_none;
252        assert_eq!(u128_none.as_byte_vec(), &[&[0]]);
253
254        let u128_some_zero: Option<u128> = Some(0);
255        let u128_some_zero: &dyn AsByteVec = &u128_some_zero;
256        assert_eq!(
257            u128_some_zero.as_byte_vec(),
258            &[
259                &[1][..],
260                &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0][..]
261            ]
262        );
263    }
264
265    #[test]
266    fn test_as_byte_vec_array() {
267        let arr: [u8; 0] = [];
268        let arr: &dyn AsByteVec = &arr;
269        assert_eq!(arr.as_byte_vec(), &[&[]]);
270
271        let arr: [u8; 1] = [255];
272        let arr: &dyn AsByteVec = &arr;
273        assert_eq!(arr.as_byte_vec(), &[&[255]]);
274
275        let arr: [u8; 4] = [255, 255, 255, 255];
276        let arr: &dyn AsByteVec = &arr;
277        assert_eq!(arr.as_byte_vec(), &[&[255, 255, 255, 255]]);
278    }
279
280    #[test]
281    fn test_as_byte_vec_string() {
282        let s: &dyn AsByteVec = &"".to_string();
283        assert_eq!(s.as_byte_vec(), &[b""]);
284
285        let s: &dyn AsByteVec = &"foobar".to_string();
286        assert_eq!(s.as_byte_vec(), &[b"foobar"]);
287    }
288}