From f96b6b9f96e894853cba015101c1b26102349bf7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fe=CC=81lix=20Saparelli?= Date: Mon, 30 Sep 2019 19:31:55 +1300 Subject: [PATCH 1/2] Add Entry::insert backend for rust-lang/rust#64656 --- src/rustc_entry.rs | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/rustc_entry.rs b/src/rustc_entry.rs index fefa5c3f9a..d4c320be6c 100644 --- a/src/rustc_entry.rs +++ b/src/rustc_entry.rs @@ -546,6 +546,32 @@ impl<'a, K, V> RustcVacantEntry<'a, K, V> { let bucket = self.table.insert_no_grow(self.hash, (self.key, value)); unsafe { &mut bucket.as_mut().1 } } + + /// Sets the value of the entry with the RustcVacantEntry's key, + /// and returns a RustcOccupiedEntry. + /// + /// # Examples + /// + /// ``` + /// use hashbrown::HashMap; + /// use hashbrown::hash_map::RustcEntry; + /// + /// let mut map: HashMap<&str, u32> = HashMap::new(); + /// + /// if let RustcEntry::Vacant(v) = map.rustc_entry("poneyland") { + /// let o = v.insert_entry(37); + /// assert_eq!(o.get(), &37); + /// } + /// ``` + #[inline] + pub fn insert_entry(self, value: V) -> RustcOccupiedEntry<'a, K, V> { + let bucket = self.table.insert_no_grow(self.hash, (self.key, value)); + RustcOccupiedEntry { + key: None, + elem: bucket, + table: self.table, + } + } } impl IterMut<'_, K, V> { From ecbdeb96e1d95c46bf044482a98bad1dfcd4e2db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fe=CC=81lix=20Saparelli?= Date: Mon, 30 Sep 2019 23:51:37 +1300 Subject: [PATCH 2/2] Add ::insert to Entry, RustcEntry, and RawEntryMut --- src/map.rs | 90 ++++++++++++++++++++++++++++++++++++++++++++++ src/rustc_entry.rs | 22 ++++++++++++ 2 files changed, 112 insertions(+) diff --git a/src/map.rs b/src/map.rs index 822a51c3a4..eb95d48e60 100644 --- a/src/map.rs +++ b/src/map.rs @@ -1433,6 +1433,33 @@ where } impl<'a, K, V, S> RawEntryMut<'a, K, V, S> { + /// Sets the value of the entry, and returns a RawOccupiedEntryMut. + /// + /// # Examples + /// + /// ``` + /// use hashbrown::HashMap; + /// + /// let mut map: HashMap<&str, u32> = HashMap::new(); + /// let entry = map.raw_entry_mut().from_key("horseyland").insert("horseyland", 37); + /// + /// assert_eq!(entry.remove_entry(), ("horseyland", 37)); + /// ``` + #[inline] + pub fn insert(self, key: K, value: V) -> RawOccupiedEntryMut<'a, K, V> + where + K: Hash, + S: BuildHasher, + { + match self { + RawEntryMut::Occupied(mut entry) => { + entry.insert(value); + entry + } + RawEntryMut::Vacant(entry) => entry.insert_entry(key, value), + } + } + /// Ensures a value is in the entry by inserting the default if empty, and returns /// mutable references to the key and value in the entry. /// @@ -1674,6 +1701,25 @@ impl<'a, K, V, S> RawVacantEntryMut<'a, K, V, S> { (k, v) } } + + #[inline] + fn insert_entry(self, key: K, value: V) -> RawOccupiedEntryMut<'a, K, V> + where + K: Hash, + S: BuildHasher, + { + let hash_builder = self.hash_builder; + let mut hasher = self.hash_builder.build_hasher(); + key.hash(&mut hasher); + + let elem = self.table.insert(hasher.finish(), (key, value), |k| { + make_hash(hash_builder, &k.0) + }); + RawOccupiedEntryMut { + elem, + table: self.table, + } + } } impl Debug for RawEntryBuilderMut<'_, K, V, S> { @@ -2018,6 +2064,33 @@ where } impl<'a, K, V, S> Entry<'a, K, V, S> { + /// Sets the value of the entry, and returns an OccupiedEntry. + /// + /// # Examples + /// + /// ``` + /// use hashbrown::HashMap; + /// + /// let mut map: HashMap<&str, u32> = HashMap::new(); + /// let entry = map.entry("horseyland").insert(37); + /// + /// assert_eq!(entry.key(), &"horseyland"); + /// ``` + #[inline] + pub fn insert(self, value: V) -> OccupiedEntry<'a, K, V, S> + where + K: Hash, + S: BuildHasher, + { + match self { + Entry::Occupied(mut entry) => { + entry.insert(value); + entry + } + Entry::Vacant(entry) => entry.insert_entry(value), + } + } + /// Ensures a value is in the entry by inserting the default if empty, and returns /// a mutable reference to the value in the entry. /// @@ -2449,6 +2522,23 @@ impl<'a, K, V, S> VacantEntry<'a, K, V, S> { }); unsafe { &mut bucket.as_mut().1 } } + + #[inline] + fn insert_entry(self, value: V) -> OccupiedEntry<'a, K, V, S> + where + K: Hash, + S: BuildHasher, + { + let hash_builder = &self.table.hash_builder; + let elem = self.table.table.insert(self.hash, (self.key, value), |x| { + make_hash(hash_builder, &x.0) + }); + OccupiedEntry { + key: None, + elem, + table: self.table, + } + } } impl FromIterator<(K, V)> for HashMap diff --git a/src/rustc_entry.rs b/src/rustc_entry.rs index d4c320be6c..8cf0024e35 100644 --- a/src/rustc_entry.rs +++ b/src/rustc_entry.rs @@ -125,6 +125,28 @@ impl Debug for RustcVacantEntry<'_, K, V> { } impl<'a, K, V> RustcEntry<'a, K, V> { + /// Sets the value of the entry, and returns a RustcOccupiedEntry. + /// + /// # Examples + /// + /// ``` + /// use hashbrown::HashMap; + /// + /// let mut map: HashMap<&str, u32> = HashMap::new(); + /// let entry = map.entry("horseyland").insert(37); + /// + /// assert_eq!(entry.key(), &"horseyland"); + /// ``` + pub fn insert(self, value: V) -> RustcOccupiedEntry<'a, K, V> { + match self { + Vacant(entry) => entry.insert_entry(value), + Occupied(mut entry) => { + entry.insert(value); + entry + } + } + } + /// Ensures a value is in the entry by inserting the default if empty, and returns /// a mutable reference to the value in the entry. ///