Skip to content

Commit 9b170c3

Browse files
authored
Merge pull request #579 from djugei/master
allow providing the key at insertion time for EntryRef
2 parents 01bb41c + 2712a86 commit 9b170c3

File tree

1 file changed

+58
-9
lines changed

1 file changed

+58
-9
lines changed

src/map.rs

Lines changed: 58 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3034,10 +3034,10 @@ where
30343034
/// }
30353035
/// assert!(map["b"] == 20 && map.len() == 2);
30363036
/// ```
3037-
pub struct VacantEntryRef<'a, 'b, K, Q: ?Sized, V, S, A: Allocator = Global> {
3037+
pub struct VacantEntryRef<'map, 'key, K, Q: ?Sized, V, S, A: Allocator = Global> {
30383038
hash: u64,
3039-
key: &'b Q,
3040-
table: &'a mut HashMap<K, V, S, A>,
3039+
key: &'key Q,
3040+
table: &'map mut HashMap<K, V, S, A>,
30413041
}
30423042

30433043
impl<K, Q, V, S, A> Debug for VacantEntryRef<'_, '_, K, Q, V, S, A>
@@ -4448,7 +4448,7 @@ impl<'a, 'b, K, Q: ?Sized, V: Default, S, A: Allocator> EntryRef<'a, 'b, K, Q, V
44484448
}
44494449
}
44504450

4451-
impl<'a, 'b, K, Q: ?Sized, V, S, A: Allocator> VacantEntryRef<'a, 'b, K, Q, V, S, A> {
4451+
impl<'map, 'key, K, Q: ?Sized, V, S, A: Allocator> VacantEntryRef<'map, 'key, K, Q, V, S, A> {
44524452
/// Gets a reference to the key that would be used when inserting a value
44534453
/// through the `VacantEntryRef`.
44544454
///
@@ -4462,7 +4462,7 @@ impl<'a, 'b, K, Q: ?Sized, V, S, A: Allocator> VacantEntryRef<'a, 'b, K, Q, V, S
44624462
/// assert_eq!(map.entry_ref(key).key(), "poneyland");
44634463
/// ```
44644464
#[cfg_attr(feature = "inline-more", inline)]
4465-
pub fn key(&self) -> &'b Q {
4465+
pub fn key(&self) -> &'key Q {
44664466
self.key
44674467
}
44684468

@@ -4484,10 +4484,10 @@ impl<'a, 'b, K, Q: ?Sized, V, S, A: Allocator> VacantEntryRef<'a, 'b, K, Q, V, S
44844484
/// assert_eq!(map["poneyland"], 37);
44854485
/// ```
44864486
#[cfg_attr(feature = "inline-more", inline)]
4487-
pub fn insert(self, value: V) -> &'a mut V
4487+
pub fn insert(self, value: V) -> &'map mut V
44884488
where
44894489
K: Hash,
4490-
&'b Q: Into<K>,
4490+
&'key Q: Into<K>,
44914491
S: BuildHasher,
44924492
{
44934493
let table = &mut self.table.table;
@@ -4499,6 +4499,55 @@ impl<'a, 'b, K, Q: ?Sized, V, S, A: Allocator> VacantEntryRef<'a, 'b, K, Q, V, S
44994499
&mut entry.1
45004500
}
45014501

4502+
/// Sets the key and value of the entry and returns a mutable reference to
4503+
/// the inserted value.
4504+
///
4505+
/// Unlike [`VacantEntryRef::insert`], this method allows the key to be
4506+
/// explicitly specified, which is useful for key types that don't implement
4507+
/// `K: From<&Q>`.
4508+
///
4509+
/// # Panics
4510+
///
4511+
/// This method panics if `key` is not equivalent to the key used to create
4512+
/// the `VacantEntryRef`.
4513+
///
4514+
/// # Example
4515+
///
4516+
/// ```
4517+
/// use hashbrown::hash_map::EntryRef;
4518+
/// use hashbrown::HashMap;
4519+
///
4520+
/// let mut map = HashMap::<(String, String), char>::new();
4521+
/// let k = ("c".to_string(), "C".to_string());
4522+
/// let v = match map.entry_ref(&k) {
4523+
/// // Insert cannot be used here because tuples do not implement From.
4524+
/// // However this works because we can manually clone instead.
4525+
/// EntryRef::Vacant(r) => r.insert_with_key(k.clone(), 'c'),
4526+
/// // In this branch we avoid the clone.
4527+
/// EntryRef::Occupied(r) => r.into_mut(),
4528+
/// };
4529+
/// assert_eq!(*v, 'c');
4530+
/// ```
4531+
#[cfg_attr(feature = "inline-more", inline)]
4532+
pub fn insert_with_key(self, key: K, value: V) -> &'map mut V
4533+
where
4534+
K: Hash,
4535+
Q: Equivalent<K>,
4536+
S: BuildHasher,
4537+
{
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
4549+
}
4550+
45024551
/// Sets the value of the entry with the [`VacantEntryRef`]'s key,
45034552
/// and returns an [`OccupiedEntry`].
45044553
///
@@ -4516,10 +4565,10 @@ impl<'a, 'b, K, Q: ?Sized, V, S, A: Allocator> VacantEntryRef<'a, 'b, K, Q, V, S
45164565
/// }
45174566
/// ```
45184567
#[cfg_attr(feature = "inline-more", inline)]
4519-
pub fn insert_entry(self, value: V) -> OccupiedEntry<'a, K, V, S, A>
4568+
pub fn insert_entry(self, value: V) -> OccupiedEntry<'map, K, V, S, A>
45204569
where
45214570
K: Hash,
4522-
&'b Q: Into<K>,
4571+
&'key Q: Into<K>,
45234572
S: BuildHasher,
45244573
{
45254574
let elem = self.table.table.insert(

0 commit comments

Comments
 (0)