devela/data/hash/
pengy.rs
use crate::{ConstDefault, Hasher};
pub struct HasherPengy {
state: [u64; 4],
seed: u64,
}
impl ConstDefault for HasherPengy {
const DEFAULT: Self = Self { state: [0; 4], seed: 0 };
}
impl Default for HasherPengy {
fn default() -> Self {
Self::DEFAULT
}
}
impl HasherPengy {
pub const fn new() -> Self {
Self::DEFAULT
}
pub const fn with_seed(seed: u64) -> Self {
Self { state: [0; 4], seed }
}
pub const fn is_empty(&self) -> bool {
let [a, b, c, d] = self.state;
a + b + c + d == 0
}
pub const fn reset(&mut self) {
self.state = [0; 4];
}
pub const fn clear(&mut self) {
self.state = [0; 4];
self.seed = 0;
}
pub const fn process(&mut self, data: &[u8]) {
let mut b: [u64; 4] = [0; 4];
let mut s: [u64; 4] = [0, 0, 0, data.len() as u64];
let mut remaining = data;
while remaining.len() >= 32 {
let mut i = 0;
while i < 4 {
let (_, rest) = remaining.split_at(i * 8);
let (chunk, _) = rest.split_at(8);
b[i] = u64::from_le_bytes(Self::make_byte_array(chunk));
i += 1;
}
let (_left, right) = remaining.split_at(32);
remaining = right;
s[0] = s[0].wrapping_add(s[1]).wrapping_add(b[3]);
s[1] = s[0].wrapping_add(s[1].wrapping_shl(14) | s[1].wrapping_shr(50));
s[2] = s[2].wrapping_add(s[3]).wrapping_add(b[2]);
s[3] = s[2].wrapping_add(s[3].wrapping_shl(23) | s[3].wrapping_shr(41));
s[0] = s[0].wrapping_add(s[3]).wrapping_add(b[1]);
s[3] = s[0] ^ (s[3].wrapping_shl(16) | s[3].wrapping_shr(48));
s[2] = s[2].wrapping_add(s[1]).wrapping_add(b[0]);
s[1] = s[2] ^ (s[1].wrapping_shl(40) | s[1].wrapping_shr(24));
}
let mut tmp = [0u8; 32];
let mut i = 0;
while i < remaining.len() {
if i < tmp.len() {
tmp[i] = remaining[i];
}
i += 1;
}
let mut i = 0;
while i < 4 {
let (_, rest) = tmp.split_at(i * 8);
let (chunk, _) = rest.split_at(8);
b[i] = u64::from_le_bytes(Self::make_byte_array(chunk));
i += 1;
}
let mut _i = 0;
while _i < 6 {
s[0] = s[0].wrapping_add(s[1]).wrapping_add(b[3]);
s[1] = s[0]
.wrapping_add(s[1].wrapping_shl(14) | s[1].wrapping_shr(50))
.wrapping_add(self.seed);
s[2] = s[2].wrapping_add(s[3]).wrapping_add(b[2]);
s[3] = s[2].wrapping_add(s[3].wrapping_shl(23) | s[3].wrapping_shr(41));
s[0] = s[0].wrapping_add(s[3]).wrapping_add(b[1]);
s[3] = s[0] ^ (s[3].wrapping_shl(16) | s[3].wrapping_shr(48));
s[2] = s[2].wrapping_add(s[1]).wrapping_add(b[0]);
s[1] = s[2] ^ (s[1].wrapping_shl(40) | s[1].wrapping_shr(24));
_i += 1;
}
self.state[0] = s[0];
self.state[1] = s[1];
self.state[2] = s[2];
self.state[3] = s[3];
}
const fn make_byte_array(chunk: &[u8]) -> [u8; 8] {
let mut byte_array = [0; 8];
let mut j = 0;
while j < chunk.len() {
byte_array[j] = chunk[j];
j += 1;
}
byte_array
}
pub const fn digest(&self) -> u64 {
self.state[0]
.wrapping_add(self.state[1])
.wrapping_add(self.state[2])
.wrapping_add(self.state[3])
}
}
impl Hasher for HasherPengy {
fn write(&mut self, data: &[u8]) {
self.process(data);
}
fn finish(&self) -> u64 {
self.digest()
}
}