Skip to content

Commit c9c361a

Browse files
committed
Rename get_each_mut to get_many_mut and align API with the stdlib
The standard library will be gaining a similar [ability for slices][]. This updates Hashbrown's API to match that PR and use only stable `MaybeUninit` functions. [ability for slices]: rust-lang/rust#83608
1 parent f169c25 commit c9c361a

File tree

3 files changed

+244
-122
lines changed

3 files changed

+244
-122
lines changed

src/lib.rs

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -129,20 +129,6 @@ pub enum TryReserveError {
129129
},
130130
}
131131

132-
/// The error type for [`RawTable::get_each_mut`](crate::raw::RawTable::get_each_mut),
133-
/// [`HashMap::get_each_mut`], and [`HashMap::get_each_key_value_mut`].
134-
#[cfg(feature = "nightly")]
135-
#[derive(Clone, PartialEq, Eq, Debug)]
136-
pub enum UnavailableMutError {
137-
/// The requested entry is not present in the table.
138-
Absent,
139-
/// The requested entry is present, but a mutable reference to it was already created and
140-
/// returned from this call to `get_each_mut` or `get_each_key_value_mut`.
141-
///
142-
/// Includes the index of the existing mutable reference in the returned array.
143-
Duplicate(usize),
144-
}
145-
146132
/// Wrapper around `Bump` which allows it to be used as an allocator for
147133
/// `HashMap`, `HashSet` and `RawTable`.
148134
///

src/map.rs

Lines changed: 201 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
use crate::raw::{Allocator, Bucket, Global, RawDrain, RawIntoIter, RawIter, RawTable};
22
use crate::TryReserveError;
3-
#[cfg(feature = "nightly")]
4-
use crate::UnavailableMutError;
53
use core::borrow::Borrow;
64
use core::fmt::{self, Debug};
75
use core::hash::{BuildHasher, Hash};
@@ -1172,109 +1170,251 @@ where
11721170

11731171
/// Attempts to get mutable references to `N` values in the map at once.
11741172
///
1175-
/// Returns an array of length `N` with the results of each query. For soundness,
1176-
/// at most one mutable reference will be returned to any value. An
1177-
/// `Err(UnavailableMutError::Duplicate(i))` in the returned array indicates that a suitable
1178-
/// key-value pair exists, but a mutable reference to the value already occurs at index `i` in
1179-
/// the returned array.
1180-
///
1181-
/// This method is available only if the `nightly` feature is enabled.
1173+
/// Returns an array of length `N` with the results of each query. For soundness, at most one
1174+
/// mutable reference will be returned to any value. `None` will be returned if any of the
1175+
/// keys are duplicates or missing.
11821176
///
11831177
/// # Examples
11841178
///
11851179
/// ```
1186-
/// use hashbrown::{HashMap, UnavailableMutError};
1180+
/// use hashbrown::HashMap;
11871181
///
11881182
/// let mut libraries = HashMap::new();
11891183
/// libraries.insert("Bodleian Library".to_string(), 1602);
11901184
/// libraries.insert("Athenæum".to_string(), 1807);
11911185
/// libraries.insert("Herzogin-Anna-Amalia-Bibliothek".to_string(), 1691);
11921186
/// libraries.insert("Library of Congress".to_string(), 1800);
11931187
///
1194-
/// let got = libraries.get_each_mut([
1188+
/// let got = libraries.get_many_mut([
1189+
/// "Athenæum",
1190+
/// "Library of Congress",
1191+
/// ]);
1192+
/// assert_eq!(
1193+
/// got,
1194+
/// Some([
1195+
/// &mut 1807,
1196+
/// &mut 1800,
1197+
/// ]),
1198+
/// );
1199+
///
1200+
/// // Missing keys result in None
1201+
/// let got = libraries.get_many_mut([
11951202
/// "Athenæum",
11961203
/// "New York Public Library",
1204+
/// ]);
1205+
/// assert_eq!(got, None);
1206+
///
1207+
/// // Duplicate keys result in None
1208+
/// let got = libraries.get_many_mut([
1209+
/// "Athenæum",
1210+
/// "Athenæum",
1211+
/// ]);
1212+
/// assert_eq!(got, None);
1213+
/// ```
1214+
pub fn get_many_mut<Q: ?Sized, const N: usize>(&mut self, ks: [&Q; N]) -> Option<[&'_ mut V; N]>
1215+
where
1216+
K: Borrow<Q>,
1217+
Q: Hash + Eq,
1218+
{
1219+
self.get_many_mut_inner(ks).map(|res| res.map(|(_, v)| v))
1220+
}
1221+
1222+
/// Attempts to get mutable references to `N` values in the map at once, without validating that
1223+
/// the values are unique.
1224+
///
1225+
/// Returns an array of length `N` with the results of each query. `None` will be returned if
1226+
/// any of the keys are missing.
1227+
///
1228+
/// For a safe alternative see [`get_many_mut`].
1229+
///
1230+
/// # Safety
1231+
///
1232+
/// Calling this method with overlapping keys is *[undefined behavior]* even if the resulting
1233+
/// references are not used.
1234+
///
1235+
/// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
1236+
///
1237+
/// # Examples
1238+
///
1239+
/// ```
1240+
/// use hashbrown::HashMap;
1241+
///
1242+
/// let mut libraries = HashMap::new();
1243+
/// libraries.insert("Bodleian Library".to_string(), 1602);
1244+
/// libraries.insert("Athenæum".to_string(), 1807);
1245+
/// libraries.insert("Herzogin-Anna-Amalia-Bibliothek".to_string(), 1691);
1246+
/// libraries.insert("Library of Congress".to_string(), 1800);
1247+
///
1248+
/// let got = libraries.get_many_mut([
11971249
/// "Athenæum",
11981250
/// "Library of Congress",
11991251
/// ]);
12001252
/// assert_eq!(
12011253
/// got,
1202-
/// [
1203-
/// Ok(&mut 1807),
1204-
/// Err(UnavailableMutError::Absent),
1205-
/// Err(UnavailableMutError::Duplicate(0)),
1206-
/// Ok(&mut 1800),
1207-
/// ]
1254+
/// Some([
1255+
/// &mut 1807,
1256+
/// &mut 1800,
1257+
/// ]),
12081258
/// );
1259+
///
1260+
/// // Missing keys result in None
1261+
/// let got = libraries.get_many_mut([
1262+
/// "Athenæum",
1263+
/// "New York Public Library",
1264+
/// ]);
1265+
/// assert_eq!(got, None);
12091266
/// ```
1210-
#[cfg(feature = "nightly")]
1211-
pub fn get_each_mut<Q: ?Sized, const N: usize>(
1267+
pub unsafe fn get_many_unchecked_mut<Q: ?Sized, const N: usize>(
12121268
&mut self,
12131269
ks: [&Q; N],
1214-
) -> [Result<&'_ mut V, UnavailableMutError>; N]
1270+
) -> Option<[&'_ mut V; N]>
12151271
where
12161272
K: Borrow<Q>,
12171273
Q: Hash + Eq,
12181274
{
1219-
self.get_each_inner_mut(ks).map(|res| res.map(|(_, v)| v))
1275+
self.get_many_unchecked_mut_inner(ks)
1276+
.map(|res| res.map(|(_, v)| v))
12201277
}
12211278

12221279
/// Attempts to get mutable references to `N` values in the map at once, with immutable
12231280
/// references to the corresponding keys.
12241281
///
1225-
/// Returns an array of length `N` with the results of each query. For soundness,
1226-
/// at most one mutable reference will be returned to any value. An
1227-
/// `Err(UnavailableMutError::Duplicate(i))` in the returned array indicates that a suitable
1228-
/// key-value pair exists, but a mutable reference to the value already occurs at index `i` in
1229-
/// the returned array.
1230-
///
1231-
/// This method is available only if the `nightly` feature is enabled.
1282+
/// Returns an array of length `N` with the results of each query. For soundness, at most one
1283+
/// mutable reference will be returned to any value. `None` will be returned if any of the keys
1284+
/// are duplicates or missing.
12321285
///
12331286
/// # Examples
12341287
///
12351288
/// ```
1236-
/// use hashbrown::{HashMap, UnavailableMutError};
1289+
/// use hashbrown::HashMap;
12371290
///
12381291
/// let mut libraries = HashMap::new();
12391292
/// libraries.insert("Bodleian Library".to_string(), 1602);
12401293
/// libraries.insert("Athenæum".to_string(), 1807);
12411294
/// libraries.insert("Herzogin-Anna-Amalia-Bibliothek".to_string(), 1691);
12421295
/// libraries.insert("Library of Congress".to_string(), 1800);
12431296
///
1244-
/// let got = libraries.get_each_key_value_mut([
1297+
/// let got = libraries.get_many_key_value_mut([
12451298
/// "Bodleian Library",
12461299
/// "Herzogin-Anna-Amalia-Bibliothek",
1247-
/// "Herzogin-Anna-Amalia-Bibliothek",
1300+
/// ]);
1301+
/// assert_eq!(
1302+
/// got,
1303+
/// Some([
1304+
/// (&"Bodleian Library".to_string(), &mut 1602),
1305+
/// (&"Herzogin-Anna-Amalia-Bibliothek".to_string(), &mut 1691),
1306+
/// ]),
1307+
/// );
1308+
/// // Missing keys result in None
1309+
/// let got = libraries.get_many_key_value_mut([
1310+
/// "Bodleian Library",
12481311
/// "Gewandhaus",
12491312
/// ]);
1313+
/// assert_eq!(got, None);
1314+
///
1315+
/// // Duplicate keys result in None
1316+
/// let got = libraries.get_many_key_value_mut([
1317+
/// "Bodleian Library",
1318+
/// "Herzogin-Anna-Amalia-Bibliothek",
1319+
/// "Herzogin-Anna-Amalia-Bibliothek",
1320+
/// ]);
1321+
/// assert_eq!(got, None);
1322+
/// ```
1323+
pub fn get_many_key_value_mut<Q: ?Sized, const N: usize>(
1324+
&mut self,
1325+
ks: [&Q; N],
1326+
) -> Option<[(&'_ K, &'_ mut V); N]>
1327+
where
1328+
K: Borrow<Q>,
1329+
Q: Hash + Eq,
1330+
{
1331+
self.get_many_mut_inner(ks)
1332+
.map(|res| res.map(|(k, v)| (&*k, v)))
1333+
}
1334+
1335+
/// Attempts to get mutable references to `N` values in the map at once, with immutable
1336+
/// references to the corresponding keys, without validating that the values are unique.
1337+
///
1338+
/// Returns an array of length `N` with the results of each query. `None` will be returned if
1339+
/// any of the keys are missing.
1340+
///
1341+
/// For a safe alternative see [`get_many_key_value_mut`].
1342+
///
1343+
/// # Safety
1344+
///
1345+
/// Calling this method with overlapping keys is *[undefined behavior]* even if the resulting
1346+
/// references are not used.
1347+
///
1348+
/// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
1349+
///
1350+
/// # Examples
1351+
///
1352+
/// ```
1353+
/// use hashbrown::HashMap;
1354+
///
1355+
/// let mut libraries = HashMap::new();
1356+
/// libraries.insert("Bodleian Library".to_string(), 1602);
1357+
/// libraries.insert("Athenæum".to_string(), 1807);
1358+
/// libraries.insert("Herzogin-Anna-Amalia-Bibliothek".to_string(), 1691);
1359+
/// libraries.insert("Library of Congress".to_string(), 1800);
1360+
///
1361+
/// let got = libraries.get_many_key_value_mut([
1362+
/// "Bodleian Library",
1363+
/// "Herzogin-Anna-Amalia-Bibliothek",
1364+
/// ]);
12501365
/// assert_eq!(
12511366
/// got,
1252-
/// [
1253-
/// Ok((&"Bodleian Library".to_string(), &mut 1602)),
1254-
/// Ok((&"Herzogin-Anna-Amalia-Bibliothek".to_string(), &mut 1691)),
1255-
/// Err(UnavailableMutError::Duplicate(1)),
1256-
/// Err(UnavailableMutError::Absent),
1257-
/// ]
1367+
/// Some([
1368+
/// (&"Bodleian Library".to_string(), &mut 1602),
1369+
/// (&"Herzogin-Anna-Amalia-Bibliothek".to_string(), &mut 1691),
1370+
/// ]),
12581371
/// );
1372+
/// // Missing keys result in None
1373+
/// let got = libraries.get_many_key_value_mut([
1374+
/// "Bodleian Library",
1375+
/// "Gewandhaus",
1376+
/// ]);
1377+
/// assert_eq!(got, None);
12591378
/// ```
1260-
#[cfg(feature = "nightly")]
1261-
pub fn get_each_key_value_mut<Q: ?Sized, const N: usize>(
1379+
pub unsafe fn get_many_key_value_unchecked_mut<Q: ?Sized, const N: usize>(
12621380
&mut self,
12631381
ks: [&Q; N],
1264-
) -> [Result<(&'_ K, &'_ mut V), UnavailableMutError>; N]
1382+
) -> Option<[(&'_ K, &'_ mut V); N]>
12651383
where
12661384
K: Borrow<Q>,
12671385
Q: Hash + Eq,
12681386
{
1269-
self.get_each_inner_mut(ks)
1387+
self.get_many_unchecked_mut_inner(ks)
12701388
.map(|res| res.map(|(k, v)| (&*k, v)))
12711389
}
12721390

1273-
#[cfg(feature = "nightly")]
1274-
fn get_each_inner_mut<Q: ?Sized, const N: usize>(
1391+
fn get_many_mut_inner<Q: ?Sized, const N: usize>(
12751392
&mut self,
12761393
ks: [&Q; N],
1277-
) -> [Result<&'_ mut (K, V), UnavailableMutError>; N]
1394+
) -> Option<[&'_ mut (K, V); N]>
1395+
where
1396+
K: Borrow<Q>,
1397+
Q: Hash + Eq,
1398+
{
1399+
let hashes = self.build_hashes_inner(ks);
1400+
self.table
1401+
.get_many_mut(hashes, |i, (k, _)| ks[i].eq(k.borrow()))
1402+
}
1403+
1404+
unsafe fn get_many_unchecked_mut_inner<Q: ?Sized, const N: usize>(
1405+
&mut self,
1406+
ks: [&Q; N],
1407+
) -> Option<[&'_ mut (K, V); N]>
1408+
where
1409+
K: Borrow<Q>,
1410+
Q: Hash + Eq,
1411+
{
1412+
let hashes = self.build_hashes_inner(ks);
1413+
self.table
1414+
.get_many_unchecked_mut(hashes, |i, (k, _)| ks[i].eq(k.borrow()))
1415+
}
1416+
1417+
fn build_hashes_inner<Q: ?Sized, const N: usize>(&self, ks: [&Q; N]) -> [u64; N]
12781418
where
12791419
K: Borrow<Q>,
12801420
Q: Hash + Eq,
@@ -1283,8 +1423,7 @@ where
12831423
for i in 0..N {
12841424
hashes[i] = make_hash::<K, Q, S>(&self.hash_builder, ks[i]);
12851425
}
1286-
self.table
1287-
.get_each_mut(hashes, |i, (k, _)| ks[i].eq(k.borrow()))
1426+
hashes
12881427
}
12891428

12901429
/// Inserts a key-value pair into the map.
@@ -5120,31 +5259,32 @@ mod test_map {
51205259
}
51215260

51225261
#[test]
5123-
#[cfg(feature = "nightly")]
51245262
fn test_get_each_mut() {
5125-
use crate::UnavailableMutError::*;
5126-
51275263
let mut map = HashMap::new();
51285264
map.insert("foo".to_owned(), 0);
51295265
map.insert("bar".to_owned(), 10);
51305266
map.insert("baz".to_owned(), 20);
51315267
map.insert("qux".to_owned(), 30);
51325268

5133-
let xs = map.get_each_mut(["foo", "dud", "foo", "qux"]);
5134-
assert_eq!(
5135-
xs,
5136-
[Ok(&mut 0), Err(Absent), Err(Duplicate(0)), Ok(&mut 30)]
5137-
);
5269+
let xs = map.get_many_mut(["foo", "qux"]);
5270+
assert_eq!(xs, Some([&mut 0, &mut 30]));
5271+
5272+
let xs = map.get_many_mut(["foo", "dud"]);
5273+
assert_eq!(xs, None);
51385274

5139-
let ys = map.get_each_key_value_mut(["bar", "baz", "baz", "dip"]);
5275+
let xs = map.get_many_mut(["foo", "foo"]);
5276+
assert_eq!(xs, None);
5277+
5278+
let ys = map.get_many_key_value_mut(["bar", "baz"]);
51405279
assert_eq!(
51415280
ys,
5142-
[
5143-
Ok((&"bar".to_owned(), &mut 10)),
5144-
Ok((&"baz".to_owned(), &mut 20)),
5145-
Err(Duplicate(1)),
5146-
Err(Absent),
5147-
]
5281+
Some([(&"bar".to_owned(), &mut 10), (&"baz".to_owned(), &mut 20),]),
51485282
);
5283+
5284+
let ys = map.get_many_key_value_mut(["bar", "dip"]);
5285+
assert_eq!(ys, None);
5286+
5287+
let ys = map.get_many_key_value_mut(["baz", "baz"]);
5288+
assert_eq!(ys, None);
51495289
}
51505290
}

0 commit comments

Comments
 (0)