Skip to content

Commit 15974e3

Browse files
committed
Add hash_map::{OccupiedEntry::into_entry, VacantEntryRef::insert_entry_with_key}
1 parent bba4a01 commit 15974e3

File tree

1 file changed

+88
-11
lines changed

1 file changed

+88
-11
lines changed

src/map.rs

Lines changed: 88 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3963,6 +3963,42 @@ impl<'a, K, V, S, A: Allocator> OccupiedEntry<'a, K, V, S, A> {
39633963
unsafe { &mut self.elem.as_mut().1 }
39643964
}
39653965

3966+
/// Converts the `OccupiedEntry` into a reference to the key and a
3967+
/// mutable reference to the value in the entry with a lifetime bound to the
3968+
/// map itself.
3969+
///
3970+
/// If you need multiple references to the `OccupiedEntry`, see [`key`] and
3971+
/// [`get_mut`].
3972+
///
3973+
/// [`key`]: Self::key
3974+
/// [`get_mut`]: Self::get_mut
3975+
///
3976+
/// # Examples
3977+
///
3978+
/// ```
3979+
/// use hashbrown::hash_map::{Entry, HashMap};
3980+
///
3981+
/// let mut map: HashMap<&str, u32> = HashMap::new();
3982+
/// map.entry("poneyland").or_insert(12);
3983+
///
3984+
/// assert_eq!(map["poneyland"], 12);
3985+
///
3986+
/// let key_val: (&&str, &mut u32);
3987+
/// match map.entry("poneyland") {
3988+
/// Entry::Occupied(entry) => key_val = entry.into_entry(),
3989+
/// Entry::Vacant(_) => panic!(),
3990+
/// }
3991+
/// *key_val.1 += 10;
3992+
///
3993+
/// assert_eq!(key_val, (&"poneyland", &mut 22));
3994+
/// assert_eq!(map["poneyland"], 22);
3995+
/// ```
3996+
#[cfg_attr(feature = "inline-more", inline)]
3997+
pub fn into_entry(self) -> (&'a K, &'a mut V) {
3998+
let (key, val) = self.inner.into_mut();
3999+
(key, val)
4000+
}
4001+
39664002
/// Sets the value of the entry, and returns the entry's old value.
39674003
///
39684004
/// # Examples
@@ -4535,17 +4571,7 @@ impl<'map, 'key, K, Q: ?Sized, V, S, A: Allocator> VacantEntryRef<'map, 'key, K,
45354571
Q: Equivalent<K>,
45364572
S: BuildHasher,
45374573
{
4538-
let table = &mut self.table.table;
4539-
assert!(
4540-
(self.key).equivalent(&key),
4541-
"key used for Entry creation is not equivalent to the one used for insertion"
4542-
);
4543-
let entry = table.insert_entry(
4544-
self.hash,
4545-
(key, value),
4546-
make_hasher::<_, V, S>(&self.table.hash_builder),
4547-
);
4548-
&mut entry.1
4574+
self.insert_entry_with_key(key, value).into_mut()
45494575
}
45504576

45514577
/// Sets the value of the entry with the [`VacantEntryRef`]'s key,
@@ -4582,6 +4608,57 @@ impl<'map, 'key, K, Q: ?Sized, V, S, A: Allocator> VacantEntryRef<'map, 'key, K,
45824608
table: self.table,
45834609
}
45844610
}
4611+
4612+
/// Sets the key and value of the entry and returns an [`OccupiedEntry`].
4613+
///
4614+
/// Unlike [`VacantEntryRef::insert_entry`], this method allows the key to
4615+
/// be explicitly specified, which is useful for key types that don't
4616+
/// implement `K: From<&Q>`.
4617+
///
4618+
/// # Panics
4619+
///
4620+
/// This method panics if `key` is not equivalent to the key used to create
4621+
/// the `VacantEntryRef`.
4622+
///
4623+
/// # Example
4624+
///
4625+
/// ```
4626+
/// use hashbrown::hash_map::EntryRef;
4627+
/// use hashbrown::HashMap;
4628+
///
4629+
/// let mut map = HashMap::<(String, String), char>::new();
4630+
/// let k = ("c".to_string(), "C".to_string());
4631+
/// let v = match map.entry_ref(&k) {
4632+
/// // Insert cannot be used here because tuples do not implement From.
4633+
/// // However this works because we can manually clone instead.
4634+
/// EntryRef::Vacant(r) => r.insert_entry_with_key(k.clone(), 'c'),
4635+
/// // In this branch we avoid the clone.
4636+
/// EntryRef::Occupied(r) => r,
4637+
/// };
4638+
/// assert_eq!(r.get(), 'c');
4639+
/// ```
4640+
#[cfg_attr(feature = "inline-more", inline)]
4641+
pub fn insert_entry_with_key(self, key: K, value: V) -> OccupiedEntry<'map, K, V, S, A>
4642+
where
4643+
K: Hash,
4644+
Q: Equivalent<K>,
4645+
S: BuildHasher,
4646+
{
4647+
assert!(
4648+
(self.key).equivalent(&key),
4649+
"key used for Entry creation is not equivalent to the one used for insertion"
4650+
);
4651+
let elem = self.table.table.insert(
4652+
self.hash,
4653+
(key, value),
4654+
make_hasher::<_, V, S>(&self.table.hash_builder),
4655+
);
4656+
OccupiedEntry {
4657+
hash: self.hash,
4658+
elem,
4659+
table: self.table,
4660+
}
4661+
}
45854662
}
45864663

45874664
impl<K, V, S, A> FromIterator<(K, V)> for HashMap<K, V, S, A>

0 commit comments

Comments
 (0)