1
+ #[ cfg( feature = "nightly" ) ]
2
+ use crate :: raw:: array_assume_init_shim;
1
3
use crate :: raw:: { Allocator , Bucket , Global , RawDrain , RawIntoIter , RawIter , RawTable } ;
2
4
use crate :: TryReserveError ;
5
+ #[ cfg( feature = "nightly" ) ]
6
+ use crate :: UnavailableMutError ;
3
7
use core:: borrow:: Borrow ;
4
8
use core:: fmt:: { self , Debug } ;
5
9
use core:: hash:: { BuildHasher , Hash } ;
6
10
use core:: iter:: { FromIterator , FusedIterator } ;
7
11
use core:: marker:: PhantomData ;
8
12
use core:: mem;
13
+ #[ cfg( feature = "nightly" ) ]
14
+ use core:: mem:: MaybeUninit ;
9
15
use core:: ops:: Index ;
10
16
11
17
/// Default hasher for `HashMap`.
@@ -1113,6 +1119,135 @@ where
1113
1119
self . table . get_mut ( hash, equivalent_key ( k) )
1114
1120
}
1115
1121
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(i))` 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
+
1116
1251
/// Inserts a key-value pair into the map.
1117
1252
///
1118
1253
/// If the map did not have this key present, [`None`] is returned.
@@ -3315,6 +3450,7 @@ mod test_map {
3315
3450
use super :: { HashMap , RawEntryMut } ;
3316
3451
use crate :: TryReserveError :: * ;
3317
3452
use rand:: { rngs:: SmallRng , Rng , SeedableRng } ;
3453
+ use std:: borrow:: ToOwned ;
3318
3454
use std:: cell:: RefCell ;
3319
3455
use std:: usize;
3320
3456
use std:: vec:: Vec ;
@@ -4682,7 +4818,6 @@ mod test_map {
4682
4818
#[ test]
4683
4819
fn test_const_with_hasher ( ) {
4684
4820
use core:: hash:: BuildHasher ;
4685
- use std:: borrow:: ToOwned ;
4686
4821
use std:: collections:: hash_map:: DefaultHasher ;
4687
4822
4688
4823
#[ derive( Clone ) ]
@@ -4702,4 +4837,33 @@ mod test_map {
4702
4837
map. insert ( 17 , "seventeen" . to_owned ( ) ) ;
4703
4838
assert_eq ! ( "seventeen" , map[ & 17 ] ) ;
4704
4839
}
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
+ }
4705
4869
}
0 commit comments