1use crate::HasherError;
2
3pub trait DataHasher {
4 fn hash<H: crate::Hasher>(&self) -> Result<[u8; 32], HasherError>;
5}
6
7macro_rules! impl_data_hasher_for_array {
8 ($(
9 $len:literal => [$($index:tt),* $(,)?]
11 )*) => {
12 $(
13 impl<T: DataHasher + Default> DataHasher for [T; $len] {
14 fn hash<H: crate::Hasher>(&self) -> Result<[u8; 32], HasherError> {
15 H::hashv(&[$( &self[$index].hash::<H>()?.as_slice() ),*])
17 }
18 }
19 )*
20 }
21}
22
23impl_data_hasher_for_array! {
24 1 => [0]
25}
26impl_data_hasher_for_array! {
27 2 => [0, 1]
28}
29impl_data_hasher_for_array! {
30 3 => [0, 1, 2]
31}
32impl_data_hasher_for_array! {
33 4 => [0, 1, 2, 3]
34}
35impl_data_hasher_for_array! {
36 5 => [0, 1, 2, 3, 4]
37}
38impl_data_hasher_for_array! {
39 6 => [0, 1, 2, 3, 4, 5]
40}
41impl_data_hasher_for_array! {
42 7 => [0, 1, 2, 3, 4, 5, 6]
43}
44impl_data_hasher_for_array! {
45 8 => [0, 1, 2, 3, 4, 5, 6, 7]
46}
47impl_data_hasher_for_array! {
48 9 => [0, 1, 2, 3, 4, 5, 6, 7, 8]
49}
50impl_data_hasher_for_array! {
51 10 => [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
52}
53impl_data_hasher_for_array! {
54 11 => [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
55}
56impl_data_hasher_for_array! {
57 12 => [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
58}
59
60#[cfg(test)]
61mod tests {
62 use super::*;
63 use crate::{Hasher, Poseidon};
64
65 #[derive(Default, Clone)]
67 struct TestHashable {
68 value: u8,
69 }
70
71 impl TestHashable {
72 fn new(value: u8) -> Self {
73 Self { value }
74 }
75 }
76
77 impl DataHasher for TestHashable {
78 fn hash<H: Hasher>(&self) -> Result<[u8; 32], HasherError> {
79 let mut result = [0u8; 32];
81 result[31] = self.value;
82 Ok(result)
83 }
84 }
85
86 #[test]
87 fn test_data_hasher_array_1() {
88 let arr = [TestHashable::new(42)];
89 let hash_result = arr.hash::<Poseidon>().unwrap();
90
91 let expected_input = [
93 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
94 0, 0, 42,
95 ];
96 let expected_hash = Poseidon::hash(&expected_input).unwrap();
97
98 assert_eq!(hash_result, expected_hash);
99 }
100
101 #[test]
102 fn test_data_hasher_array_2() {
103 let arr = [TestHashable::new(1), TestHashable::new(2)];
104 let hash_result = arr.hash::<Poseidon>().unwrap();
105
106 let hash1 = [0u8; 32];
108 let hash2 = [0u8; 32];
109
110 let mut hash1 = hash1;
111 hash1[31] = 1;
112
113 let mut hash2 = hash2;
114 hash2[31] = 2;
115
116 let expected_hash = Poseidon::hashv(&[&hash1, &hash2]).unwrap();
118
119 assert_eq!(hash_result, expected_hash);
120 }
121
122 #[test]
123 fn test_data_hasher_array_multiple_sizes() {
124 for size in 1..=12 {
126 let mut array = Vec::with_capacity(size);
127 for i in 0..size {
128 array.push(TestHashable::new(i as u8));
129 }
130
131 let array_slice = array.as_slice();
133
134 let mut expected_inputs = Vec::with_capacity(size);
136 for i in 0..size {
137 let mut hash = [0u8; 32];
138 hash[31] = i as u8;
139 expected_inputs.push(hash);
140 }
141
142 match size {
144 1 => {
145 let arr: [TestHashable; 1] = [array_slice[0].clone()];
146 let hash_result = arr.hash::<Poseidon>().unwrap();
147
148 let expected_slices: Vec<&[u8]> =
149 expected_inputs.iter().map(|h| h.as_slice()).collect();
150 let expected_hash = Poseidon::hashv(&expected_slices).unwrap();
151
152 assert_eq!(hash_result, expected_hash);
153 }
154 2 => {
155 let arr: [TestHashable; 2] = [array_slice[0].clone(), array_slice[1].clone()];
156 let hash_result = arr.hash::<Poseidon>().unwrap();
157
158 let expected_slices: Vec<&[u8]> =
159 expected_inputs.iter().map(|h| h.as_slice()).collect();
160 let expected_hash = Poseidon::hashv(&expected_slices).unwrap();
161
162 assert_eq!(hash_result, expected_hash);
163 }
164 3 => {
165 let arr: [TestHashable; 3] = [
166 array_slice[0].clone(),
167 array_slice[1].clone(),
168 array_slice[2].clone(),
169 ];
170 let hash_result = arr.hash::<Poseidon>().unwrap();
171
172 let expected_slices: Vec<&[u8]> =
173 expected_inputs.iter().map(|h| h.as_slice()).collect();
174 let expected_hash = Poseidon::hashv(&expected_slices).unwrap();
175
176 assert_eq!(hash_result, expected_hash);
177 }
178 4 => {
180 let arr: [TestHashable; 4] = [
181 array_slice[0].clone(),
182 array_slice[1].clone(),
183 array_slice[2].clone(),
184 array_slice[3].clone(),
185 ];
186 let hash_result = arr.hash::<Poseidon>().unwrap();
187
188 let expected_slices: Vec<&[u8]> =
189 expected_inputs.iter().map(|h| h.as_slice()).collect();
190 let expected_hash = Poseidon::hashv(&expected_slices).unwrap();
191
192 assert_eq!(hash_result, expected_hash);
193 }
194 _ => {
195 }
198 }
199 }
200 }
201}