use crate::convert::{Convert};
use std::hash::{Hasher};
use const_random::const_random;
use arrayref::*;
const MULTIPLES: [u64; 2] = [0xBF58476D1CE4E5B9, 0x94D049BB133111EB];
const INCREMENT: u64 = 0x9e3779b97f4a7c15;
const DEFAULT_KEYS: [u64; 2] = [const_random!(u64), const_random!(u64)];
#[derive(Debug, Clone)]
pub struct AHasher {
buffer: u64,
key: u64,
}
impl Default for AHasher {
#[inline]
fn default() -> AHasher {
AHasher {buffer: DEFAULT_KEYS[0], key: DEFAULT_KEYS[1]}
}
}
impl AHasher {
#[inline]
pub fn new_with_keys(key0: u64, key1: u64) -> AHasher {
AHasher { buffer: key0, key: key1 }
}
#[inline(always)]
fn update(&mut self, new_data: u64) {
let value = (new_data ^ self.key).wrapping_mul(MULTIPLES[0]);
self.buffer ^= value.rotate_right(27).wrapping_mul(MULTIPLES[1]);
self.key = self.key.wrapping_add(INCREMENT);
}
}
impl Hasher for AHasher {
#[inline]
fn write_u8(&mut self, i: u8) {
self.update(i as u64);
}
#[inline]
fn write_u16(&mut self, i: u16) {
self.update(i as u64);
}
#[inline]
fn write_u32(&mut self, i: u32) {
self.update(i as u64);
}
#[inline]
fn write_u64(&mut self, i: u64) {
self.update(i as u64);
}
#[inline]
fn write_u128(&mut self, i: u128) {
let data: [u64;2] = i.convert();
self.update(data[0]);
self.update(data[1]);
}
#[inline]
fn write_usize(&mut self, i: usize) {
self.write_u64(i as u64);
}
#[inline]
fn write(&mut self, input: &[u8]) {
let mut data = input;
let length = data.len() as u64;
self.key = self.key.wrapping_add(length);
if data.len() >= 8 {
while data.len() > 16 {
let (block, rest) = data.split_at(8);
let val: u64 = as_array!(block, 8).convert();
self.update(val);
data = rest;
}
let val: u64 = (*array_ref!(data, 0, 8)).convert();
self.update(val);
let val: u64 = (*array_ref!(data, data.len()-8, 8)).convert();
self.update(val);
} else {
if data.len() >= 2 {
if data.len() >= 4 {
let block: [u32; 2] = [(*array_ref!(data, 0, 4)).convert(),
(*array_ref!(data, data.len()-4, 4)).convert()];
self.update(block.convert());
} else {
let block: [u16; 2] = [(*array_ref!(data, 0, 2)).convert(),
(*array_ref!(data, data.len()-2, 2)).convert()];
let val: u32 = block.convert();
self.update(val as u64);
}
} else {
if data.len() >= 1 {
self.update(data[0] as u64);
}
}
}
}
#[inline]
fn finish(&self) -> u64 {
let result = self.buffer ^ self.key;
let result = ((result >> 30) ^ result).wrapping_mul(MULTIPLES[0]);
result ^ (result >> 31)
}
}
#[cfg(test)]
mod tests {
use std::collections::HashMap;
use std::hash::{BuildHasherDefault};
use crate::convert::Convert;
use crate::fallback_hash::*;
#[test]
fn test_builder() {
let mut map = HashMap::<u32, u64, BuildHasherDefault<AHasher>>::default();
map.insert(1, 3);
}
#[test]
fn test_default() {
let hasher_a = AHasher::default();
assert_ne!(0, hasher_a.buffer);
assert_ne!(0, hasher_a.key);
assert_ne!(hasher_a.buffer, hasher_a.key);
let hasher_b = AHasher::default();
assert_eq!(hasher_a.buffer, hasher_b.buffer);
assert_eq!(hasher_a.key, hasher_b.key);
}
#[test]
fn test_hash() {
let mut hasher = AHasher::new_with_keys(0,0);
let value: u64 = 1 << 32;
hasher.update(value);
let result = hasher.buffer;
let mut hasher = AHasher::new_with_keys(0,0);
let value2: u64 = 1;
hasher.update(value2);
let result2 = hasher.buffer;
let result: [u8; 8] = result.convert();
let result2: [u8; 8] = result2.convert();
assert_ne!(hex::encode(result), hex::encode(result2));
}
#[test]
fn test_conversion() {
let input: &[u8] = "dddddddd".as_bytes();
let bytes: u64 = as_array!(input, 8).convert();
assert_eq!(bytes, 0x6464646464646464);
}
}