1use crate::{Hasher, HasherError, Poseidon};
2
3pub trait ToByteArray {
4 const NUM_FIELDS: usize;
5 const IS_PRIMITIVE: bool = false;
6 fn to_byte_array(&self) -> Result<[u8; 32], HasherError>;
7}
8
9macro_rules! impl_to_byte_array_for_integer_type {
10 ($int_ty:ty) => {
11 impl ToByteArray for $int_ty {
12 const IS_PRIMITIVE: bool = true;
13 const NUM_FIELDS: usize = 1;
14
15 fn to_byte_array(&self) -> Result<[u8; 32], HasherError> {
17 let bytes = self.to_be_bytes();
18 let mut result = [0; 32];
19 result[32 - std::mem::size_of::<$int_ty>()..].copy_from_slice(&bytes);
20 Ok(result)
21 }
22 }
23 };
24}
25
26impl<T: ToByteArray> ToByteArray for Option<T> {
27 const NUM_FIELDS: usize = 1;
28
29 fn to_byte_array(&self) -> Result<[u8; 32], HasherError> {
33 if let Some(value) = &self {
34 let byte_array = if T::IS_PRIMITIVE {
35 let mut byte_array = value.to_byte_array()?;
36 byte_array[32 - std::mem::size_of::<T>() - 1] = 1;
38 byte_array
39 } else {
40 let byte_array = value.to_byte_array()?;
41 Poseidon::hash(byte_array.as_slice())?
42 };
43 Ok(byte_array)
44 } else {
45 Ok([0; 32])
46 }
47 }
48}
49
50impl ToByteArray for bool {
51 const NUM_FIELDS: usize = 1;
52 const IS_PRIMITIVE: bool = true;
53
54 fn to_byte_array(&self) -> Result<[u8; 32], HasherError> {
56 let mut bytes = [0u8; 32];
57 bytes[31] = *self as u8;
58 Ok(bytes)
59 }
60}
61
62impl_to_byte_array_for_integer_type!(i8);
63impl_to_byte_array_for_integer_type!(u8);
64impl_to_byte_array_for_integer_type!(i16);
65impl_to_byte_array_for_integer_type!(u16);
66impl_to_byte_array_for_integer_type!(i32);
67impl_to_byte_array_for_integer_type!(u32);
68impl_to_byte_array_for_integer_type!(i64);
69impl_to_byte_array_for_integer_type!(u64);
70impl_to_byte_array_for_integer_type!(i128);
71impl_to_byte_array_for_integer_type!(u128);
72
73#[cfg(feature = "zero-copy")]
75macro_rules! impl_to_byte_array_for_zero_copy_type {
76 ($zero_copy_type:ty, $primitive_type:ty) => {
77 impl ToByteArray for $zero_copy_type {
78 const IS_PRIMITIVE: bool = true;
79 const NUM_FIELDS: usize = 1;
80
81 fn to_byte_array(&self) -> Result<[u8; 32], HasherError> {
82 let value: $primitive_type = (*self).into();
83 value.to_byte_array()
84 }
85 }
86 };
87}
88
89#[cfg(feature = "zero-copy")]
91impl_to_byte_array_for_zero_copy_type!(zerocopy::little_endian::U16, u16);
92#[cfg(feature = "zero-copy")]
93impl_to_byte_array_for_zero_copy_type!(zerocopy::little_endian::U32, u32);
94#[cfg(feature = "zero-copy")]
95impl_to_byte_array_for_zero_copy_type!(zerocopy::little_endian::U64, u64);
96#[cfg(feature = "zero-copy")]
97impl_to_byte_array_for_zero_copy_type!(zerocopy::little_endian::I16, i16);
98#[cfg(feature = "zero-copy")]
99impl_to_byte_array_for_zero_copy_type!(zerocopy::little_endian::I32, i32);
100#[cfg(feature = "zero-copy")]
101impl_to_byte_array_for_zero_copy_type!(zerocopy::little_endian::I64, i64);
102
103#[macro_export]
110macro_rules! impl_to_byte_array_for_array {
111 ($t:ty, $( $len:literal => [$($index:tt),*] );* $(;)?) => {
113 $(
114 impl ToByteArray for [$t; $len] {
115 const NUM_FIELDS: usize = $len;
116 const IS_PRIMITIVE: bool = false;
117
118 fn to_byte_array(&self) -> Result<[u8; 32], HasherError> {
119 let arrays = [$(self[$index].to_byte_array()?),*];
120 let slices = [$(arrays[$index].as_slice()),*];
121 Poseidon::hashv(&slices)
122 }
123 }
124 )*
125 }
126}
127
128macro_rules! impl_to_byte_array_for_u8_array {
130 ($size:expr) => {
131 impl ToByteArray for [u8; $size] {
132 const NUM_FIELDS: usize = 1;
133
134 fn to_byte_array(&self) -> Result<[u8; 32], HasherError> {
135 let mut result = [0u8; 32];
136 result[32 - $size..].copy_from_slice(self.as_slice());
137 Ok(result)
138 }
139 }
140 };
141}
142
143impl_to_byte_array_for_u8_array!(1);
145impl_to_byte_array_for_u8_array!(2);
146impl_to_byte_array_for_u8_array!(4);
147impl_to_byte_array_for_u8_array!(5);
148impl_to_byte_array_for_u8_array!(6);
149impl_to_byte_array_for_u8_array!(7);
150impl_to_byte_array_for_u8_array!(8);
151impl_to_byte_array_for_u8_array!(9);
152impl_to_byte_array_for_u8_array!(10);
153impl_to_byte_array_for_u8_array!(11);
154impl_to_byte_array_for_u8_array!(12);
155impl_to_byte_array_for_u8_array!(13);
156impl_to_byte_array_for_u8_array!(14);
157impl_to_byte_array_for_u8_array!(15);
158impl_to_byte_array_for_u8_array!(16);
159impl_to_byte_array_for_u8_array!(17);
160impl_to_byte_array_for_u8_array!(18);
161impl_to_byte_array_for_u8_array!(19);
162impl_to_byte_array_for_u8_array!(20);
163impl_to_byte_array_for_u8_array!(21);
164impl_to_byte_array_for_u8_array!(22);
165impl_to_byte_array_for_u8_array!(23);
166impl_to_byte_array_for_u8_array!(24);
167impl_to_byte_array_for_u8_array!(25);
168impl_to_byte_array_for_u8_array!(26);
169impl_to_byte_array_for_u8_array!(27);
170impl_to_byte_array_for_u8_array!(28);
171impl_to_byte_array_for_u8_array!(29);
172impl_to_byte_array_for_u8_array!(30);
173impl_to_byte_array_for_u8_array!(31);
174
175impl ToByteArray for String {
176 const NUM_FIELDS: usize = 1;
177
178 fn to_byte_array(&self) -> Result<[u8; 32], HasherError> {
181 let bytes = self.as_bytes();
182 let mut result = [0u8; 32];
183 let byte_len = bytes.len();
184 if byte_len > 31 {
185 return Err(HasherError::InvalidInputLength(31, bytes.len()));
186 }
187 result[32 - byte_len..].copy_from_slice(bytes);
188 Ok(result)
189 }
190}
191
192#[cfg(test)]
193mod test {
194 use super::*;
195
196 #[test]
197 fn test_to_byte_array_integers() {
198 let i8_min_result = i8::MIN.to_byte_array().unwrap();
200 let mut expected_i8_min = [0u8; 32];
201 expected_i8_min[31] = 128; assert_eq!(i8_min_result, expected_i8_min);
203
204 let i8_max_result = i8::MAX.to_byte_array().unwrap();
205 let mut expected_i8_max = [0u8; 32];
206 expected_i8_max[31] = 127; assert_eq!(i8_max_result, expected_i8_max);
208
209 let u8_min_result = u8::MIN.to_byte_array().unwrap();
211 let mut expected_u8_min = [0u8; 32];
212 expected_u8_min[31] = 0; assert_eq!(u8_min_result, expected_u8_min);
214
215 let u8_max_result = u8::MAX.to_byte_array().unwrap();
216 let mut expected_u8_max = [0u8; 32];
217 expected_u8_max[31] = 255; assert_eq!(u8_max_result, expected_u8_max);
219
220 let i16_min_result = i16::MIN.to_byte_array().unwrap();
222 let mut expected_i16_min = [0u8; 32];
223 expected_i16_min[30..32].copy_from_slice(&i16::MIN.to_be_bytes()); assert_eq!(i16_min_result, expected_i16_min);
225
226 let i16_max_result = i16::MAX.to_byte_array().unwrap();
227 let mut expected_i16_max = [0u8; 32];
228 expected_i16_max[30..32].copy_from_slice(&i16::MAX.to_be_bytes()); assert_eq!(i16_max_result, expected_i16_max);
230
231 let u16_min_result = u16::MIN.to_byte_array().unwrap();
233 let mut expected_u16_min = [0u8; 32];
234 expected_u16_min[30..32].copy_from_slice(&u16::MIN.to_be_bytes()); assert_eq!(u16_min_result, expected_u16_min);
236
237 let u16_max_result = u16::MAX.to_byte_array().unwrap();
238 let mut expected_u16_max = [0u8; 32];
239 expected_u16_max[30..32].copy_from_slice(&u16::MAX.to_be_bytes()); assert_eq!(u16_max_result, expected_u16_max);
241
242 let i32_min_result = i32::MIN.to_byte_array().unwrap();
244 let mut expected_i32_min = [0u8; 32];
245 expected_i32_min[28..32].copy_from_slice(&i32::MIN.to_be_bytes()); assert_eq!(i32_min_result, expected_i32_min);
247
248 let i32_max_result = i32::MAX.to_byte_array().unwrap();
249 let mut expected_i32_max = [0u8; 32];
250 expected_i32_max[28..32].copy_from_slice(&i32::MAX.to_be_bytes()); assert_eq!(i32_max_result, expected_i32_max);
252
253 let u32_min_result = u32::MIN.to_byte_array().unwrap();
255 let mut expected_u32_min = [0u8; 32];
256 expected_u32_min[28..32].copy_from_slice(&u32::MIN.to_be_bytes()); assert_eq!(u32_min_result, expected_u32_min);
258
259 let u32_max_result = u32::MAX.to_byte_array().unwrap();
260 let mut expected_u32_max = [0u8; 32];
261 expected_u32_max[28..32].copy_from_slice(&u32::MAX.to_be_bytes()); assert_eq!(u32_max_result, expected_u32_max);
263
264 let i64_min_result = i64::MIN.to_byte_array().unwrap();
266 let mut expected_i64_min = [0u8; 32];
267 expected_i64_min[24..32].copy_from_slice(&i64::MIN.to_be_bytes()); assert_eq!(i64_min_result, expected_i64_min);
269
270 let i64_max_result = i64::MAX.to_byte_array().unwrap();
271 let mut expected_i64_max = [0u8; 32];
272 expected_i64_max[24..32].copy_from_slice(&i64::MAX.to_be_bytes()); assert_eq!(i64_max_result, expected_i64_max);
274
275 let u64_min_result = u64::MIN.to_byte_array().unwrap();
277 let mut expected_u64_min = [0u8; 32];
278 expected_u64_min[24..32].copy_from_slice(&u64::MIN.to_be_bytes()); assert_eq!(u64_min_result, expected_u64_min);
280
281 let u64_max_result = u64::MAX.to_byte_array().unwrap();
282 let mut expected_u64_max = [0u8; 32];
283 expected_u64_max[24..32].copy_from_slice(&u64::MAX.to_be_bytes()); assert_eq!(u64_max_result, expected_u64_max);
285
286 let i128_min_result = i128::MIN.to_byte_array().unwrap();
288 let mut expected_i128_min = [0u8; 32];
289 expected_i128_min[16..32].copy_from_slice(&i128::MIN.to_be_bytes()); assert_eq!(i128_min_result, expected_i128_min);
291
292 let i128_max_result = i128::MAX.to_byte_array().unwrap();
293 let mut expected_i128_max = [0u8; 32];
294 expected_i128_max[16..32].copy_from_slice(&i128::MAX.to_be_bytes()); assert_eq!(i128_max_result, expected_i128_max);
296
297 let u128_min_result = u128::MIN.to_byte_array().unwrap();
299 let mut expected_u128_min = [0u8; 32];
300 expected_u128_min[16..32].copy_from_slice(&u128::MIN.to_be_bytes()); assert_eq!(u128_min_result, expected_u128_min);
302
303 let u128_max_result = u128::MAX.to_byte_array().unwrap();
304 let mut expected_u128_max = [0u8; 32];
305 expected_u128_max[16..32].copy_from_slice(&u128::MAX.to_be_bytes()); assert_eq!(u128_max_result, expected_u128_max);
307 }
308
309 #[test]
310 fn test_to_byte_array_primitives() {
311 let bool_false_result = false.to_byte_array().unwrap();
313 let mut expected_bool_false = [0u8; 32];
314 expected_bool_false[31] = 0;
315 assert_eq!(bool_false_result, expected_bool_false);
316
317 let bool_true_result = true.to_byte_array().unwrap();
318 let mut expected_bool_true = [0u8; 32];
319 expected_bool_true[31] = 1;
320 assert_eq!(bool_true_result, expected_bool_true);
321 }
322
323 #[test]
324 fn test_to_byte_array_option() {
325 let u8_none: Option<u8> = None;
330 let u8_none_result = u8_none.to_byte_array().unwrap();
331 assert_eq!(u8_none_result, [0u8; 32]);
332
333 let u8_some_zero: Option<u8> = Some(0);
334 let u8_some_zero_result = u8_some_zero.to_byte_array().unwrap();
335 let mut expected_u8_some_zero = [0u8; 32];
336 expected_u8_some_zero[32 - std::mem::size_of::<u8>() - 1] = 1; assert_eq!(u8_some_zero_result, expected_u8_some_zero);
338
339 let u16_none: Option<u16> = None;
341 let u16_none_result = u16_none.to_byte_array().unwrap();
342 assert_eq!(u16_none_result, [0u8; 32]);
343
344 let u16_some_zero: Option<u16> = Some(0);
345 let u16_some_zero_result = u16_some_zero.to_byte_array().unwrap();
346 let mut expected_u16_some_zero = [0u8; 32];
347 expected_u16_some_zero[32 - std::mem::size_of::<u16>() - 1] = 1; assert_eq!(u16_some_zero_result, expected_u16_some_zero);
349
350 let u32_none: Option<u32> = None;
352 let u32_none_result = u32_none.to_byte_array().unwrap();
353 assert_eq!(u32_none_result, [0u8; 32]);
354
355 let u32_some_zero: Option<u32> = Some(0);
356 let u32_some_zero_result = u32_some_zero.to_byte_array().unwrap();
357 let mut expected_u32_some_zero = [0u8; 32];
358 expected_u32_some_zero[32 - std::mem::size_of::<u32>() - 1] = 1; assert_eq!(u32_some_zero_result, expected_u32_some_zero);
360
361 let u64_none: Option<u64> = None;
363 let u64_none_result = u64_none.to_byte_array().unwrap();
364 assert_eq!(u64_none_result, [0u8; 32]);
365
366 let u64_some_zero: Option<u64> = Some(0);
367 let u64_some_zero_result = u64_some_zero.to_byte_array().unwrap();
368 let mut expected_u64_some_zero = [0u8; 32];
369 expected_u64_some_zero[32 - std::mem::size_of::<u64>() - 1] = 1; assert_eq!(u64_some_zero_result, expected_u64_some_zero);
371
372 let u128_none: Option<u128> = None;
374 let u128_none_result = u128_none.to_byte_array().unwrap();
375 assert_eq!(u128_none_result, [0u8; 32]);
376
377 let u128_some_zero: Option<u128> = Some(0);
378 let u128_some_zero_result = u128_some_zero.to_byte_array().unwrap();
379 let mut expected_u128_some_zero = [0u8; 32];
380 expected_u128_some_zero[32 - std::mem::size_of::<u128>() - 1] = 1; assert_eq!(u128_some_zero_result, expected_u128_some_zero);
382 }
383
384 #[test]
385 fn test_to_byte_array_u8_arrays() {
386 let single_element_arr: [u8; 1] = [255];
388 let result = single_element_arr.to_byte_array().unwrap();
389 let mut expected = [0u8; 32];
390 expected[31] = 255;
391 assert_eq!(result, expected);
392
393 let multi_element_arr: [u8; 4] = [1, 2, 3, 4];
395 let result = multi_element_arr.to_byte_array().unwrap();
396 let mut expected = [0u8; 32];
397 expected[32 - 4..].copy_from_slice(&multi_element_arr);
398 assert_eq!(result, expected);
399
400 let full_arr: [u8; 31] = [
402 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
403 25, 26, 27, 28, 29, 30, 31,
404 ];
405 let result = full_arr.to_byte_array().unwrap();
406 assert_eq!(result[0], 0);
407 assert_eq!(&result[1..], full_arr.as_slice());
408 }
409
410 #[test]
411 fn test_to_byte_array_string() {
412 let empty_string = "".to_string();
414 let result = empty_string.to_byte_array().unwrap();
415 let expected = [0u8; 32];
416 assert_eq!(result, expected);
417
418 let short_string = "foobar".to_string();
420 let result = short_string.to_byte_array().unwrap();
421 let mut expected = [0u8; 32];
422 expected[32 - 6..].copy_from_slice(b"foobar");
423 assert_eq!(result, expected);
424
425 let long_string =
427 "this is a string that is longer than 32 bytes and will be fail".to_string();
428 let byte_len = long_string.len();
429 let result = long_string.to_byte_array();
430 assert_eq!(result, Err(HasherError::InvalidInputLength(31, byte_len)));
431 }
432}