1use std::ops::{Deref, DerefMut};
27
28use crate::crypto::Hash;
29
30pub const CACHE_LINE_SIZE: usize = 64;
32
33#[repr(C, align(64))]
38#[derive(Clone, Copy, PartialEq, Eq)]
39pub struct AlignedHash {
40 hash: Hash,
41 _padding: [u8; 32], }
43
44impl AlignedHash {
45 #[inline]
47 pub const fn new(hash: Hash) -> Self {
48 Self {
49 hash,
50 _padding: [0; 32],
51 }
52 }
53
54 #[inline]
56 pub const fn zero() -> Self {
57 Self::new(Hash::ZERO)
58 }
59
60 #[inline]
62 pub const fn inner(&self) -> &Hash {
63 &self.hash
64 }
65
66 #[inline]
68 pub fn inner_mut(&mut self) -> &mut Hash {
69 &mut self.hash
70 }
71
72 #[inline]
74 pub fn into_inner(self) -> Hash {
75 self.hash
76 }
77}
78
79impl From<Hash> for AlignedHash {
80 #[inline]
81 fn from(hash: Hash) -> Self {
82 Self::new(hash)
83 }
84}
85
86impl From<AlignedHash> for Hash {
87 #[inline]
88 fn from(aligned: AlignedHash) -> Self {
89 aligned.hash
90 }
91}
92
93impl Deref for AlignedHash {
94 type Target = Hash;
95
96 #[inline]
97 fn deref(&self) -> &Self::Target {
98 &self.hash
99 }
100}
101
102impl DerefMut for AlignedHash {
103 #[inline]
104 fn deref_mut(&mut self) -> &mut Self::Target {
105 &mut self.hash
106 }
107}
108
109impl std::fmt::Debug for AlignedHash {
110 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
111 f.debug_tuple("AlignedHash").field(&self.hash).finish()
112 }
113}
114
115#[repr(C, align(64))]
121#[derive(Clone)]
122pub struct AlignedHashArray<const N: usize> {
123 hashes: [Hash; N],
124}
125
126impl<const N: usize> AlignedHashArray<N> {
127 #[inline]
129 pub const fn new() -> Self {
130 Self {
131 hashes: [Hash::ZERO; N],
132 }
133 }
134
135 #[inline]
137 pub const fn from_array(hashes: [Hash; N]) -> Self {
138 Self { hashes }
139 }
140
141 #[inline]
143 pub fn get(&self, index: usize) -> Option<&Hash> {
144 self.hashes.get(index)
145 }
146
147 #[inline]
149 pub fn set(&mut self, index: usize, hash: Hash) {
150 if index < N {
151 self.hashes[index] = hash;
152 }
153 }
154
155 #[inline]
157 pub const fn as_array(&self) -> &[Hash; N] {
158 &self.hashes
159 }
160
161 #[inline]
163 pub fn as_array_mut(&mut self) -> &mut [Hash; N] {
164 &mut self.hashes
165 }
166
167 #[inline]
169 pub fn as_ptr(&self) -> *const Hash {
170 self.hashes.as_ptr()
171 }
172
173 #[inline]
175 pub fn as_mut_ptr(&mut self) -> *mut Hash {
176 self.hashes.as_mut_ptr()
177 }
178
179 #[inline]
181 pub fn as_bytes_ptr(&self) -> *const u8 {
182 self.hashes.as_ptr() as *const u8
183 }
184
185 #[inline]
187 pub fn as_slice(&self) -> &[Hash] {
188 &self.hashes
189 }
190
191 #[inline]
193 pub fn as_mut_slice(&mut self) -> &mut [Hash] {
194 &mut self.hashes
195 }
196
197 #[inline]
199 pub fn iter(&self) -> impl Iterator<Item = &Hash> {
200 self.hashes.iter()
201 }
202
203 #[inline]
205 pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut Hash> {
206 self.hashes.iter_mut()
207 }
208}
209
210impl<const N: usize> Default for AlignedHashArray<N> {
211 fn default() -> Self {
212 Self::new()
213 }
214}
215
216impl<const N: usize> Deref for AlignedHashArray<N> {
217 type Target = [Hash; N];
218
219 #[inline]
220 fn deref(&self) -> &Self::Target {
221 &self.hashes
222 }
223}
224
225impl<const N: usize> DerefMut for AlignedHashArray<N> {
226 #[inline]
227 fn deref_mut(&mut self) -> &mut Self::Target {
228 &mut self.hashes
229 }
230}
231
232impl<const N: usize> std::fmt::Debug for AlignedHashArray<N> {
233 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
234 f.debug_struct("AlignedHashArray")
235 .field("len", &N)
236 .field("hashes", &self.hashes)
237 .finish()
238 }
239}
240
241#[repr(C, align(64))]
247#[derive(Clone, Copy)]
248pub struct CacheLinePadded<T> {
249 value: T,
250}
251
252impl<T> CacheLinePadded<T> {
253 #[inline]
255 pub const fn new(value: T) -> Self {
256 Self { value }
257 }
258
259 #[inline]
261 pub const fn inner(&self) -> &T {
262 &self.value
263 }
264
265 #[inline]
267 pub fn inner_mut(&mut self) -> &mut T {
268 &mut self.value
269 }
270
271 #[inline]
273 pub fn into_inner(self) -> T {
274 self.value
275 }
276}
277
278impl<T> Deref for CacheLinePadded<T> {
279 type Target = T;
280
281 #[inline]
282 fn deref(&self) -> &Self::Target {
283 &self.value
284 }
285}
286
287impl<T> DerefMut for CacheLinePadded<T> {
288 #[inline]
289 fn deref_mut(&mut self) -> &mut Self::Target {
290 &mut self.value
291 }
292}
293
294impl<T: Default> Default for CacheLinePadded<T> {
295 fn default() -> Self {
296 Self::new(T::default())
297 }
298}
299
300impl<T: std::fmt::Debug> std::fmt::Debug for CacheLinePadded<T> {
301 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
302 f.debug_tuple("CacheLinePadded").field(&self.value).finish()
303 }
304}
305
306#[cfg(test)]
307mod tests {
308 use super::*;
309 use crate::hash;
310
311 #[test]
312 fn test_aligned_hash_size_and_alignment() {
313 assert_eq!(std::mem::size_of::<AlignedHash>(), 64);
314 assert_eq!(std::mem::align_of::<AlignedHash>(), 64);
315 }
316
317 #[test]
318 fn test_aligned_hash_array_alignment() {
319 assert_eq!(std::mem::align_of::<AlignedHashArray<8>>(), 64);
320
321 assert_eq!(std::mem::size_of::<AlignedHashArray<8>>(), 256);
323 }
324
325 #[test]
326 fn test_cache_line_padded_alignment() {
327 assert_eq!(std::mem::align_of::<CacheLinePadded<u64>>(), 64);
328
329 assert!(std::mem::size_of::<CacheLinePadded<u64>>() >= 64);
331 }
332
333 #[test]
334 fn test_aligned_hash_operations() {
335 let h = hash(b"test");
336 let aligned = AlignedHash::new(h);
337
338 assert_eq!(*aligned.inner(), h);
339 assert_eq!(aligned.into_inner(), h);
340 }
341
342 #[test]
343 fn test_aligned_hash_array_operations() {
344 let mut arr = AlignedHashArray::<4>::new();
345
346 let h0 = hash(b"zero");
347 let h1 = hash(b"one");
348 let h2 = hash(b"two");
349 let h3 = hash(b"three");
350
351 arr.set(0, h0);
352 arr.set(1, h1);
353 arr.set(2, h2);
354 arr.set(3, h3);
355
356 assert_eq!(arr.get(0), Some(&h0));
357 assert_eq!(arr.get(1), Some(&h1));
358 assert_eq!(arr.get(2), Some(&h2));
359 assert_eq!(arr.get(3), Some(&h3));
360 assert_eq!(arr.get(4), None);
361 }
362
363 #[test]
364 fn test_alignment_is_correct_at_runtime() {
365 let aligned = AlignedHash::new(hash(b"test"));
366 let ptr = &aligned as *const AlignedHash as usize;
367 assert_eq!(ptr % 64, 0, "AlignedHash should be 64-byte aligned");
368
369 let arr = AlignedHashArray::<8>::new();
370 let arr_ptr = &arr as *const AlignedHashArray<8> as usize;
371 assert_eq!(
372 arr_ptr % 64,
373 0,
374 "AlignedHashArray should be 64-byte aligned"
375 );
376 }
377
378 #[test]
379 fn test_heap_allocation_alignment() {
380 let boxed = Box::new(AlignedHash::new(hash(b"test")));
382 let ptr = boxed.as_ref() as *const AlignedHash as usize;
383 assert_eq!(ptr % 64, 0, "Boxed AlignedHash should be 64-byte aligned");
384
385 let mut vec = Vec::with_capacity(4);
387 for i in 0..4u8 {
388 vec.push(AlignedHash::new(hash(&[i])));
389 }
390 for (i, aligned) in vec.iter().enumerate() {
391 let ptr = aligned as *const AlignedHash as usize;
392 assert_eq!(ptr % 64, 0, "Vec element {} should be 64-byte aligned", i);
393 }
394 }
395}