use core::convert::TryInto;
pub struct Checksum {
pub value: [u64; 4], }
pub trait StructuralIntegrity {
fn calculate_structural_checksum(&self) -> u64;
}
impl Checksum {
pub fn calculate(data: &[u8]) -> Self {
let hash = blake3::hash(data);
let bytes = hash.as_bytes();
let (a, rest) = bytes.split_at(8);
let (b, rest) = rest.split_at(8);
let (c, d) = rest.split_at(8);
debug_assert_eq!(a.len(), 8);
debug_assert_eq!(b.len(), 8);
debug_assert_eq!(c.len(), 8);
debug_assert_eq!(d.len(), 8);
let v0 = u64::from_le_bytes([a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7]]);
let v1 = u64::from_le_bytes([b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7]]);
let v2 = u64::from_le_bytes([c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7]]);
let v3 = u64::from_le_bytes([d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7]]);
Checksum {
value: [v0, v1, v2, v3],
}
}
pub fn calculate_fletcher4(data: &[u8]) -> Self {
Self::calculate(data)
}
pub fn matches(&self, other: &[u64; 4]) -> bool {
self.value == *other
}
pub fn first(&self) -> u64 {
self.value.first().copied().unwrap_or(0)
}
pub fn second(&self) -> u64 {
self.value.get(1).copied().unwrap_or(0)
}
pub fn third(&self) -> u64 {
self.value.get(2).copied().unwrap_or(0)
}
pub fn fourth(&self) -> u64 {
self.value.get(3).copied().unwrap_or(0)
}
pub fn to_u64_array(&self) -> [u64; 4] {
self.value
}
pub fn as_bytes(&self) -> [u8; 32] {
let mut bytes = [0u8; 32];
let (chunk0, rest) = bytes.split_at_mut(8);
let (chunk1, rest) = rest.split_at_mut(8);
let (chunk2, chunk3) = rest.split_at_mut(8);
chunk0.copy_from_slice(&self.first().to_le_bytes());
chunk1.copy_from_slice(&self.second().to_le_bytes());
chunk2.copy_from_slice(&self.third().to_le_bytes());
chunk3.copy_from_slice(&self.fourth().to_le_bytes());
bytes
}
}