#![deny(missing_docs)]
use std::collections::{HashMap, HashSet};
use std::default::Default;
use std::hash::{Hasher, Hash, BuildHasherDefault};
use std::ops::BitXor;
extern crate byteorder;
use byteorder::{ByteOrder, NativeEndian};
pub type FxBuildHasher = BuildHasherDefault<FxHasher>;
pub type FxHashMap<K, V> = HashMap<K, V, FxBuildHasher>;
pub type FxHashSet<V> = HashSet<V, FxBuildHasher>;
#[derive(Debug, Clone)]
pub struct FxHasher {
hash: usize,
}
impl Default for FxHasher {
#[inline]
fn default() -> FxHasher {
FxHasher { hash: 0 }
}
}
#[cfg(target_pointer_width = "32")]
const K: usize = 0x9e3779b9;
#[cfg(target_pointer_width = "64")]
const K: usize = 0x517cc1b727220a95;
impl FxHasher {
#[inline]
fn add_to_hash(&mut self, i: usize) {
self.hash = self.hash.rotate_left(5).bitxor(i).wrapping_mul(K);
}
}
impl Hasher for FxHasher {
#[cfg(target_pointer_width = "32")]
#[inline]
fn write(&mut self, mut bytes: &[u8]) {
let ptr_size = std::mem::size_of::<usize>();
while bytes.len() >= ptr_size {
let n = NativeEndian::read_u32(bytes) as usize;
self.add_to_hash(n as usize);
bytes = bytes.split_at(ptr_size).1;
}
for byte in bytes {
let i = *byte;
self.add_to_hash(i as usize);
}
}
#[cfg(target_pointer_width = "64")]
#[inline]
fn write(&mut self, mut bytes: &[u8]) {
let ptr_size = std::mem::size_of::<usize>();
while bytes.len() >= ptr_size {
let n = NativeEndian::read_u64(bytes);
self.add_to_hash(n as usize);
bytes = bytes.split_at(ptr_size).1;
}
while bytes.len() >= 4 {
let n = NativeEndian::read_u32(bytes);
self.add_to_hash(n as usize);
bytes = bytes.split_at(4).1;
}
for byte in bytes {
let i = *byte;
self.add_to_hash(i as usize);
}
}
#[inline]
fn write_u8(&mut self, i: u8) {
self.add_to_hash(i as usize);
}
#[inline]
fn write_u16(&mut self, i: u16) {
self.add_to_hash(i as usize);
}
#[inline]
fn write_u32(&mut self, i: u32) {
self.add_to_hash(i as usize);
}
#[cfg(target_pointer_width = "32")]
#[inline]
fn write_u64(&mut self, i: u64) {
self.add_to_hash(i as usize);
self.add_to_hash((i >> 32) as usize);
}
#[cfg(target_pointer_width = "64")]
#[inline]
fn write_u64(&mut self, i: u64) {
self.add_to_hash(i as usize);
}
#[inline]
fn write_usize(&mut self, i: usize) {
self.add_to_hash(i);
}
#[inline]
fn finish(&self) -> u64 {
self.hash as u64
}
}
#[inline]
pub fn hash<T: Hash + ?Sized>(v: &T) -> u64 {
let mut state = FxHasher::default();
v.hash(&mut state);
state.finish()
}