Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
104 changes: 93 additions & 11 deletions lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![deny(missing_docs)]

//! # Fx Hash
//!
//! This hashing algorithm was extracted from the Rustc compiler. This is the same hashing
Expand All @@ -25,10 +23,11 @@
//! potentially cause quadratic behavior in `HashMap`s. So it is not recommended to expose
//! this hash in places where collissions or DDOS attacks may be a concern.

use std::iter::FromIterator;
use std::collections::{HashMap, HashSet};
use std::default::Default;
use std::hash::{BuildHasherDefault, Hash, Hasher};
use std::ops::BitXor;
use std::ops::{BitXor, Deref, DerefMut};

extern crate byteorder;
use byteorder::{ByteOrder, NativeEndian};
Expand All @@ -38,16 +37,99 @@ pub type FxBuildHasher = BuildHasherDefault<FxHasher>;

/// A `HashMap` using a default Fx hasher.
///
/// Use `FxHashMap::default()`, not `new()` to create a new `FxHashMap`.
/// To create with a reserved capacity, use `FxHashMap::with_capacity_and_hasher(num, Default::default())`.
pub type FxHashMap<K, V> = HashMap<K, V, FxBuildHasher>;
#[repr(transparent)]
#[derive(Debug, Clone, Default)]
pub struct FxHashMap<K, V>(HashMap<K, V, FxBuildHasher>);

impl<K, V> FxHashMap<K, V> {
#[inline]
pub fn new() -> Self {
Self(HashMap::with_hasher(FxBuildHasher::default()))
}

#[inline]
pub fn with_capacity(n: usize) -> Self {
Self(HashMap::with_capacity_and_hasher(n, FxBuildHasher::default()))
}
}

impl<K, V> Deref for FxHashMap<K, V> {
type Target = HashMap<K, V, FxBuildHasher>;

#[inline]
fn deref(&self) -> &Self::Target {
&self.0
}
}

impl<K, V> DerefMut for FxHashMap<K, V> {
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}

impl<K, V> FromIterator<(K, V)> for FxHashMap<K, V>
where
K: Eq + Hash
{
#[inline]
fn from_iter<I>(iter: I) -> Self
where
I: IntoIterator<Item = (K, V)>
{
let inner_set = HashMap::<K, V, FxBuildHasher>::from_iter(iter);
Self(inner_set)
}
}

/// A `HashSet` using a default Fx hasher.
///
/// Note: Use `FxHashSet::default()`, not `new()` to create a new `FxHashSet`.
/// To create with a reserved capacity, use `FxHashSet::with_capacity_and_hasher(num, Default::default())`.
pub type FxHashSet<V> = HashSet<V, FxBuildHasher>;
#[repr(transparent)]
#[derive(Debug, Clone, Default)]
pub struct FxHashSet<V>(HashSet<V, FxBuildHasher>);

impl<V> FxHashSet<V> {
#[inline]
pub fn new() -> Self {
Self(HashSet::with_hasher(FxBuildHasher::default()))
}

#[inline]
pub fn with_capacity(n: usize) -> Self {
Self(HashSet::with_capacity_and_hasher(n, FxBuildHasher::default()))
}
}

impl<V> DerefMut for FxHashSet<V> {
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}

impl<V> Deref for FxHashSet<V> {
type Target = HashSet<V, FxBuildHasher>;

#[inline]
fn deref(&self) -> &Self::Target {
&self.0
}
}

impl<V> FromIterator<V> for FxHashSet<V>
where
V: Eq + Hash
{
#[inline]
fn from_iter<I>(iter: I) -> Self
where
I: IntoIterator<Item = V>
{
let inner_set = HashSet::<V, FxBuildHasher>::from_iter(iter);
Self(inner_set)
}
}

const ROTATE: u32 = 5;
const SEED64: u64 = 0x51_7c_c1_b7_27_22_0a_95;
const SEED32: u32 = 0x9e_37_79_b9;
Expand All @@ -58,7 +140,7 @@ const SEED: usize = SEED32 as usize;
const SEED: usize = SEED64 as usize;

trait HashWord {
fn hash_word(&mut self, Self);
fn hash_word(&mut self, _: Self);
}

macro_rules! impl_hash_word {
Expand Down