Skip to content

Commit 6272247

Browse files
committed
Add insert_with_key, allowing the user to provide the key at insertion time.
1 parent e514afe commit 6272247

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
@@ -2983,10 +2983,10 @@ where
29832983
/// }
29842984
/// assert!(map["b"] == 20 && map.len() == 2);
29852985
/// ```
2986-
pub struct VacantEntryRef<'a, 'b, K, Q: ?Sized, V, S, A: Allocator = Global> {
2986+
pub struct VacantEntryRef<'map, 'key, K, Q: ?Sized, V, S, A: Allocator = Global> {
29872987
hash: u64,
2988-
key: &'b Q,
2989-
table: &'a mut HashMap<K, V, S, A>,
2988+
key: &'key Q,
2989+
table: &'map mut HashMap<K, V, S, A>,
29902990
}
29912991

29922992
impl<K, Q, V, S, A> Debug for VacantEntryRef<'_, '_, K, Q, V, S, A>
@@ -4332,7 +4332,7 @@ impl<'a, 'b, K, Q: ?Sized, V: Default, S, A: Allocator> EntryRef<'a, 'b, K, Q, V
43324332
}
43334333
}
43344334

4335-
impl<'a, 'b, K, Q: ?Sized, V, S, A: Allocator> VacantEntryRef<'a, 'b, K, Q, V, S, A> {
4335+
impl<'map, 'key, K, Q: ?Sized, V, S, A: Allocator> VacantEntryRef<'map, 'key, K, Q, V, S, A> {
43364336
/// Gets a reference to the key that would be used when inserting a value
43374337
/// through the `VacantEntryRef`.
43384338
///
@@ -4346,7 +4346,7 @@ impl<'a, 'b, K, Q: ?Sized, V, S, A: Allocator> VacantEntryRef<'a, 'b, K, Q, V, S
43464346
/// assert_eq!(map.entry_ref(key).key(), "poneyland");
43474347
/// ```
43484348
#[cfg_attr(feature = "inline-more", inline)]
4349-
pub fn key(&self) -> &'b Q {
4349+
pub fn key(&self) -> &'key Q {
43504350
self.key
43514351
}
43524352

@@ -4368,10 +4368,10 @@ impl<'a, 'b, K, Q: ?Sized, V, S, A: Allocator> VacantEntryRef<'a, 'b, K, Q, V, S
43684368
/// assert_eq!(map["poneyland"], 37);
43694369
/// ```
43704370
#[cfg_attr(feature = "inline-more", inline)]
4371-
pub fn insert(self, value: V) -> &'a mut V
4371+
pub fn insert(self, value: V) -> &'map mut V
43724372
where
43734373
K: Hash,
4374-
&'b Q: Into<K>,
4374+
&'key Q: Into<K>,
43754375
S: BuildHasher,
43764376
{
43774377
let table = &mut self.table.table;
@@ -4383,6 +4383,55 @@ impl<'a, 'b, K, Q: ?Sized, V, S, A: Allocator> VacantEntryRef<'a, 'b, K, Q, V, S
43834383
&mut entry.1
43844384
}
43854385

4386+
/// [insert](Self::insert) a value by providing the key at insertion time.
4387+
/// Returns a mutable reference to the inserted value.
4388+
///
4389+
/// Useful if Into is not implemented for converting from &Q to K.
4390+
/// ```compile_fail
4391+
/// # use hashbrown::hash_map::EntryRef;
4392+
/// # use hashbrown::HashMap;
4393+
/// // note that our key is a (small) tuple
4394+
/// let mut h = HashMap::<(String,), char>::new();
4395+
/// let k = (String::from("c"),);
4396+
/// match h.entry_ref(&k) {
4397+
/// // fails here, as &(i32) does not implement Into<(i32)>
4398+
/// EntryRef::Vacant(r) => r.insert('c'),
4399+
/// EntryRef::Occupied(r) => r.get(),
4400+
/// };
4401+
/// ```
4402+
/// ```
4403+
/// # use hashbrown::hash_map::EntryRef;
4404+
/// # use hashbrown::HashMap;
4405+
/// let mut h = HashMap::<(String,), char>::new();
4406+
/// let k = (String::from("c"),);
4407+
/// match h.entry_ref(&k) {
4408+
/// // works, because we manually clone when needed.
4409+
/// EntryRef::Vacant(r) => r.insert_with_key(k.clone(),'c'),
4410+
/// // in this branch we avoided the clone
4411+
/// EntryRef::Occupied(r) => r.get(),
4412+
/// };
4413+
/// ```
4414+
///
4415+
#[cfg_attr(feature = "inline-more", inline)]
4416+
pub fn insert_with_key(self, key: K, value: V) -> &'map mut V
4417+
where
4418+
K: Hash,
4419+
Q: Equivalent<K>,
4420+
S: BuildHasher,
4421+
{
4422+
let table = &mut self.table.table;
4423+
assert!(
4424+
(self.key).equivalent(&key),
4425+
"The key used for Entry creation and the one used for insertion are not equivalent"
4426+
);
4427+
let entry = table.insert_entry(
4428+
self.hash,
4429+
(key, value),
4430+
make_hasher::<_, V, S>(&self.table.hash_builder),
4431+
);
4432+
&mut entry.1
4433+
}
4434+
43864435
/// Sets the value of the entry with the [`VacantEntryRef`]'s key,
43874436
/// and returns an [`OccupiedEntry`].
43884437
///
@@ -4400,10 +4449,10 @@ impl<'a, 'b, K, Q: ?Sized, V, S, A: Allocator> VacantEntryRef<'a, 'b, K, Q, V, S
44004449
/// }
44014450
/// ```
44024451
#[cfg_attr(feature = "inline-more", inline)]
4403-
pub fn insert_entry(self, value: V) -> OccupiedEntry<'a, K, V, S, A>
4452+
pub fn insert_entry(self, value: V) -> OccupiedEntry<'map, K, V, S, A>
44044453
where
44054454
K: Hash,
4406-
&'b Q: Into<K>,
4455+
&'key Q: Into<K>,
44074456
S: BuildHasher,
44084457
{
44094458
let elem = self.table.table.insert(

0 commit comments

Comments
 (0)