Skip to content

Commit

Permalink
Add more _equiv methods
Browse files Browse the repository at this point in the history
This should be enough to do everything you'd be able to do before

Closes #8
  • Loading branch information
sfackler committed Jul 25, 2014
1 parent c98c691 commit 61eea75
Show file tree
Hide file tree
Showing 2 changed files with 97 additions and 19 deletions.
90 changes: 71 additions & 19 deletions phf/src/lib.rs
Expand Up @@ -90,6 +90,19 @@ impl<K: Hash+Eq, V> Index<K, V> for PhfMap<K, V> {
}

impl<K: Hash+Eq, V> PhfMap<K, V> {
/// Returns a reference to the map's internal static instance of the given
/// key.
///
/// This can be useful for interning schemes.
pub fn find_key(&self, key: &K) -> Option<&K> {
self.get_entry(key, |k| key == k).map(|e| {
let &(ref k, _) = e;
k
})
}
}

impl<K, V> PhfMap<K, V> {
fn get_entry<T: Hash>(&self, key: &T, check: |&K| -> bool)
-> Option<&(K, V)> {
let (g, f1, f2) = shared::hash(key, self.k1, self.k2);
Expand All @@ -103,17 +116,6 @@ impl<K: Hash+Eq, V> PhfMap<K, V> {
}
}

/// Returns a reference to the map's internal static instance of the given
/// key.
///
/// This can be useful for interning schemes.
pub fn find_key(&self, key: &K) -> Option<&K> {
self.get_entry(key, |k| key == k).map(|e| {
let &(ref k, _) = e;
k
})
}

/// Like `find`, but can operate on any type that is equivalent to a key.
pub fn find_equiv<T: Hash+Equiv<K>>(&self, key: &T) -> Option<&V> {
self.get_entry(key, |k| key.equiv(k)).map(|e| {
Expand Down Expand Up @@ -304,6 +306,22 @@ impl<T: Hash+Eq> PhfSet<T> {
}
}

impl<T> PhfSet<T> {
/// Like `contains`, but can operate on any type that is equivalent to a
/// value
#[inline]
pub fn contains_equiv<U: Hash+Equiv<T>>(&self, key: &U) -> bool {
self.map.find_equiv(key).is_some()
}

/// Like `find_key`, but can operate on any type that is equivalent to a
/// value
#[inline]
pub fn find_key_equiv<U: Hash+Equiv<T>>(&self, key: &U) -> Option<&T> {
self.map.find_key_equiv(key)
}
}

impl<T> PhfSet<T> {
/// Returns an iterator over the values in the set.
///
Expand Down Expand Up @@ -401,7 +419,7 @@ impl<K, V> Collection for PhfOrderedMap<K, V> {

impl<K: Hash+Eq, V> Map<K, V> for PhfOrderedMap<K, V> {
fn find(&self, key: &K) -> Option<&V> {
self.find_entry(key).map(|e| {
self.find_entry(key, |k| k == key).map(|e| {
let &(_, ref v) = e;
v
})
Expand All @@ -415,25 +433,45 @@ impl<K: Hash+Eq, V> Index<K, V> for PhfOrderedMap<K, V> {
}

impl<K: Hash+Eq, V> PhfOrderedMap<K, V> {
fn find_entry(&self, key: &K) -> Option<&(K, V)> {
/// Returns a reference to the map's internal static instance of the given
/// key.
///
/// This can be useful for interning schemes.
pub fn find_key(&self, key: &K) -> Option<&K> {
self.find_entry(key, |k| k == key).map(|e| {
let &(ref k, _) = e;
k
})
}
}

impl<K, V> PhfOrderedMap<K, V> {
fn find_entry<T: Hash>(&self, key: &T, check: |&K| -> bool)
-> Option<&(K, V)> {
let (g, f1, f2) = shared::hash(key, self.k1, self.k2);
let (d1, d2) = self.disps[g % self.disps.len()];
let idx = self.idxs[shared::displace(f1, f2, d1, d2) % self.idxs.len()];
let entry @ &(ref s, _) = &self.entries[idx];

if s == key {
if check(s) {
Some(entry)
} else {
None
}
}

/// Returns a reference to the map's internal static instance of the given
/// Like `find`, but can operate on any type that is equivalent to a key.
pub fn find_equiv<T: Hash+Equiv<K>>(&self, key: &T) -> Option<&V> {
self.find_entry(key, |k| key.equiv(k)).map(|e| {
let &(_, ref v) = e;
v
})
}

/// Like `find_key`, but can operate on any type that is equivalent to a
/// key.
///
/// This can be useful for interning schemes.
pub fn find_key(&self, key: &K) -> Option<&K> {
self.find_entry(key).map(|e| {
pub fn find_key_equiv<T: Hash+Equiv<K>>(&self, key: &T) -> Option<&K> {
self.find_entry(key, |k| key.equiv(k)).map(|e| {
let &(ref k, _) = e;
k
})
Expand Down Expand Up @@ -648,6 +686,20 @@ impl<T: Hash+Eq> PhfOrderedSet<T> {
}

impl<T> PhfOrderedSet<T> {
/// Like `contains`, but can operate on any type that is equivalent to a
/// value
#[inline]
pub fn contains_equiv<U: Hash+Equiv<T>>(&self, key: &U) -> bool {
self.map.find_equiv(key).is_some()
}

/// Like `find_key`, but can operate on any type that is equivalent to a
/// value
#[inline]
pub fn find_key_equiv<U: Hash+Equiv<T>>(&self, key: &U) -> Option<&T> {
self.map.find_key_equiv(key)
}

/// Returns an iterator over the values in the set.
///
/// Values are returned in the same order in which they were defined.
Expand Down
26 changes: 26 additions & 0 deletions phf/src/test.rs
Expand Up @@ -241,6 +241,15 @@ mod set {
assert!(set.contains(&"world"));
assert_eq!(2, set.len());
}

#[test]
fn test_non_static_str_contains() {
static SET: PhfSet<&'static str> = phf_set! {
"hello",
"world",
};
assert!(SET.contains_equiv(&"hello".to_string().as_slice()));
}
}

mod ordered_map {
Expand Down Expand Up @@ -317,6 +326,14 @@ mod ordered_map {
);
map["b"];
}

#[test]
fn test_non_static_str_key() {
static map: PhfOrderedMap<&'static str, int> = phf_ordered_map!(
"a" => 0,
);
assert_eq!(Some(&0), map.find_equiv(&"a".to_string().as_slice()));
}
}

mod ordered_set {
Expand Down Expand Up @@ -356,4 +373,13 @@ mod ordered_set {
let vec = SET.iter().map(|&e| e).collect::<Vec<_>>();
assert_eq!(vec, vec!("hello", "there", "world"));
}

#[test]
fn test_non_static_str_contains() {
static SET: PhfOrderedSet<&'static str> = phf_ordered_set! {
"hello",
"world",
};
assert!(SET.contains_equiv(&"hello".to_string().as_slice()));
}
}

0 comments on commit 61eea75

Please sign in to comment.