diff --git a/Makefile.in b/Makefile.in index bf8ad9a8..29eceeeb 100644 --- a/Makefile.in +++ b/Makefile.in @@ -26,7 +26,7 @@ $(BUILDDIR): $(PHF): $(PHF_LIB) | $(BUILDDIR) $(ENV) $(RUSTC) $(RUSTFLAGS) --dep-info $(BUILDDIR)/phf.d --out-dir $(@D) $< -$(PHF_MAC): $(PHF_MAC_LIB) $(PHF) | $(BUILDDIR) +$(PHF_MAC): $(PHF_MAC_LIB) | $(BUILDDIR) $(ENV) $(RUSTC) $(RUSTFLAGS) --dep-info $(BUILDDIR)/phf_mac.d --out-dir $(@D) \ -L $(BUILDDIR) $< diff --git a/phf/Cargo.toml b/phf/Cargo.toml index b0249b8a..ceb12904 100644 --- a/phf/Cargo.toml +++ b/phf/Cargo.toml @@ -8,3 +8,12 @@ version = "0.0.0" name = "phf" path = "src/lib.rs" + +[dev_dependencies.phf_mac] + +path = "../phf_mac" + +[[test]] + +name = "test" +path = "src/test.rs" \ No newline at end of file diff --git a/phf/src/lib.rs b/phf/src/lib.rs index 71133430..ed86ef1e 100644 --- a/phf/src/lib.rs +++ b/phf/src/lib.rs @@ -9,33 +9,13 @@ #![warn(missing_doc)] use std::fmt; -use std::hash::{Hash, Hasher}; -use std::hash::sip::SipHasher; +use std::hash::Hash; use std::iter; use std::slice; use std::collections::Collection; -static LOG_MAX_SIZE: uint = 21; - -#[doc(hidden)] -pub static MAX_SIZE: uint = 1 << LOG_MAX_SIZE; - -#[doc(hidden)] -#[inline] -pub fn hash(s: &T, k1: u64, k2: u64) -> (uint, uint, uint) { - let hash = SipHasher::new_with_keys(k1, k2).hash(s); - let mask = (MAX_SIZE - 1) as u64; - - ((hash & mask) as uint, - ((hash >> LOG_MAX_SIZE) & mask) as uint, - ((hash >> (2 * LOG_MAX_SIZE)) & mask) as uint) -} - -#[doc(hidden)] -#[inline] -pub fn displace(f1: uint, f2: uint, d1: uint, d2: uint) -> uint { - d2 + f1 * d1 + f2 -} +#[path="../../phf_shared/mod.rs"] +mod phf_shared; /// An immutable map constructed at compile time. /// @@ -106,9 +86,9 @@ impl fmt::Show for PhfMap { impl PhfMap { fn get_entry<'a, T: Hash>(&'a self, key: &T, check: |&K| -> bool) -> Option<&'a (K, V)> { - let (g, f1, f2) = hash(key, self.k1, self.k2); + let (g, f1, f2) = phf_shared::hash(key, self.k1, self.k2); let (d1, d2) = self.disps[g % self.disps.len()]; - let entry @ &(ref s, _) = &self.entries[displace(f1, f2, d1, d2) % + let entry @ &(ref s, _) = &self.entries[phf_shared::displace(f1, f2, d1, d2) % self.entries.len()]; if check(s) { Some(entry) @@ -426,9 +406,9 @@ impl<'a, K: Hash+Eq, V> Map for PhfOrderedMap { impl PhfOrderedMap { fn find_entry<'a>(&'a self, key: &K) -> Option<&'a (K, V)> { - let (g, f1, f2) = hash(key, self.k1, self.k2); + let (g, f1, f2) = phf_shared::hash(key, self.k1, self.k2); let (d1, d2) = self.disps[g % self.disps.len()]; - let idx = self.idxs[displace(f1, f2, d1, d2) % self.idxs.len()]; + let idx = self.idxs[phf_shared::displace(f1, f2, d1, d2) % self.idxs.len()]; let entry @ &(ref s, _) = &self.entries[idx]; if s == key { diff --git a/phf_mac/Cargo.toml b/phf_mac/Cargo.toml index 80addf79..28e22c80 100644 --- a/phf_mac/Cargo.toml +++ b/phf_mac/Cargo.toml @@ -9,7 +9,3 @@ version = "0.0.0" name = "phf_mac" path = "src/lib.rs" plugin = true - -[dependencies.phf] - -path = "../phf" diff --git a/phf_mac/src/lib.rs b/phf_mac/src/lib.rs index 406c1936..d9ccd9a3 100644 --- a/phf_mac/src/lib.rs +++ b/phf_mac/src/lib.rs @@ -9,13 +9,12 @@ extern crate rand; extern crate syntax; extern crate time; -extern crate phf; extern crate rustc; use std::collections::HashMap; use std::gc::{Gc, GC}; use std::hash; -use std::hash::{Hash}; +use std::hash::Hash; use std::os; use std::rc::Rc; use syntax::ast; @@ -31,6 +30,9 @@ use syntax::print::pprust; use rand::{Rng, SeedableRng, XorShiftRng}; use rustc::plugin::Registry; +#[path="../../phf_shared/mod.rs"] +mod phf_shared; + static DEFAULT_LAMBDA: uint = 5; static FIXED_SEED: [u32, ..4] = [3141592653, 589793238, 462643383, 2795028841]; @@ -188,10 +190,10 @@ fn parse_map(cx: &mut ExtCtxt, tts: &[TokenTree]) -> Option> { } } - if entries.len() > phf::MAX_SIZE { + if entries.len() > phf_shared::MAX_SIZE { cx.span_err(parser.span, format!("maps with more than {} entries are not supported", - phf::MAX_SIZE).as_slice()); + phf_shared::MAX_SIZE).as_slice()); return None; } @@ -228,10 +230,10 @@ fn parse_set(cx: &mut ExtCtxt, tts: &[TokenTree]) -> Option> { } } - if entries.len() > phf::MAX_SIZE { + if entries.len() > phf_shared::MAX_SIZE { cx.span_err(parser.span, format!("maps with more than {} entries are not supported", - phf::MAX_SIZE).as_slice()); + phf_shared::MAX_SIZE).as_slice()); return None; } @@ -336,7 +338,7 @@ fn try_generate_hash(entries: &[Entry], rng: &mut XorShiftRng) let k2 = rng.gen(); let hashes: Vec = entries.iter().map(|entry| { - let (g, f1, f2) = phf::hash(&entry.key_contents, k1, k2); + let (g, f1, f2) = phf_shared::hash(&entry.key_contents, k1, k2); Hashes { g: g, f1: f1, @@ -364,10 +366,10 @@ fn try_generate_hash(entries: &[Entry], rng: &mut XorShiftRng) 'disps: for d2 in range(0, table_len) { try_map.clear(); for &key in bucket.keys.iter() { - let idx = phf::displace(hashes.get(key).f1, - hashes.get(key).f2, - d1, - d2) % table_len; + let idx = phf_shared::displace(hashes.get(key).f1, + hashes.get(key).f2, + d1, + d2) % table_len; if map.get(idx).is_some() || try_map.find(&idx).is_some() { continue 'disps; } diff --git a/phf_shared/mod.rs b/phf_shared/mod.rs new file mode 100644 index 00000000..be451e06 --- /dev/null +++ b/phf_shared/mod.rs @@ -0,0 +1,19 @@ +use std::hash::{Hash, Hasher}; +use std::hash::sip::SipHasher; + +static LOG_MAX_SIZE: uint = 21; + +pub static MAX_SIZE: uint = 1 << LOG_MAX_SIZE; + +pub fn hash(s: &T, k1: u64, k2: u64) -> (uint, uint, uint) { + let hash = SipHasher::new_with_keys(k1, k2).hash(s); + let mask = (MAX_SIZE - 1) as u64; + + ((hash & mask) as uint, + ((hash >> LOG_MAX_SIZE) & mask) as uint, + ((hash >> (2 * LOG_MAX_SIZE)) & mask) as uint) +} + +pub fn displace(f1: uint, f2: uint, d1: uint, d2: uint) -> uint { + d2 + f1 * d1 + f2 +}