Skip to content

Commit

Permalink
Provide find_index{,_equiv} on PhfOrdered{Set,Map}
Browse files Browse the repository at this point in the history
  • Loading branch information
kmcallister committed Sep 3, 2014
1 parent 3687c0e commit b16d440
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 6 deletions.
39 changes: 33 additions & 6 deletions phf/src/lib.rs
Expand Up @@ -415,7 +415,7 @@ impl<K, V> Collection for PhfOrderedMap<K, V> {

impl<K, V> Map<K, V> for PhfOrderedMap<K, V> where K: PhfHash+Eq {
fn find(&self, key: &K) -> Option<&V> {
self.find_entry(key, |k| k == key).map(|e| {
self.find_entry(key, |k| k == key).map(|(_, e)| {
let &(_, ref v) = e;
v
})
Expand All @@ -434,31 +434,38 @@ impl<K, V> PhfOrderedMap<K, V> where K: PhfHash+Eq {
///
/// 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| {
self.find_entry(key, |k| k == key).map(|(_, e)| {
let &(ref k, _) = e;
k
})
}

/// Returns the index of the key within the list used to initialize
/// the ordered map.
pub fn find_index(&self, key: &K) -> Option<uint> {
self.find_entry(key, |k| k == key).map(|(i, _)| i)
}
}

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

if check(s) {
Some(entry)
Some((idx, entry))
} else {
None
}
}

/// Like `find`, but can operate on any type that is equivalent to a key.
pub fn find_equiv<T>(&self, key: &T) -> Option<&V> where T: PhfHash+Equiv<K> {
self.find_entry(key, |k| key.equiv(k)).map(|e| {
self.find_entry(key, |k| key.equiv(k)).map(|(_, e)| {
let &(_, ref v) = e;
v
})
Expand All @@ -467,11 +474,18 @@ impl<K, V> PhfOrderedMap<K, V> {
/// Like `find_key`, but can operate on any type that is equivalent to a
/// key.
pub fn find_key_equiv<T>(&self, key: &T) -> Option<&K> where T: PhfHash+Equiv<K> {
self.find_entry(key, |k| key.equiv(k)).map(|e| {
self.find_entry(key, |k| key.equiv(k)).map(|(_, e)| {
let &(ref k, _) = e;
k
})
}

/// Like `find_index`, but can operate on any type that is equivalent to a
/// key.
pub fn find_index_equiv<T>(&self, key: &T) -> Option<uint>
where T: PhfHash+Equiv<K> {
self.find_entry(key, |k| key.equiv(k)).map(|(i, _)| i)
}
}

impl<K, V> PhfOrderedMap<K, V> {
Expand Down Expand Up @@ -679,6 +693,12 @@ impl<T: PhfHash+Eq> PhfOrderedSet<T> {
pub fn find_key(&self, key: &T) -> Option<&T> {
self.map.find_key(key)
}

/// Returns the index of the key within the list used to initialize
/// the ordered set.
pub fn find_index(&self, key: &T) -> Option<uint> {
self.map.find_index(key)
}
}

impl<T> PhfOrderedSet<T> {
Expand All @@ -696,6 +716,13 @@ impl<T> PhfOrderedSet<T> {
self.map.find_key_equiv(key)
}

/// Like `find_index`, but can operate on any type that is equivalent to a
/// key.
pub fn find_index_equiv<U>(&self, key: &U) -> Option<uint>
where U: PhfHash+Equiv<T> {
self.map.find_index_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
34 changes: 34 additions & 0 deletions phf/tests/test.rs
Expand Up @@ -277,6 +277,23 @@ mod ordered_map {
assert_eq!(2, map.len());
}

#[test]
fn test_find_index() {
static map: PhfOrderedMap<&'static str, int> = phf_ordered_map!(
"foo" => 5,
"bar" => 5,
"baz" => 5,
);
assert_eq!(Some(0), map.find_index(&"foo"));
assert_eq!(Some(2), map.find_index(&"baz"));
assert_eq!(None, map.find_index(&"xyz"));
assert_eq!(&"baz", map.keys().idx(map.find_index(&"baz").unwrap()).unwrap());

assert_eq!(Some(0), map.find_index_equiv(&"foo".to_string().as_slice()));
assert_eq!(Some(2), map.find_index_equiv(&"baz".to_string().as_slice()));
assert_eq!(None, map.find_index_equiv(&"xyz".to_string().as_slice()));
}

#[test]
fn test_entries() {
static MAP: PhfOrderedMap<&'static str, int> = phf_ordered_map!(
Expand Down Expand Up @@ -363,6 +380,23 @@ mod ordered_set {
assert_eq!(3, SET.len());
}

#[test]
fn test_find_index() {
static SET: PhfOrderedSet<&'static str> = phf_ordered_set! {
"foo",
"bar",
"baz",
};
assert_eq!(Some(0), SET.find_index(&"foo"));
assert_eq!(Some(2), SET.find_index(&"baz"));
assert_eq!(None, SET.find_index(&"xyz"));
assert_eq!(&"baz", SET.iter().idx(SET.find_index(&"baz").unwrap()).unwrap());

assert_eq!(Some(0), SET.find_index_equiv(&"foo".to_string().as_slice()));
assert_eq!(Some(2), SET.find_index_equiv(&"baz".to_string().as_slice()));
assert_eq!(None, SET.find_index_equiv(&"xyz".to_string().as_slice()));
}

#[test]
fn test_iter() {
static SET: PhfOrderedSet<&'static str> = phf_ordered_set! {
Expand Down

0 comments on commit b16d440

Please sign in to comment.