Skip to content

Commit 1a50e7b

Browse files
authored
Merge pull request #305 from cuviper/raw_entry-index
Add indexing methods to raw entry
2 parents 7264ce4 + f4bb006 commit 1a50e7b

File tree

3 files changed

+49
-7
lines changed

3 files changed

+49
-7
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[package]
22
name = "indexmap"
33
edition = "2021"
4-
version = "2.2.1"
4+
version = "2.2.2"
55
documentation = "https://docs.rs/indexmap/"
66
repository = "https://github.com/indexmap-rs/indexmap"
77
license = "Apache-2.0 OR MIT"

RELEASES.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
- 2.2.2
2+
3+
- Added indexing methods to raw entries: `RawEntryBuilder::from_hash_full`,
4+
`RawEntryBuilder::index_from_hash`, and `RawEntryMut::index`.
5+
16
- 2.2.1
27

38
- Corrected the signature of `RawOccupiedEntryMut::into_key(self) -> &'a mut K`,

src/map/core/raw_entry_v1.rs

Lines changed: 43 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -56,14 +56,18 @@ pub trait RawEntryApiV1<K, V, S>: private::Sealed {
5656
///
5757
/// for k in ["a", "b", "c", "d", "e", "f"] {
5858
/// let hash = compute_hash(map.hasher(), k);
59-
/// let v = map.get(k).cloned();
60-
/// let kv = v.as_ref().map(|v| (&k, v));
59+
/// let i = map.get_index_of(k);
60+
/// let v = map.get(k);
61+
/// let kv = map.get_key_value(k);
62+
/// let ikv = map.get_full(k);
6163
///
6264
/// println!("Key: {} and value: {:?}", k, v);
6365
///
6466
/// assert_eq!(map.raw_entry_v1().from_key(k), kv);
6567
/// assert_eq!(map.raw_entry_v1().from_hash(hash, |q| *q == k), kv);
6668
/// assert_eq!(map.raw_entry_v1().from_key_hashed_nocheck(hash, k), kv);
69+
/// assert_eq!(map.raw_entry_v1().from_hash_full(hash, |q| *q == k), ikv);
70+
/// assert_eq!(map.raw_entry_v1().index_from_hash(hash, |q| *q == k), i);
6771
/// }
6872
/// ```
6973
fn raw_entry_v1(&self) -> RawEntryBuilder<'_, K, V, S>;
@@ -116,6 +120,7 @@ pub trait RawEntryApiV1<K, V, S>: private::Sealed {
116120
/// match map.raw_entry_mut_v1().from_key("a") {
117121
/// RawEntryMut::Vacant(_) => unreachable!(),
118122
/// RawEntryMut::Occupied(mut view) => {
123+
/// assert_eq!(view.index(), 0);
119124
/// assert_eq!(view.get(), &100);
120125
/// let v = view.get_mut();
121126
/// let new_v = (*v) * 10;
@@ -132,6 +137,7 @@ pub trait RawEntryApiV1<K, V, S>: private::Sealed {
132137
/// match map.raw_entry_mut_v1().from_key_hashed_nocheck(hash, "c") {
133138
/// RawEntryMut::Vacant(_) => unreachable!(),
134139
/// RawEntryMut::Occupied(view) => {
140+
/// assert_eq!(view.index(), 2);
135141
/// assert_eq!(view.shift_remove_entry(), ("c", 300));
136142
/// }
137143
/// }
@@ -144,6 +150,7 @@ pub trait RawEntryApiV1<K, V, S>: private::Sealed {
144150
/// match map.raw_entry_mut_v1().from_hash(hash, |q| *q == key) {
145151
/// RawEntryMut::Occupied(_) => unreachable!(),
146152
/// RawEntryMut::Vacant(view) => {
153+
/// assert_eq!(view.index(), 2);
147154
/// let (k, value) = view.insert("d", 4000);
148155
/// assert_eq!((*k, *value), ("d", 4000));
149156
/// *value = 40000;
@@ -155,6 +162,7 @@ pub trait RawEntryApiV1<K, V, S>: private::Sealed {
155162
/// match map.raw_entry_mut_v1().from_hash(hash, |q| *q == key) {
156163
/// RawEntryMut::Vacant(_) => unreachable!(),
157164
/// RawEntryMut::Occupied(view) => {
165+
/// assert_eq!(view.index(), 2);
158166
/// assert_eq!(view.swap_remove_entry(), ("d", 40000));
159167
/// }
160168
/// }
@@ -205,19 +213,39 @@ impl<'a, K, V, S> RawEntryBuilder<'a, K, V, S> {
205213
{
206214
let hash = HashValue(hash as usize);
207215
let i = self.map.core.get_index_of(hash, key)?;
208-
Some(self.map.core.entries[i].refs())
216+
self.map.get_index(i)
209217
}
210218

211219
/// Access an entry by hash.
212-
pub fn from_hash<F>(self, hash: u64, mut is_match: F) -> Option<(&'a K, &'a V)>
220+
pub fn from_hash<F>(self, hash: u64, is_match: F) -> Option<(&'a K, &'a V)>
221+
where
222+
F: FnMut(&K) -> bool,
223+
{
224+
let map = self.map;
225+
let i = self.index_from_hash(hash, is_match)?;
226+
map.get_index(i)
227+
}
228+
229+
/// Access an entry by hash, including its index.
230+
pub fn from_hash_full<F>(self, hash: u64, is_match: F) -> Option<(usize, &'a K, &'a V)>
231+
where
232+
F: FnMut(&K) -> bool,
233+
{
234+
let map = self.map;
235+
let i = self.index_from_hash(hash, is_match)?;
236+
let (key, value) = map.get_index(i)?;
237+
Some((i, key, value))
238+
}
239+
240+
/// Access the index of an entry by hash.
241+
pub fn index_from_hash<F>(self, hash: u64, mut is_match: F) -> Option<usize>
213242
where
214243
F: FnMut(&K) -> bool,
215244
{
216245
let hash = HashValue(hash as usize);
217246
let entries = &*self.map.core.entries;
218247
let eq = move |&i: &usize| is_match(&entries[i].key);
219-
let i = *self.map.core.indices.get(hash.get(), eq)?;
220-
Some(entries[i].refs())
248+
self.map.core.indices.get(hash.get(), eq).copied()
221249
}
222250
}
223251

@@ -294,6 +322,15 @@ impl<K: fmt::Debug, V: fmt::Debug, S> fmt::Debug for RawEntryMut<'_, K, V, S> {
294322
}
295323

296324
impl<'a, K, V, S> RawEntryMut<'a, K, V, S> {
325+
/// Return the index where the key-value pair exists or may be inserted.
326+
#[inline]
327+
pub fn index(&self) -> usize {
328+
match self {
329+
Self::Occupied(entry) => entry.index(),
330+
Self::Vacant(entry) => entry.index(),
331+
}
332+
}
333+
297334
/// Inserts the given default key and value in the entry if it is vacant and returns mutable
298335
/// references to them. Otherwise mutable references to an already existent pair are returned.
299336
pub fn or_insert(self, default_key: K, default_value: V) -> (&'a mut K, &'a mut V)

0 commit comments

Comments
 (0)