@@ -497,6 +497,50 @@ impl<K, V, S> HashMap<K, V, S> {
497497 Drain { base : self . base . drain ( ) }
498498 }
499499
500+ /// Creates an iterator which uses a closure to determine if an element should be removed.
501+ ///
502+ /// If the closure returns true, the element is removed from the map and yielded.
503+ /// If the closure returns false, or panics, the element remains in the map and will not be
504+ /// yielded.
505+ ///
506+ /// Note that `drain_filter` lets you mutate every value in the filter closure, regardless of
507+ /// whether you choose to keep or remove it.
508+ ///
509+ /// If the iterator is only partially consumed or not consumed at all, each of the remaining
510+ /// elements will still be subjected to the closure and removed and dropped if it returns true.
511+ ///
512+ /// It is unspecified how many more elements will be subjected to the closure
513+ /// if a panic occurs in the closure, or a panic occurs while dropping an element,
514+ /// or if the `DrainFilter` value is leaked.
515+ ///
516+ /// # Examples
517+ ///
518+ /// Splitting a map into even and odd keys, reusing the original map:
519+ ///
520+ /// ```
521+ /// #![feature(hash_drain_filter)]
522+ /// use std::collections::HashMap;
523+ ///
524+ /// let mut map: HashMap<i32, i32> = (0..8).map(|x| (x, x)).collect();
525+ /// let drained: HashMap<i32, i32> = map.drain_filter(|k, _v| k % 2 == 0).collect();
526+ ///
527+ /// let mut evens = drained.keys().copied().collect::<Vec<_>>();
528+ /// let mut odds = map.keys().copied().collect::<Vec<_>>();
529+ /// evens.sort();
530+ /// odds.sort();
531+ ///
532+ /// assert_eq!(evens, vec![0, 2, 4, 6]);
533+ /// assert_eq!(odds, vec![1, 3, 5, 7]);
534+ /// ```
535+ #[ inline]
536+ #[ unstable( feature = "hash_drain_filter" , issue = "59618" ) ]
537+ pub fn drain_filter < F > ( & mut self , pred : F ) -> DrainFilter < ' _ , K , V , F >
538+ where
539+ F : FnMut ( & K , & mut V ) -> bool ,
540+ {
541+ DrainFilter { base : self . base . drain_filter ( pred) }
542+ }
543+
500544 /// Clears the map, removing all key-value pairs. Keeps the allocated memory
501545 /// for reuse.
502546 ///
@@ -1190,6 +1234,19 @@ impl<'a, K, V> Drain<'a, K, V> {
11901234 }
11911235}
11921236
1237+ /// A draining, filtering iterator over the entries of a `HashMap`.
1238+ ///
1239+ /// This `struct` is created by the [`drain_filter`] method on [`HashMap`].
1240+ ///
1241+ /// [`drain_filter`]: HashMap::drain_filter
1242+ #[ unstable( feature = "hash_drain_filter" , issue = "59618" ) ]
1243+ pub struct DrainFilter < ' a , K , V , F >
1244+ where
1245+ F : FnMut ( & K , & mut V ) -> bool ,
1246+ {
1247+ base : base:: DrainFilter < ' a , K , V , F > ,
1248+ }
1249+
11931250/// A mutable iterator over the values of a `HashMap`.
11941251///
11951252/// This `struct` is created by the [`values_mut`] method on [`HashMap`]. See its
@@ -1247,16 +1304,16 @@ pub struct RawEntryBuilderMut<'a, K: 'a, V: 'a, S: 'a> {
12471304#[ unstable( feature = "hash_raw_entry" , issue = "56167" ) ]
12481305pub enum RawEntryMut < ' a , K : ' a , V : ' a , S : ' a > {
12491306 /// An occupied entry.
1250- Occupied ( RawOccupiedEntryMut < ' a , K , V > ) ,
1307+ Occupied ( RawOccupiedEntryMut < ' a , K , V , S > ) ,
12511308 /// A vacant entry.
12521309 Vacant ( RawVacantEntryMut < ' a , K , V , S > ) ,
12531310}
12541311
12551312/// A view into an occupied entry in a `HashMap`.
12561313/// It is part of the [`RawEntryMut`] enum.
12571314#[ unstable( feature = "hash_raw_entry" , issue = "56167" ) ]
1258- pub struct RawOccupiedEntryMut < ' a , K : ' a , V : ' a > {
1259- base : base:: RawOccupiedEntryMut < ' a , K , V > ,
1315+ pub struct RawOccupiedEntryMut < ' a , K : ' a , V : ' a , S : ' a > {
1316+ base : base:: RawOccupiedEntryMut < ' a , K , V , S > ,
12601317}
12611318
12621319/// A view into a vacant entry in a `HashMap`.
@@ -1457,7 +1514,7 @@ impl<'a, K, V, S> RawEntryMut<'a, K, V, S> {
14571514 }
14581515}
14591516
1460- impl < ' a , K , V > RawOccupiedEntryMut < ' a , K , V > {
1517+ impl < ' a , K , V , S > RawOccupiedEntryMut < ' a , K , V , S > {
14611518 /// Gets a reference to the key in the entry.
14621519 #[ inline]
14631520 #[ unstable( feature = "hash_raw_entry" , issue = "56167" ) ]
@@ -1597,7 +1654,7 @@ impl<K: Debug, V: Debug, S> Debug for RawEntryMut<'_, K, V, S> {
15971654}
15981655
15991656#[ unstable( feature = "hash_raw_entry" , issue = "56167" ) ]
1600- impl < K : Debug , V : Debug > Debug for RawOccupiedEntryMut < ' _ , K , V > {
1657+ impl < K : Debug , V : Debug , S > Debug for RawOccupiedEntryMut < ' _ , K , V , S > {
16011658 fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
16021659 f. debug_struct ( "RawOccupiedEntryMut" )
16031660 . field ( "key" , self . key ( ) )
@@ -1990,6 +2047,36 @@ where
19902047 }
19912048}
19922049
2050+ #[ unstable( feature = "hash_drain_filter" , issue = "59618" ) ]
2051+ impl < K , V , F > Iterator for DrainFilter < ' _ , K , V , F >
2052+ where
2053+ F : FnMut ( & K , & mut V ) -> bool ,
2054+ {
2055+ type Item = ( K , V ) ;
2056+
2057+ #[ inline]
2058+ fn next ( & mut self ) -> Option < ( K , V ) > {
2059+ self . base . next ( )
2060+ }
2061+ #[ inline]
2062+ fn size_hint ( & self ) -> ( usize , Option < usize > ) {
2063+ self . base . size_hint ( )
2064+ }
2065+ }
2066+
2067+ #[ unstable( feature = "hash_drain_filter" , issue = "59618" ) ]
2068+ impl < K , V , F > FusedIterator for DrainFilter < ' _ , K , V , F > where F : FnMut ( & K , & mut V ) -> bool { }
2069+
2070+ #[ unstable( feature = "hash_drain_filter" , issue = "59618" ) ]
2071+ impl < ' a , K , V , F > fmt:: Debug for DrainFilter < ' a , K , V , F >
2072+ where
2073+ F : FnMut ( & K , & mut V ) -> bool ,
2074+ {
2075+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
2076+ f. pad ( "DrainFilter { .. }" )
2077+ }
2078+ }
2079+
19932080impl < ' a , K , V > Entry < ' a , K , V > {
19942081 #[ stable( feature = "rust1" , since = "1.0.0" ) ]
19952082 /// Ensures a value is in the entry by inserting the default if empty, and returns
@@ -2698,7 +2785,7 @@ fn map_entry<'a, K: 'a, V: 'a>(raw: base::RustcEntry<'a, K, V>) -> Entry<'a, K,
26982785}
26992786
27002787#[ inline]
2701- fn map_try_reserve_error ( err : hashbrown:: TryReserveError ) -> TryReserveError {
2788+ pub ( super ) fn map_try_reserve_error ( err : hashbrown:: TryReserveError ) -> TryReserveError {
27022789 match err {
27032790 hashbrown:: TryReserveError :: CapacityOverflow => TryReserveError :: CapacityOverflow ,
27042791 hashbrown:: TryReserveError :: AllocError { layout } => {
0 commit comments