diff --git a/phf/src/lib.rs b/phf/src/lib.rs index 9e5de946..175500c7 100644 --- a/phf/src/lib.rs +++ b/phf/src/lib.rs @@ -415,7 +415,7 @@ impl Collection for PhfOrderedMap { impl Map for PhfOrderedMap 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 }) @@ -434,15 +434,22 @@ impl PhfOrderedMap 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 { + self.find_entry(key, |k| k == key).map(|(i, _)| i) + } } impl PhfOrderedMap { - fn find_entry(&self, key: &T, check: |&K| -> bool) -> Option<&(K, V)> where T: PhfHash { + fn find_entry(&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]; @@ -450,7 +457,7 @@ impl PhfOrderedMap { let &(ref s, _) = entry; if check(s) { - Some(entry) + Some((idx, entry)) } else { None } @@ -458,7 +465,7 @@ impl PhfOrderedMap { /// Like `find`, but can operate on any type that is equivalent to a key. pub fn find_equiv(&self, key: &T) -> Option<&V> where T: PhfHash+Equiv { - 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 }) @@ -467,11 +474,18 @@ impl PhfOrderedMap { /// Like `find_key`, but can operate on any type that is equivalent to a /// key. pub fn find_key_equiv(&self, key: &T) -> Option<&K> where T: PhfHash+Equiv { - 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(&self, key: &T) -> Option + where T: PhfHash+Equiv { + self.find_entry(key, |k| key.equiv(k)).map(|(i, _)| i) + } } impl PhfOrderedMap { @@ -679,6 +693,12 @@ impl PhfOrderedSet { 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 { + self.map.find_index(key) + } } impl PhfOrderedSet { @@ -696,6 +716,13 @@ impl PhfOrderedSet { 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(&self, key: &U) -> Option + where U: PhfHash+Equiv { + 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. diff --git a/phf/tests/test.rs b/phf/tests/test.rs index edfa789f..72ed7280 100644 --- a/phf/tests/test.rs +++ b/phf/tests/test.rs @@ -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!( @@ -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! {