light_hasher/
to_byte_array.rs1#[cfg(feature = "alloc")]
2use crate::String;
3use crate::{Hasher, HasherError, Poseidon};
4
5pub trait ToByteArray {
6 const NUM_FIELDS: usize;
7 const IS_PRIMITIVE: bool = false;
8 fn to_byte_array(&self) -> Result<[u8; 32], HasherError>;
9}
10
11macro_rules! impl_to_byte_array_for_integer_type {
12 ($int_ty:ty) => {
13 impl ToByteArray for $int_ty {
14 const IS_PRIMITIVE: bool = true;
15 const NUM_FIELDS: usize = 1;
16
17 fn to_byte_array(&self) -> Result<[u8; 32], HasherError> {
19 let bytes = self.to_be_bytes();
20 let mut result = [0; 32];
21 result[32 - core::mem::size_of::<$int_ty>()..].copy_from_slice(&bytes);
22 Ok(result)
23 }
24 }
25 };
26}
27
28impl<T: ToByteArray> ToByteArray for Option<T> {
29 const NUM_FIELDS: usize = 1;
30
31 fn to_byte_array(&self) -> Result<[u8; 32], HasherError> {
35 if let Some(value) = &self {
36 let byte_array = if T::IS_PRIMITIVE {
37 let mut byte_array = value.to_byte_array()?;
38 byte_array[32 - core::mem::size_of::<T>() - 1] = 1;
40 byte_array
41 } else {
42 let byte_array = value.to_byte_array()?;
43 Poseidon::hash(byte_array.as_slice())?
44 };
45 Ok(byte_array)
46 } else {
47 Ok([0; 32])
48 }
49 }
50}
51
52impl ToByteArray for bool {
53 const NUM_FIELDS: usize = 1;
54 const IS_PRIMITIVE: bool = true;
55
56 fn to_byte_array(&self) -> Result<[u8; 32], HasherError> {
58 let mut bytes = [0u8; 32];
59 bytes[31] = *self as u8;
60 Ok(bytes)
61 }
62}
63
64impl_to_byte_array_for_integer_type!(i8);
65impl_to_byte_array_for_integer_type!(u8);
66impl_to_byte_array_for_integer_type!(i16);
67impl_to_byte_array_for_integer_type!(u16);
68impl_to_byte_array_for_integer_type!(i32);
69impl_to_byte_array_for_integer_type!(u32);
70impl_to_byte_array_for_integer_type!(i64);
71impl_to_byte_array_for_integer_type!(u64);
72impl_to_byte_array_for_integer_type!(i128);
73impl_to_byte_array_for_integer_type!(u128);
74
75#[cfg(feature = "zero-copy")]
77macro_rules! impl_to_byte_array_for_zero_copy_type {
78 ($zero_copy_type:ty, $primitive_type:ty) => {
79 impl ToByteArray for $zero_copy_type {
80 const IS_PRIMITIVE: bool = true;
81 const NUM_FIELDS: usize = 1;
82
83 fn to_byte_array(&self) -> Result<[u8; 32], HasherError> {
84 let value: $primitive_type = (*self).into();
85 value.to_byte_array()
86 }
87 }
88 };
89}
90
91#[cfg(feature = "zero-copy")]
93impl_to_byte_array_for_zero_copy_type!(zerocopy::little_endian::U16, u16);
94#[cfg(feature = "zero-copy")]
95impl_to_byte_array_for_zero_copy_type!(zerocopy::little_endian::U32, u32);
96#[cfg(feature = "zero-copy")]
97impl_to_byte_array_for_zero_copy_type!(zerocopy::little_endian::U64, u64);
98#[cfg(feature = "zero-copy")]
99impl_to_byte_array_for_zero_copy_type!(zerocopy::little_endian::I16, i16);
100#[cfg(feature = "zero-copy")]
101impl_to_byte_array_for_zero_copy_type!(zerocopy::little_endian::I32, i32);
102#[cfg(feature = "zero-copy")]
103impl_to_byte_array_for_zero_copy_type!(zerocopy::little_endian::I64, i64);
104
105#[macro_export]
112macro_rules! impl_to_byte_array_for_array {
113 ($t:ty, $( $len:literal => [$($index:tt),*] );* $(;)?) => {
115 $(
116 impl ToByteArray for [$t; $len] {
117 const NUM_FIELDS: usize = $len;
118 const IS_PRIMITIVE: bool = false;
119
120 fn to_byte_array(&self) -> Result<[u8; 32], HasherError> {
121 let arrays = [$(self[$index].to_byte_array()?),*];
122 let slices = [$(arrays[$index].as_slice()),*];
123 Poseidon::hashv(&slices)
124 }
125 }
126 )*
127 }
128}
129
130macro_rules! impl_to_byte_array_for_u8_array {
132 ($size:expr) => {
133 impl ToByteArray for [u8; $size] {
134 const NUM_FIELDS: usize = 1;
135
136 fn to_byte_array(&self) -> Result<[u8; 32], HasherError> {
137 let mut result = [0u8; 32];
138 result[32 - $size..].copy_from_slice(self.as_slice());
139 Ok(result)
140 }
141 }
142 };
143}
144
145impl_to_byte_array_for_u8_array!(1);
147impl_to_byte_array_for_u8_array!(2);
148impl_to_byte_array_for_u8_array!(4);
149impl_to_byte_array_for_u8_array!(5);
150impl_to_byte_array_for_u8_array!(6);
151impl_to_byte_array_for_u8_array!(7);
152impl_to_byte_array_for_u8_array!(8);
153impl_to_byte_array_for_u8_array!(9);
154impl_to_byte_array_for_u8_array!(10);
155impl_to_byte_array_for_u8_array!(11);
156impl_to_byte_array_for_u8_array!(12);
157impl_to_byte_array_for_u8_array!(13);
158impl_to_byte_array_for_u8_array!(14);
159impl_to_byte_array_for_u8_array!(15);
160impl_to_byte_array_for_u8_array!(16);
161impl_to_byte_array_for_u8_array!(17);
162impl_to_byte_array_for_u8_array!(18);
163impl_to_byte_array_for_u8_array!(19);
164impl_to_byte_array_for_u8_array!(20);
165impl_to_byte_array_for_u8_array!(21);
166impl_to_byte_array_for_u8_array!(22);
167impl_to_byte_array_for_u8_array!(23);
168impl_to_byte_array_for_u8_array!(24);
169impl_to_byte_array_for_u8_array!(25);
170impl_to_byte_array_for_u8_array!(26);
171impl_to_byte_array_for_u8_array!(27);
172impl_to_byte_array_for_u8_array!(28);
173impl_to_byte_array_for_u8_array!(29);
174impl_to_byte_array_for_u8_array!(30);
175impl_to_byte_array_for_u8_array!(31);
176
177#[cfg(feature = "alloc")]
178impl ToByteArray for String {
179 const NUM_FIELDS: usize = 1;
180
181 fn to_byte_array(&self) -> Result<[u8; 32], HasherError> {
184 let bytes = self.as_bytes();
185 let mut result = [0u8; 32];
186 let byte_len = bytes.len();
187 if byte_len > 31 {
188 return Err(HasherError::InvalidInputLength(31, bytes.len()));
189 }
190 result[32 - byte_len..].copy_from_slice(bytes);
191 Ok(result)
192 }
193}