1+ #[ cfg( feature = "nightly" ) ]
2+ use crate :: raw:: array_assume_init_shim;
13use crate :: raw:: { Allocator , Bucket , Global , RawDrain , RawIntoIter , RawIter , RawTable } ;
24use crate :: TryReserveError ;
5+ #[ cfg( feature = "nightly" ) ]
6+ use crate :: UnavailableMutError ;
37use core:: borrow:: Borrow ;
48use core:: fmt:: { self , Debug } ;
59use core:: hash:: { BuildHasher , Hash } ;
610use core:: iter:: { FromIterator , FusedIterator } ;
711use core:: marker:: PhantomData ;
812use core:: mem;
13+ #[ cfg( feature = "nightly" ) ]
14+ use core:: mem:: MaybeUninit ;
915use core:: ops:: Index ;
1016
1117/// Default hasher for `HashMap`.
@@ -1113,6 +1119,135 @@ where
11131119 self . table . get_mut ( hash, equivalent_key ( k) )
11141120 }
11151121
1122+ /// Attempts to get mutable references to `N` values in the map at once.
1123+ ///
1124+ /// Returns an array of length `N` with the results of each query. For soundness,
1125+ /// at most one mutable reference will be returned to any value. An
1126+ /// `Err(UnavailableMutError::Duplicate(i))` in the returned array indicates that a suitable
1127+ /// key-value pair exists, but a mutable reference to the value already occurs at index `i` in
1128+ /// the returned array.
1129+ ///
1130+ /// This method is available only if the `nightly` feature is enabled.
1131+ ///
1132+ /// ```
1133+ /// use hashbrown::{HashMap, UnavailableMutError};
1134+ ///
1135+ /// let mut libraries = HashMap::new();
1136+ /// libraries.insert("Bodleian Library".to_string(), 1602);
1137+ /// libraries.insert("Athenæum".to_string(), 1807);
1138+ /// libraries.insert("Herzogin-Anna-Amalia-Bibliothek".to_string(), 1691);
1139+ /// libraries.insert("Library of Congress".to_string(), 1800);
1140+ ///
1141+ /// let got = libraries.get_each_mut([
1142+ /// "Athenæum",
1143+ /// "New York Public Library",
1144+ /// "Athenæum",
1145+ /// "Library of Congress",
1146+ /// ]);
1147+ /// assert_eq!(
1148+ /// got,
1149+ /// [
1150+ /// Ok(&mut 1807),
1151+ /// Err(UnavailableMutError::Absent),
1152+ /// Err(UnavailableMutError::Duplicate(0)),
1153+ /// Ok(&mut 1800),
1154+ /// ]
1155+ /// );
1156+ /// ```
1157+ #[ cfg( feature = "nightly" ) ]
1158+ pub fn get_each_mut < Q : ?Sized , const N : usize > (
1159+ & mut self ,
1160+ ks : [ & Q ; N ] ,
1161+ ) -> [ Result < & ' _ mut V , UnavailableMutError > ; N ]
1162+ where
1163+ K : Borrow < Q > ,
1164+ Q : Hash + Eq ,
1165+ {
1166+ let mut pairs = self . get_each_inner_mut ( ks) ;
1167+ let mut out: [ MaybeUninit < Result < & ' _ mut V , UnavailableMutError > > ; N ] =
1168+ unsafe { MaybeUninit :: uninit ( ) . assume_init ( ) } ;
1169+ for i in 0 ..N {
1170+ out[ i] = MaybeUninit :: new (
1171+ mem:: replace ( & mut pairs[ i] , Err ( UnavailableMutError :: Absent ) ) . map ( |( _, v) | v) ,
1172+ ) ;
1173+ }
1174+ unsafe { array_assume_init_shim ( out) }
1175+ }
1176+
1177+ /// Attempts to get mutable references to `N` values in the map at once, with immutable
1178+ /// references to the corresponding keys.
1179+ ///
1180+ /// Returns an array of length `N` with the results of each query. For soundness,
1181+ /// at most one mutable reference will be returned to any value. An
1182+ /// `Err(UnavailableMutError::Duplicate)` in the returned array indicates that a suitable
1183+ /// key-value pair exists, but a mutable reference to the value already occurs at index `i` in
1184+ /// the returned array.
1185+ ///
1186+ /// This method is available only if the `nightly` feature is enabled.
1187+ ///
1188+ /// ```
1189+ /// use hashbrown::{HashMap, UnavailableMutError};
1190+ ///
1191+ /// let mut libraries = HashMap::new();
1192+ /// libraries.insert("Bodleian Library".to_string(), 1602);
1193+ /// libraries.insert("Athenæum".to_string(), 1807);
1194+ /// libraries.insert("Herzogin-Anna-Amalia-Bibliothek".to_string(), 1691);
1195+ /// libraries.insert("Library of Congress".to_string(), 1800);
1196+ ///
1197+ /// let got = libraries.get_each_key_value_mut([
1198+ /// "Bodleian Library",
1199+ /// "Herzogin-Anna-Amalia-Bibliothek",
1200+ /// "Herzogin-Anna-Amalia-Bibliothek",
1201+ /// "Gewandhaus",
1202+ /// ]);
1203+ /// assert_eq!(
1204+ /// got,
1205+ /// [
1206+ /// Ok((&"Bodleian Library".to_string(), &mut 1602)),
1207+ /// Ok((&"Herzogin-Anna-Amalia-Bibliothek".to_string(), &mut 1691)),
1208+ /// Err(UnavailableMutError::Duplicate(1)),
1209+ /// Err(UnavailableMutError::Absent),
1210+ /// ]
1211+ /// );
1212+ /// ```
1213+ #[ cfg( feature = "nightly" ) ]
1214+ pub fn get_each_key_value_mut < Q : ?Sized , const N : usize > (
1215+ & mut self ,
1216+ ks : [ & Q ; N ] ,
1217+ ) -> [ Result < ( & ' _ K , & ' _ mut V ) , UnavailableMutError > ; N ]
1218+ where
1219+ K : Borrow < Q > ,
1220+ Q : Hash + Eq ,
1221+ {
1222+ let mut pairs = self . get_each_inner_mut ( ks) ;
1223+ let mut out: [ MaybeUninit < Result < ( & ' _ K , & ' _ mut V ) , UnavailableMutError > > ; N ] =
1224+ unsafe { MaybeUninit :: uninit ( ) . assume_init ( ) } ;
1225+ for i in 0 ..N {
1226+ out[ i] = MaybeUninit :: new (
1227+ mem:: replace ( & mut pairs[ i] , Err ( UnavailableMutError :: Absent ) )
1228+ . map ( |( k, v) | ( & * k, v) ) ,
1229+ ) ;
1230+ }
1231+ unsafe { array_assume_init_shim ( out) }
1232+ }
1233+
1234+ #[ cfg( feature = "nightly" ) ]
1235+ fn get_each_inner_mut < Q : ?Sized , const N : usize > (
1236+ & mut self ,
1237+ ks : [ & Q ; N ] ,
1238+ ) -> [ Result < & ' _ mut ( K , V ) , UnavailableMutError > ; N ]
1239+ where
1240+ K : Borrow < Q > ,
1241+ Q : Hash + Eq ,
1242+ {
1243+ let mut hashes = [ 0_u64 ; N ] ;
1244+ for i in 0 ..N {
1245+ hashes[ i] = make_hash :: < K , Q , S > ( & self . hash_builder , ks[ i] ) ;
1246+ }
1247+ self . table
1248+ . get_each_mut ( hashes, |i, ( k, _) | ks[ i] . eq ( k. borrow ( ) ) )
1249+ }
1250+
11161251 /// Inserts a key-value pair into the map.
11171252 ///
11181253 /// If the map did not have this key present, [`None`] is returned.
@@ -3315,6 +3450,7 @@ mod test_map {
33153450 use super :: { HashMap , RawEntryMut } ;
33163451 use crate :: TryReserveError :: * ;
33173452 use rand:: { rngs:: SmallRng , Rng , SeedableRng } ;
3453+ use std:: borrow:: ToOwned ;
33183454 use std:: cell:: RefCell ;
33193455 use std:: usize;
33203456 use std:: vec:: Vec ;
@@ -4682,7 +4818,6 @@ mod test_map {
46824818 #[ test]
46834819 fn test_const_with_hasher ( ) {
46844820 use core:: hash:: BuildHasher ;
4685- use std:: borrow:: ToOwned ;
46864821 use std:: collections:: hash_map:: DefaultHasher ;
46874822
46884823 #[ derive( Clone ) ]
@@ -4702,4 +4837,33 @@ mod test_map {
47024837 map. insert ( 17 , "seventeen" . to_owned ( ) ) ;
47034838 assert_eq ! ( "seventeen" , map[ & 17 ] ) ;
47044839 }
4840+
4841+ #[ test]
4842+ #[ cfg( feature = "nightly" ) ]
4843+ fn test_get_each_mut ( ) {
4844+ use crate :: UnavailableMutError :: * ;
4845+
4846+ let mut map = HashMap :: new ( ) ;
4847+ map. insert ( "foo" . to_owned ( ) , 0 ) ;
4848+ map. insert ( "bar" . to_owned ( ) , 10 ) ;
4849+ map. insert ( "baz" . to_owned ( ) , 20 ) ;
4850+ map. insert ( "qux" . to_owned ( ) , 30 ) ;
4851+
4852+ let xs = map. get_each_mut ( [ "foo" , "dud" , "foo" , "qux" ] ) ;
4853+ assert_eq ! (
4854+ xs,
4855+ [ Ok ( & mut 0 ) , Err ( Absent ) , Err ( Duplicate ( 0 ) ) , Ok ( & mut 30 ) ]
4856+ ) ;
4857+
4858+ let ys = map. get_each_key_value_mut ( [ "bar" , "baz" , "baz" , "dip" ] ) ;
4859+ assert_eq ! (
4860+ ys,
4861+ [
4862+ Ok ( ( & "bar" . to_owned( ) , & mut 10 ) ) ,
4863+ Ok ( ( & "baz" . to_owned( ) , & mut 20 ) ) ,
4864+ Err ( Duplicate ( 1 ) ) ,
4865+ Err ( Absent ) ,
4866+ ]
4867+ ) ;
4868+ }
47054869}
0 commit comments