use std::ops::{Deref, DerefMut};
use crate::crypto::Hash;
pub const CACHE_LINE_SIZE: usize = 64;
#[repr(C, align(64))]
#[derive(Clone, Copy, PartialEq, Eq)]
pub struct AlignedHash {
hash: Hash,
_padding: [u8; 32], }
impl AlignedHash {
#[inline]
pub const fn new(hash: Hash) -> Self {
Self {
hash,
_padding: [0; 32],
}
}
#[inline]
pub const fn zero() -> Self {
Self::new(Hash::ZERO)
}
#[inline]
pub const fn inner(&self) -> &Hash {
&self.hash
}
#[inline]
pub fn inner_mut(&mut self) -> &mut Hash {
&mut self.hash
}
#[inline]
pub fn into_inner(self) -> Hash {
self.hash
}
}
impl From<Hash> for AlignedHash {
#[inline]
fn from(hash: Hash) -> Self {
Self::new(hash)
}
}
impl From<AlignedHash> for Hash {
#[inline]
fn from(aligned: AlignedHash) -> Self {
aligned.hash
}
}
impl Deref for AlignedHash {
type Target = Hash;
#[inline]
fn deref(&self) -> &Self::Target {
&self.hash
}
}
impl DerefMut for AlignedHash {
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.hash
}
}
impl std::fmt::Debug for AlignedHash {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_tuple("AlignedHash").field(&self.hash).finish()
}
}
#[repr(C, align(64))]
#[derive(Clone)]
pub struct AlignedHashArray<const N: usize> {
hashes: [Hash; N],
}
impl<const N: usize> AlignedHashArray<N> {
#[inline]
pub const fn new() -> Self {
Self {
hashes: [Hash::ZERO; N],
}
}
#[inline]
pub const fn from_array(hashes: [Hash; N]) -> Self {
Self { hashes }
}
#[inline]
pub fn get(&self, index: usize) -> Option<&Hash> {
self.hashes.get(index)
}
#[inline]
pub fn set(&mut self, index: usize, hash: Hash) {
if index < N {
self.hashes[index] = hash;
}
}
#[inline]
pub const fn as_array(&self) -> &[Hash; N] {
&self.hashes
}
#[inline]
pub fn as_array_mut(&mut self) -> &mut [Hash; N] {
&mut self.hashes
}
#[inline]
pub fn as_ptr(&self) -> *const Hash {
self.hashes.as_ptr()
}
#[inline]
pub fn as_mut_ptr(&mut self) -> *mut Hash {
self.hashes.as_mut_ptr()
}
#[inline]
pub fn as_bytes_ptr(&self) -> *const u8 {
self.hashes.as_ptr() as *const u8
}
#[inline]
pub fn as_slice(&self) -> &[Hash] {
&self.hashes
}
#[inline]
pub fn as_mut_slice(&mut self) -> &mut [Hash] {
&mut self.hashes
}
#[inline]
pub fn iter(&self) -> impl Iterator<Item = &Hash> {
self.hashes.iter()
}
#[inline]
pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut Hash> {
self.hashes.iter_mut()
}
}
impl<const N: usize> Default for AlignedHashArray<N> {
fn default() -> Self {
Self::new()
}
}
impl<const N: usize> Deref for AlignedHashArray<N> {
type Target = [Hash; N];
#[inline]
fn deref(&self) -> &Self::Target {
&self.hashes
}
}
impl<const N: usize> DerefMut for AlignedHashArray<N> {
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.hashes
}
}
impl<const N: usize> std::fmt::Debug for AlignedHashArray<N> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("AlignedHashArray")
.field("len", &N)
.field("hashes", &self.hashes)
.finish()
}
}
#[repr(C, align(64))]
#[derive(Clone, Copy)]
pub struct CacheLinePadded<T> {
value: T,
}
impl<T> CacheLinePadded<T> {
#[inline]
pub const fn new(value: T) -> Self {
Self { value }
}
#[inline]
pub const fn inner(&self) -> &T {
&self.value
}
#[inline]
pub fn inner_mut(&mut self) -> &mut T {
&mut self.value
}
#[inline]
pub fn into_inner(self) -> T {
self.value
}
}
impl<T> Deref for CacheLinePadded<T> {
type Target = T;
#[inline]
fn deref(&self) -> &Self::Target {
&self.value
}
}
impl<T> DerefMut for CacheLinePadded<T> {
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.value
}
}
impl<T: Default> Default for CacheLinePadded<T> {
fn default() -> Self {
Self::new(T::default())
}
}
impl<T: std::fmt::Debug> std::fmt::Debug for CacheLinePadded<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_tuple("CacheLinePadded").field(&self.value).finish()
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::hash;
#[test]
fn test_aligned_hash_size_and_alignment() {
assert_eq!(std::mem::size_of::<AlignedHash>(), 64);
assert_eq!(std::mem::align_of::<AlignedHash>(), 64);
}
#[test]
fn test_aligned_hash_array_alignment() {
assert_eq!(std::mem::align_of::<AlignedHashArray<8>>(), 64);
assert_eq!(std::mem::size_of::<AlignedHashArray<8>>(), 256);
}
#[test]
fn test_cache_line_padded_alignment() {
assert_eq!(std::mem::align_of::<CacheLinePadded<u64>>(), 64);
assert!(std::mem::size_of::<CacheLinePadded<u64>>() >= 64);
}
#[test]
fn test_aligned_hash_operations() {
let h = hash(b"test");
let aligned = AlignedHash::new(h);
assert_eq!(*aligned.inner(), h);
assert_eq!(aligned.into_inner(), h);
}
#[test]
fn test_aligned_hash_array_operations() {
let mut arr = AlignedHashArray::<4>::new();
let h0 = hash(b"zero");
let h1 = hash(b"one");
let h2 = hash(b"two");
let h3 = hash(b"three");
arr.set(0, h0);
arr.set(1, h1);
arr.set(2, h2);
arr.set(3, h3);
assert_eq!(arr.get(0), Some(&h0));
assert_eq!(arr.get(1), Some(&h1));
assert_eq!(arr.get(2), Some(&h2));
assert_eq!(arr.get(3), Some(&h3));
assert_eq!(arr.get(4), None);
}
#[test]
fn test_alignment_is_correct_at_runtime() {
let aligned = AlignedHash::new(hash(b"test"));
let ptr = &aligned as *const AlignedHash as usize;
assert_eq!(ptr % 64, 0, "AlignedHash should be 64-byte aligned");
let arr = AlignedHashArray::<8>::new();
let arr_ptr = &arr as *const AlignedHashArray<8> as usize;
assert_eq!(
arr_ptr % 64,
0,
"AlignedHashArray should be 64-byte aligned"
);
}
#[test]
fn test_heap_allocation_alignment() {
let boxed = Box::new(AlignedHash::new(hash(b"test")));
let ptr = boxed.as_ref() as *const AlignedHash as usize;
assert_eq!(ptr % 64, 0, "Boxed AlignedHash should be 64-byte aligned");
let mut vec = Vec::with_capacity(4);
for i in 0..4u8 {
vec.push(AlignedHash::new(hash(&[i])));
}
for (i, aligned) in vec.iter().enumerate() {
let ptr = aligned as *const AlignedHash as usize;
assert_eq!(ptr % 64, 0, "Vec element {} should be 64-byte aligned", i);
}
}
}