use std::convert::Infallible;
use std::hash::Hasher;
pub trait AlwaysOk<T> {
fn aok(self) -> T;
}
impl<T, I> AlwaysOk<T> for Result<T, I> where I: Into<Infallible> {
#[inline] fn aok(self) -> T {
match self {
Ok(ok) => ok,
Err(err) => { let _err: Infallible = err.into(); match _err {} }
}
}
}
#[derive(Debug, Copy, Clone, Default)]
pub struct PassThroughHasher {
pub starting_value: u64
}
impl Hasher for PassThroughHasher {
#[inline(always)] fn finish(&self) -> u64 { self.starting_value }
#[inline(always)] fn write(&mut self, bytes: &[u8]) {
let mut new_value = [0; 8];
let mut i = 0;
for byte in bytes.iter().rev() {
if i >= 8 { break }
new_value[7 - i] = *byte;
i += 1;
}
let old_value = self.starting_value.to_ne_bytes();
for byte in old_value.iter().rev() {
if i >= 8 { break }
new_value[7 - i] = *byte;
i += 1;
}
self.starting_value = u64::from_ne_bytes(new_value);
}
#[inline(always)] fn write_u64(&mut self, value: u64) { self.starting_value = value }
}
#[cfg(test)]
mod tests {
use super::*;
use rand_xoshiro::Xoshiro256StarStar;
use rand::SeedableRng;
use rand::Rng;
const RNG_SEED: u64 = 0xCAFEDECAF2832;
#[test]
fn pass_through_hasher_works() {
let mut hasher = PassThroughHasher::default();
assert_eq!(hasher.finish(), 0);
hasher.write(&[1, 2, 3, 4]);
assert_eq!(hasher.finish(), u64::from_ne_bytes([0, 0, 0, 0, 1, 2, 3, 4]));
hasher.write(&[5, 6, 7, 8]);
assert_eq!(hasher.finish(), u64::from_ne_bytes([1, 2, 3, 4, 5, 6, 7, 8]));
let mut rng = Xoshiro256StarStar::seed_from_u64(RNG_SEED);
for _ in 0..100 {
let val = rng.gen();
hasher.write_u64(val);
assert_eq!(hasher.finish(), val);
hasher.write(&val.to_ne_bytes());
assert_eq!(hasher.finish(), val);
}
}
}