@@ -7,14 +7,22 @@ use std::collections::hash_map::RandomState;
77use std:: fmt;
88use std:: hash:: { BuildHasher , Hash } ;
99use std:: marker:: PhantomData ;
10+ use std:: mem:: ManuallyDrop ;
1011
1112/// A concurrent hash table.
1213///
1314/// Most hash table operations require a [`Guard`](crate::Guard), which can be acquired through
1415/// [`HashMap::guard`] or using the [`HashMap::pin`] API. See the [crate-level documentation](crate#usage)
1516/// for details.
1617pub struct HashMap < K , V , S = RandomState > {
17- raw : raw:: HashMap < K , V , S > ,
18+ raw : ManuallyDrop < raw:: HashMap < K , V , S > > ,
19+ }
20+
21+ impl < K , V , S > Drop for HashMap < K , V , S > {
22+ fn drop ( & mut self ) {
23+ // Safety: We don't access `self` after taking the inner map.
24+ raw:: drop_map ( unsafe { ManuallyDrop :: take ( & mut self . raw ) } ) ;
25+ }
1826}
1927
2028// Safety: `HashMap` acts as a single-threaded collection on a single thread.
@@ -131,7 +139,12 @@ impl<K, V, S> HashMapBuilder<K, V, S> {
131139 /// Construct a [`HashMap`] from the builder, using the configured options.
132140 pub fn build ( self ) -> HashMap < K , V , S > {
133141 HashMap {
134- raw : raw:: HashMap :: new ( self . capacity , self . hasher , self . collector , self . resize_mode ) ,
142+ raw : ManuallyDrop :: new ( raw:: HashMap :: new (
143+ self . capacity ,
144+ self . hasher ,
145+ self . collector ,
146+ self . resize_mode ,
147+ ) ) ,
135148 }
136149 }
137150}
@@ -251,7 +264,7 @@ impl<K, V, S> HashMap<K, V, S> {
251264 ///
252265 /// Warning: `hash_builder` is normally randomly generated, and is designed
253266 /// to allow HashMaps to be resistant to attacks that cause many collisions
254- /// and very poor performance. Setting it manually using this function can
267+ /// and very actuallypoor performance. Setting it manually using this function can
255268 /// expose a DoS attack vector.
256269 ///
257270 /// The `hash_builder` passed should implement the [`BuildHasher`] trait for
@@ -298,12 +311,12 @@ impl<K, V, S> HashMap<K, V, S> {
298311 /// ```
299312 pub fn with_capacity_and_hasher ( capacity : usize , hash_builder : S ) -> HashMap < K , V , S > {
300313 HashMap {
301- raw : raw:: HashMap :: new (
314+ raw : ManuallyDrop :: new ( raw:: HashMap :: new (
302315 capacity,
303316 hash_builder,
304317 Collector :: default ( ) ,
305318 ResizeMode :: default ( ) ,
306- ) ,
319+ ) ) ,
307320 }
308321 }
309322
@@ -1100,6 +1113,37 @@ where
11001113 }
11011114}
11021115
1116+ impl < K , V , S > IntoIterator for HashMap < K , V , S > {
1117+ type Item = ( K , V ) ;
1118+ type IntoIter = IntoIter < K , V > ;
1119+
1120+ /// Creates a consuming iterator, that is, one that moves each key-value
1121+ /// pair out of the map in arbitrary order. The map cannot be used after
1122+ /// calling this.
1123+ ///
1124+ /// ```
1125+ /// use papaya::HashMap;
1126+ ///
1127+ /// let map = HashMap::from([
1128+ /// ("a", 1),
1129+ /// ("b", 2),
1130+ /// ("c", 3),
1131+ /// ]);
1132+ ///
1133+ /// let v: Vec<(&str, i32)> = map.into_iter().collect();
1134+ /// ```
1135+ fn into_iter ( self ) -> Self :: IntoIter {
1136+ let mut map = ManuallyDrop :: new ( self ) ;
1137+
1138+ // Safety: We don't access `self` after taking the inner map.
1139+ let raw = unsafe { ManuallyDrop :: take ( & mut map. raw ) } ;
1140+
1141+ IntoIter {
1142+ raw : raw. into_iter ( ) ,
1143+ }
1144+ }
1145+ }
1146+
11031147/// An operation to perform on given entry in a [`HashMap`].
11041148///
11051149/// See [`HashMap::compute`] for details.
@@ -1194,7 +1238,8 @@ where
11941238 S : BuildHasher ,
11951239{
11961240 fn extend < T : IntoIterator < Item = ( K , V ) > > ( & mut self , iter : T ) {
1197- // from `hashbrown::HashMap::extend`:
1241+ // From `hashbrown::HashMap::extend`:
1242+ //
11981243 // Keys may be already present or show multiple times in the iterator.
11991244 // Reserve the entire hint lower bound if the map is empty.
12001245 // Otherwise reserve half the hint (rounded up), so the map
@@ -1620,18 +1665,22 @@ where
16201665 }
16211666}
16221667
1668+ impl < K , V , G > Clone for Iter < ' _ , K , V , G > {
1669+ fn clone ( & self ) -> Self {
1670+ Self {
1671+ raw : self . raw . clone ( ) ,
1672+ }
1673+ }
1674+ }
1675+
16231676impl < K , V , G > fmt:: Debug for Iter < ' _ , K , V , G >
16241677where
16251678 K : fmt:: Debug ,
16261679 V : fmt:: Debug ,
16271680 G : Guard ,
16281681{
16291682 fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
1630- f. debug_list ( )
1631- . entries ( Iter {
1632- raw : self . raw . clone ( ) ,
1633- } )
1634- . finish ( )
1683+ f. debug_list ( ) . entries ( self . raw . clone ( ) ) . finish ( )
16351684 }
16361685}
16371686
@@ -1657,12 +1706,7 @@ where
16571706 V : fmt:: Debug ,
16581707{
16591708 fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
1660- f. debug_list ( )
1661- . entries ( IterMut {
1662- // Safety: We only create a single clone.
1663- raw : unsafe { self . raw . clone ( ) } ,
1664- } )
1665- . finish ( )
1709+ f. debug_list ( ) . entries ( self . raw . iter ( ) ) . finish ( )
16661710 }
16671711}
16681712
@@ -1727,3 +1771,32 @@ where
17271771 f. debug_tuple ( "Values" ) . field ( & self . iter ) . finish ( )
17281772 }
17291773}
1774+
1775+ /// An owned iterator over the entries of a `HashMap`.
1776+ ///
1777+ /// This `struct` is created by the [`into_iter`] method on [`HashMap`]
1778+ /// (provided by the [`IntoIterator`] trait). See its documentation for more.
1779+ ///
1780+ /// [`into_iter`]: IntoIterator::into_iter
1781+ pub struct IntoIter < K , V > {
1782+ pub ( crate ) raw : raw:: IntoIter < K , V > ,
1783+ }
1784+
1785+ impl < K , V > Iterator for IntoIter < K , V > {
1786+ type Item = ( K , V ) ;
1787+
1788+ #[ inline]
1789+ fn next ( & mut self ) -> Option < Self :: Item > {
1790+ self . raw . next ( )
1791+ }
1792+ }
1793+
1794+ impl < K , V > fmt:: Debug for IntoIter < K , V >
1795+ where
1796+ K : fmt:: Debug ,
1797+ V : fmt:: Debug ,
1798+ {
1799+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
1800+ f. debug_list ( ) . entries ( self . raw . iter ( ) ) . finish ( )
1801+ }
1802+ }
0 commit comments