Skip to content

Commit 5b9c757

Browse files
committed
HashMap: #or_default_entry and #or_insert_entry
I often find myself in a situation where I would like to insert a key into a map via `#entry_ref` and then use the key from the resulting entry. ``` // Get a byte slice from a buffer let key = client.request.get(index); // Insert the value (default) let mut entry = match queues.entry_ref(&key) { EntryRef::Occupied(entry) => entry, EntryRef::Vacant(entry) => entry.insert_entry(Default::default()), }; // Use the value entry.get_mut().insert_back(client.id); // Reuse the key instead of copying the bytes again keys.insert(client.id, entry.key()); ``` This is common enough that I'd love to have functions for it, similar to `insert_entry`. ``` // Get a byte slice from a buffer let key = client.request.get(index); // Insert the value (default) let mut entry = queues.entry_ref(&key).or_default_entry(); // Use the value entry.get_mut().insert_back(client.id); // Reuse the key instead of copying the bytes again keys.insert(client.id, entry.key()); ```
1 parent 25365fc commit 5b9c757

File tree

1 file changed

+65
-0
lines changed

1 file changed

+65
-0
lines changed

src/map.rs

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3527,6 +3527,38 @@ impl<'a, K, V, S, A: Allocator> Entry<'a, K, V, S, A> {
35273527
}
35283528
}
35293529

3530+
/// Ensures a value is in the entry by inserting the default if empty,
3531+
/// and returns an [`OccupiedEntry`].
3532+
///
3533+
/// # Examples
3534+
///
3535+
/// ```
3536+
/// use hashbrown::HashMap;
3537+
///
3538+
/// let mut map: HashMap<&str, u32> = HashMap::new();
3539+
///
3540+
/// // nonexistent key
3541+
/// let entry = map.entry("poneyland").or_insert_entry(3);
3542+
/// assert_eq!(entry.key(), &"poneyland");
3543+
/// assert_eq!(entry.get(), &3);
3544+
///
3545+
/// // existing key
3546+
/// let mut entry = map.entry("poneyland").or_insert_entry(10);
3547+
/// assert_eq!(entry.key(), &"poneyland");
3548+
/// assert_eq!(entry.get(), &3);
3549+
/// ```
3550+
#[cfg_attr(feature = "inline-more", inline)]
3551+
pub fn or_insert_entry(self, default: V) -> OccupiedEntry<'a, K, V, S, A>
3552+
where
3553+
K: Hash,
3554+
S: BuildHasher,
3555+
{
3556+
match self {
3557+
Entry::Occupied(entry) => entry,
3558+
Entry::Vacant(entry) => entry.insert_entry(default),
3559+
}
3560+
}
3561+
35303562
/// Ensures a value is in the entry by inserting the result of the default function if empty,
35313563
/// and returns a mutable reference to the value in the entry.
35323564
///
@@ -4328,6 +4360,39 @@ impl<'a, 'b, K, Q: ?Sized, V: Default, S, A: Allocator> EntryRef<'a, 'b, K, Q, V
43284360
EntryRef::Vacant(entry) => entry.insert(Default::default()),
43294361
}
43304362
}
4363+
4364+
/// Ensures a value is in the entry by inserting the default value if empty,
4365+
/// and returns an [`OccupiedEntry`].
4366+
///
4367+
/// # Examples
4368+
///
4369+
/// ```
4370+
/// use hashbrown::HashMap;
4371+
///
4372+
/// let mut map: HashMap<String, Option<u32>> = HashMap::new();
4373+
///
4374+
/// // nonexistent key
4375+
/// let entry = map.entry_ref("poneyland").or_default_entry();
4376+
/// assert_eq!(entry.key(), &"poneyland");
4377+
/// assert_eq!(entry.get(), &None);
4378+
///
4379+
/// // existing key
4380+
/// map.insert("horseland".to_string(), Some(3));
4381+
/// let entry = map.entry_ref("horseland").or_default_entry();
4382+
/// assert_eq!(entry.key(), &"horseland");
4383+
/// assert_eq!(entry.get(), &Some(3));
4384+
/// ```
4385+
#[cfg_attr(feature = "inline-more", inline)]
4386+
pub fn or_default_entry(self) -> OccupiedEntry<'a, K, V, S, A>
4387+
where
4388+
K: Hash + From<&'b Q>,
4389+
S: BuildHasher,
4390+
{
4391+
match self {
4392+
EntryRef::Occupied(entry) => entry,
4393+
EntryRef::Vacant(entry) => entry.insert_entry(Default::default()),
4394+
}
4395+
}
43314396
}
43324397

43334398
impl<'a, 'b, K, Q: ?Sized, V, S, A: Allocator> VacantEntryRef<'a, 'b, K, Q, V, S, A> {

0 commit comments

Comments
 (0)