Skip to content

Commit 62a1ae2

Browse files
committed
Auto merge of #118 - passcod:map-entry-insert, r=Amanieu
Add RustcVacantEntry::insert_entry for rust-lang/rust#64656 See rust-lang/rust#64656. ~~This was based on v0.5.0 as that's what rustc uses; I can rebase onto master, but I'm not sure whether rustc wants v0.6.0 or if v0.6.0 is rustc-ready.~~ For context, this ultimately provides an API with this shape: ```rust impl Entry<'a, K, V> { fn insert(self, value: V) -> OccupiedEntry<'a, K, V> {…} } ``` to be used when one wants to insert a value without consuming the Entry, e.g. because one wants to keep a reference to the key around. There's more at the original (defunct) PR: rust-lang/rust#60142.
2 parents 31ec80e + ecbdeb9 commit 62a1ae2

File tree

2 files changed

+138
-0
lines changed

2 files changed

+138
-0
lines changed

src/map.rs

+90
Original file line numberDiff line numberDiff line change
@@ -1433,6 +1433,33 @@ where
14331433
}
14341434

14351435
impl<'a, K, V, S> RawEntryMut<'a, K, V, S> {
1436+
/// Sets the value of the entry, and returns a RawOccupiedEntryMut.
1437+
///
1438+
/// # Examples
1439+
///
1440+
/// ```
1441+
/// use hashbrown::HashMap;
1442+
///
1443+
/// let mut map: HashMap<&str, u32> = HashMap::new();
1444+
/// let entry = map.raw_entry_mut().from_key("horseyland").insert("horseyland", 37);
1445+
///
1446+
/// assert_eq!(entry.remove_entry(), ("horseyland", 37));
1447+
/// ```
1448+
#[inline]
1449+
pub fn insert(self, key: K, value: V) -> RawOccupiedEntryMut<'a, K, V>
1450+
where
1451+
K: Hash,
1452+
S: BuildHasher,
1453+
{
1454+
match self {
1455+
RawEntryMut::Occupied(mut entry) => {
1456+
entry.insert(value);
1457+
entry
1458+
}
1459+
RawEntryMut::Vacant(entry) => entry.insert_entry(key, value),
1460+
}
1461+
}
1462+
14361463
/// Ensures a value is in the entry by inserting the default if empty, and returns
14371464
/// mutable references to the key and value in the entry.
14381465
///
@@ -1674,6 +1701,25 @@ impl<'a, K, V, S> RawVacantEntryMut<'a, K, V, S> {
16741701
(k, v)
16751702
}
16761703
}
1704+
1705+
#[inline]
1706+
fn insert_entry(self, key: K, value: V) -> RawOccupiedEntryMut<'a, K, V>
1707+
where
1708+
K: Hash,
1709+
S: BuildHasher,
1710+
{
1711+
let hash_builder = self.hash_builder;
1712+
let mut hasher = self.hash_builder.build_hasher();
1713+
key.hash(&mut hasher);
1714+
1715+
let elem = self.table.insert(hasher.finish(), (key, value), |k| {
1716+
make_hash(hash_builder, &k.0)
1717+
});
1718+
RawOccupiedEntryMut {
1719+
elem,
1720+
table: self.table,
1721+
}
1722+
}
16771723
}
16781724

16791725
impl<K, V, S> Debug for RawEntryBuilderMut<'_, K, V, S> {
@@ -2018,6 +2064,33 @@ where
20182064
}
20192065

20202066
impl<'a, K, V, S> Entry<'a, K, V, S> {
2067+
/// Sets the value of the entry, and returns an OccupiedEntry.
2068+
///
2069+
/// # Examples
2070+
///
2071+
/// ```
2072+
/// use hashbrown::HashMap;
2073+
///
2074+
/// let mut map: HashMap<&str, u32> = HashMap::new();
2075+
/// let entry = map.entry("horseyland").insert(37);
2076+
///
2077+
/// assert_eq!(entry.key(), &"horseyland");
2078+
/// ```
2079+
#[inline]
2080+
pub fn insert(self, value: V) -> OccupiedEntry<'a, K, V, S>
2081+
where
2082+
K: Hash,
2083+
S: BuildHasher,
2084+
{
2085+
match self {
2086+
Entry::Occupied(mut entry) => {
2087+
entry.insert(value);
2088+
entry
2089+
}
2090+
Entry::Vacant(entry) => entry.insert_entry(value),
2091+
}
2092+
}
2093+
20212094
/// Ensures a value is in the entry by inserting the default if empty, and returns
20222095
/// a mutable reference to the value in the entry.
20232096
///
@@ -2449,6 +2522,23 @@ impl<'a, K, V, S> VacantEntry<'a, K, V, S> {
24492522
});
24502523
unsafe { &mut bucket.as_mut().1 }
24512524
}
2525+
2526+
#[inline]
2527+
fn insert_entry(self, value: V) -> OccupiedEntry<'a, K, V, S>
2528+
where
2529+
K: Hash,
2530+
S: BuildHasher,
2531+
{
2532+
let hash_builder = &self.table.hash_builder;
2533+
let elem = self.table.table.insert(self.hash, (self.key, value), |x| {
2534+
make_hash(hash_builder, &x.0)
2535+
});
2536+
OccupiedEntry {
2537+
key: None,
2538+
elem,
2539+
table: self.table,
2540+
}
2541+
}
24522542
}
24532543

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

src/rustc_entry.rs

+48
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,28 @@ impl<K: Debug, V> Debug for RustcVacantEntry<'_, K, V> {
125125
}
126126

127127
impl<'a, K, V> RustcEntry<'a, K, V> {
128+
/// Sets the value of the entry, and returns a RustcOccupiedEntry.
129+
///
130+
/// # Examples
131+
///
132+
/// ```
133+
/// use hashbrown::HashMap;
134+
///
135+
/// let mut map: HashMap<&str, u32> = HashMap::new();
136+
/// let entry = map.entry("horseyland").insert(37);
137+
///
138+
/// assert_eq!(entry.key(), &"horseyland");
139+
/// ```
140+
pub fn insert(self, value: V) -> RustcOccupiedEntry<'a, K, V> {
141+
match self {
142+
Vacant(entry) => entry.insert_entry(value),
143+
Occupied(mut entry) => {
144+
entry.insert(value);
145+
entry
146+
}
147+
}
148+
}
149+
128150
/// Ensures a value is in the entry by inserting the default if empty, and returns
129151
/// a mutable reference to the value in the entry.
130152
///
@@ -546,6 +568,32 @@ impl<'a, K, V> RustcVacantEntry<'a, K, V> {
546568
let bucket = self.table.insert_no_grow(self.hash, (self.key, value));
547569
unsafe { &mut bucket.as_mut().1 }
548570
}
571+
572+
/// Sets the value of the entry with the RustcVacantEntry's key,
573+
/// and returns a RustcOccupiedEntry.
574+
///
575+
/// # Examples
576+
///
577+
/// ```
578+
/// use hashbrown::HashMap;
579+
/// use hashbrown::hash_map::RustcEntry;
580+
///
581+
/// let mut map: HashMap<&str, u32> = HashMap::new();
582+
///
583+
/// if let RustcEntry::Vacant(v) = map.rustc_entry("poneyland") {
584+
/// let o = v.insert_entry(37);
585+
/// assert_eq!(o.get(), &37);
586+
/// }
587+
/// ```
588+
#[inline]
589+
pub fn insert_entry(self, value: V) -> RustcOccupiedEntry<'a, K, V> {
590+
let bucket = self.table.insert_no_grow(self.hash, (self.key, value));
591+
RustcOccupiedEntry {
592+
key: None,
593+
elem: bucket,
594+
table: self.table,
595+
}
596+
}
549597
}
550598

551599
impl<K, V> IterMut<'_, K, V> {

0 commit comments

Comments
 (0)