Skip to content

Commit

Permalink
Update PhfHash to mirror std::hash::Hash
Browse files Browse the repository at this point in the history
  • Loading branch information
sfackler committed Jul 31, 2015
1 parent 559a211 commit 96ef156
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 47 deletions.
6 changes: 5 additions & 1 deletion phf/src/map.rs
Expand Up @@ -2,6 +2,7 @@
use debug_builders::DebugMap;
use std::borrow::Borrow;
use std::ops::Index;
use std::hash::{Hasher, SipHasher};
use std::slice;
use std::fmt;
use std::iter::IntoIterator;
Expand Down Expand Up @@ -70,7 +71,10 @@ impl<K, V> Map<K, V> {
/// Like `get`, but returns both the key and the value.
pub fn get_entry<T: ?Sized>(&self, key: &T) -> Option<(&K, &V)>
where T: Eq + PhfHash, K: Borrow<T> {
let (g, f1, f2) = key.phf_hash(self.key);
let mut hasher = SipHasher::new_with_keys(0, self.key);
key.phf_hash(&mut hasher);
let (g, f1, f2) = phf_shared::split(hasher.finish());

let (d1, d2) = self.disps[(g % (self.disps.len() as u32)) as usize];
let entry = &self.entries[(phf_shared::displace(f1, f2, d1, d2) % (self.entries.len() as u32))
as usize];
Expand Down
6 changes: 5 additions & 1 deletion phf/src/ordered_map.rs
@@ -1,6 +1,7 @@
//! An order-preserving immutable map constructed at compile time.
use debug_builders::DebugMap;
use std::borrow::Borrow;
use std::hash::{Hasher, SipHasher};
use std::iter::IntoIterator;
use std::ops::Index;
use std::fmt;
Expand Down Expand Up @@ -94,7 +95,10 @@ impl<K, V> OrderedMap<K, V> {

fn get_internal<T: ?Sized>(&self, key: &T) -> Option<(usize, (&K, &V))>
where T: Eq + PhfHash, K: Borrow<T> {
let (g, f1, f2) = key.phf_hash(self.key);
let mut hasher = SipHasher::new_with_keys(0, self.key);
key.phf_hash(&mut hasher);
let (g, f1, f2) = phf_shared::split(hasher.finish());

let (d1, d2) = self.disps[(g % (self.disps.len() as u32)) as usize];
let idx = self.idxs[(phf_shared::displace(f1, f2, d1, d2) % (self.idxs.len() as u32)) as usize];
let entry = &self.entries[idx];
Expand Down
6 changes: 5 additions & 1 deletion phf_generator/src/lib.rs
Expand Up @@ -4,6 +4,7 @@ extern crate rand;

use phf_shared::PhfHash;
use rand::{SeedableRng, XorShiftRng, Rng};
use std::hash::{Hasher, SipHasher};

const DEFAULT_LAMBDA: usize = 5;

Expand Down Expand Up @@ -37,9 +38,12 @@ fn try_generate_hash<H: PhfHash>(entries: &[H], rng: &mut XorShiftRng) -> Option
}

let key = rng.gen();
let hasher = SipHasher::new_with_keys(0, key);

let hashes: Vec<_> = entries.iter().map(|entry| {
let (g, f1, f2) = entry.phf_hash(key);
let mut hasher = hasher.clone();
entry.phf_hash(&mut hasher);
let (g, f1, f2) = phf_shared::split(hasher.finish());
Hashes {
g: g,
f1: f1,
Expand Down
30 changes: 15 additions & 15 deletions phf_macros/src/util.rs
Expand Up @@ -47,20 +47,20 @@ impl Hash for Key {
}

impl PhfHash for Key {
fn phf_hash(&self, key: u64) -> (u32, u32, u32) {
fn phf_hash<H: Hasher>(&self, state: &mut H) {
match *self {
Key::Str(ref s) => s.phf_hash(key),
Key::Binary(ref b) => b.phf_hash(key),
Key::Char(c) => c.phf_hash(key),
Key::U8(b) => b.phf_hash(key),
Key::I8(b) => b.phf_hash(key),
Key::U16(b) => b.phf_hash(key),
Key::I16(b) => b.phf_hash(key),
Key::U32(b) => b.phf_hash(key),
Key::I32(b) => b.phf_hash(key),
Key::U64(b) => b.phf_hash(key),
Key::I64(b) => b.phf_hash(key),
Key::Bool(b) => b.phf_hash(key),
Key::Str(ref s) => s.phf_hash(state),
Key::Binary(ref b) => b.phf_hash(state),
Key::Char(c) => c.phf_hash(state),
Key::U8(b) => b.phf_hash(state),
Key::I8(b) => b.phf_hash(state),
Key::U16(b) => b.phf_hash(state),
Key::I16(b) => b.phf_hash(state),
Key::U32(b) => b.phf_hash(state),
Key::I32(b) => b.phf_hash(state),
Key::U64(b) => b.phf_hash(state),
Key::I64(b) => b.phf_hash(state),
Key::Bool(b) => b.phf_hash(state),
}
}
}
Expand All @@ -72,8 +72,8 @@ pub struct Entry {
}

impl PhfHash for Entry {
fn phf_hash(&self, key: u64) -> (u32, u32, u32) {
self.key_contents.phf_hash(key)
fn phf_hash<H: Hasher>(&self, state: &mut H) {
self.key_contents.phf_hash(state)
}
}

Expand Down
61 changes: 32 additions & 29 deletions phf_shared/src/lib.rs
@@ -1,14 +1,14 @@
#![doc(html_root_url="http://sfackler.github.io/rust-phf/doc")]

use std::hash::{Hasher, Hash, SipHasher};
use std::hash::{Hasher, Hash};

#[inline]
pub fn displace(f1: u32, f2: u32, d1: u32, d2: u32) -> u32 {
d2 + f1 * d1 + f2
}

#[inline]
fn split(hash: u64) -> (u32, u32, u32) {
pub fn split(hash: u64) -> (u32, u32, u32) {
const BITS: u32 = 21;
const MASK: u64 = (1 << BITS) - 1;

Expand All @@ -17,39 +17,48 @@ fn split(hash: u64) -> (u32, u32, u32) {
((hash >> (2 * BITS)) & MASK) as u32)
}

/// A trait implemented by types which can be used in PHF data structures
/// A trait implemented by types which can be used in PHF data structures.
///
/// This differs from the standard library's `Hash` trait in that `PhfHash`'s
/// results must be architecture independent so that hashes will be consistent
/// between the host and target when cross compiling.
pub trait PhfHash {
/// Hashes the value of `self`, factoring in a seed
fn phf_hash(&self, seed: u64) -> (u32, u32, u32);
/// Feeds the value into the state given, updating the hasher as necessary.
fn phf_hash<H: Hasher>(&self, state: &mut H);

/// Feeds a slice of this type into the state provided.
fn phf_hash_slice<H: Hasher>(data: &[Self], state: &mut H) where Self: Sized {
for piece in data {
piece.phf_hash(state);
}
}
}

impl<'a> PhfHash for &'a str {
#[inline]
fn phf_hash(&self, seed: u64) -> (u32, u32, u32) {
self.as_bytes().phf_hash(seed)
fn phf_hash<H: Hasher>(&self, state: &mut H) {
self.as_bytes().phf_hash(state)
}
}

impl<'a> PhfHash for &'a [u8] {
#[inline]
fn phf_hash(&self, seed: u64) -> (u32, u32, u32) {
(*self).phf_hash(seed)
fn phf_hash<H: Hasher>(&self, state: &mut H) {
(*self).phf_hash(state)
}
}

impl PhfHash for str {
#[inline]
fn phf_hash(&self, seed: u64) -> (u32, u32, u32) {
self.as_bytes().phf_hash(seed)
fn phf_hash<H: Hasher>(&self, state: &mut H) {
self.as_bytes().phf_hash(state)
}
}

impl PhfHash for [u8] {
#[inline]
fn phf_hash(&self, seed: u64) -> (u32, u32, u32) {
let mut state = SipHasher::new_with_keys(seed, 0);
Hasher::write(&mut state, self);
split(state.finish())
fn phf_hash<H: Hasher>(&self, state: &mut H) {
state.write(self);
}
}

Expand All @@ -58,20 +67,16 @@ macro_rules! sip_impl(
(le $t:ty) => (
impl PhfHash for $t {
#[inline]
fn phf_hash(&self, seed: u64) -> (u32, u32, u32) {
let mut hasher = SipHasher::new_with_keys(seed, 0);
self.to_le().hash(&mut hasher);
split(hasher.finish())
fn phf_hash<H: Hasher>(&self, state: &mut H) {
self.to_le().hash(state);
}
}
);
($t:ty) => (
impl PhfHash for $t {
#[inline]
fn phf_hash(&self, seed: u64) -> (u32, u32, u32) {
let mut hasher = SipHasher::new_with_keys(seed, 0);
self.hash(&mut hasher);
split(hasher.finish())
fn phf_hash<H: Hasher>(&self, state: &mut H) {
self.hash(state);
}
}
)
Expand All @@ -89,19 +94,17 @@ sip_impl!(bool);

impl PhfHash for char {
#[inline]
fn phf_hash(&self, seed: u64) -> (u32, u32, u32) {
(*self as u32).phf_hash(seed)
fn phf_hash<H: Hasher>(&self, state: &mut H) {
(*self as u32).phf_hash(state)
}
}

macro_rules! array_impl(
($t:ty, $n:expr) => (
impl PhfHash for [$t; $n] {
#[inline]
fn phf_hash(&self, seed: u64) -> (u32, u32, u32) {
let mut hasher = SipHasher::new_with_keys(seed, 0);
Hasher::write(&mut hasher, self);
split(hasher.finish())
fn phf_hash<H: Hasher>(&self, state: &mut H) {
state.write(self);
}
}
)
Expand Down

0 comments on commit 96ef156

Please sign in to comment.