Skip to content

Commit 45b5fb2

Browse files
committed
Merge branch 'master' of https://github.com/rust-lang/hashbrown
2 parents c9cc194 + 8be230c commit 45b5fb2

File tree

8 files changed

+131
-20
lines changed

8 files changed

+131
-20
lines changed

.travis.yml

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,6 @@ matrix:
4242
env: TARGET=x86_64-apple-darwin
4343
os: osx
4444
osx_image: xcode10
45-
- name: "i686-apple-darwin"
46-
env: TARGET=i686-apple-darwin
47-
os: osx
48-
osx_image: xcode10
4945
- name: "x86_64-pc-windows-msvc"
5046
env: TARGET=x86_64-pc-windows-msvc
5147
os: windows

CHANGELOG.md

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,17 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
77

88
## [Unreleased]
99

10+
## [v0.7.0] - 2020-01-31
11+
12+
### Added
13+
- Added a `drain_filter` function to `HashMap`. (#135)
14+
15+
### Changed
16+
- Updated `ahash` dependency to 0.3. (#141)
17+
- Optimized set union and intersection. (#130)
18+
- `raw_entry` can now be used without requiring `S: BuildHasher`. (#123)
19+
- `RawTable::bucket_index` can now be used under the `raw` feature. (#128)
20+
1021
## [v0.6.3] - 2019-10-31
1122

1223
### Added
@@ -164,7 +175,8 @@ This release was _yanked_ due to a breaking change for users of `no-default-feat
164175

165176
- Initial release
166177

167-
[Unreleased]: https://github.com/rust-lang/hashbrown/compare/v0.6.3...HEAD
178+
[Unreleased]: https://github.com/rust-lang/hashbrown/compare/v0.7.0...HEAD
179+
[v0.7.0]: https://github.com/rust-lang/hashbrown/compare/v0.6.3...v0.7.0
168180
[v0.6.3]: https://github.com/rust-lang/hashbrown/compare/v0.6.2...v0.6.3
169181
[v0.6.2]: https://github.com/rust-lang/hashbrown/compare/v0.6.1...v0.6.2
170182
[v0.6.1]: https://github.com/rust-lang/hashbrown/compare/v0.6.0...v0.6.1

Cargo.toml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "hashbrown"
3-
version = "0.6.3"
3+
version = "0.7.0"
44
authors = ["Amanieu d'Antras <amanieu@gmail.com>"]
55
description = "A Rust port of Google's SwissTable hash map"
66
license = "Apache-2.0/MIT"
@@ -14,7 +14,7 @@ build = "build.rs"
1414

1515
[dependencies]
1616
# For the default hasher
17-
ahash = { version = "0.2.11", optional = true, default-features = false }
17+
ahash = { version = "0.3.2", optional = true, default-features = false }
1818

1919
# For external trait impls
2020
rayon = { version = "1.0", optional = true }
@@ -26,11 +26,11 @@ compiler_builtins = { version = "0.1.2", optional = true }
2626
alloc = { version = "1.0.0", optional = true, package = "rustc-std-workspace-alloc" }
2727

2828
[build-dependencies]
29-
autocfg = "0.1.4"
29+
autocfg = "1"
3030

3131
[dev-dependencies]
3232
lazy_static = "1.2"
33-
rand = "0.5.1"
33+
rand = { version = "0.7.3", features = ["small_rng"] }
3434
rayon = "1.0"
3535
rustc-hash = "1.0"
3636
serde_test = "1.0"

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ Add this to your `Cargo.toml`:
8484

8585
```toml
8686
[dependencies]
87-
hashbrown = "0.6"
87+
hashbrown = "0.7"
8888
```
8989

9090
Then:

ci/miri.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,4 @@ rustup default "$MIRI_NIGHTLY"
1212
rustup component add miri
1313
cargo miri setup
1414

15-
cargo miri test -- -- -Zunstable-options --exclude-should-panic
15+
cargo miri test

ci/run.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ if [ "${CROSS}" = "1" ]; then
2222
export CARGO_NET_RETRY=5
2323
export CARGO_NET_TIMEOUT=10
2424

25-
cargo install cross
25+
cargo install --git https://github.com/rust-embedded/cross.git
2626
CARGO=cross
2727
fi
2828

src/map.rs

Lines changed: 109 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use core::ops::Index;
1010

1111
/// Default hasher for `HashMap`.
1212
#[cfg(feature = "ahash")]
13-
pub type DefaultHashBuilder = ahash::ABuildHasher;
13+
pub type DefaultHashBuilder = ahash::RandomState;
1414

1515
/// Dummy default hasher for `HashMap`.
1616
#[cfg(not(feature = "ahash"))]
@@ -956,6 +956,35 @@ where
956956
}
957957
}
958958
}
959+
/// Drains elements which are false under the given predicate,
960+
/// and returns an iterator over the removed items.
961+
///
962+
/// In other words, move all pairs `(k, v)` such that `f(&k,&mut v)` returns `false` out
963+
/// into another iterator.
964+
///
965+
/// When the returned DrainedFilter is dropped, the elements that don't satisfy
966+
/// the predicate are dropped from the table.
967+
///
968+
/// # Examples
969+
///
970+
/// ```
971+
/// use hashbrown::HashMap;
972+
///
973+
/// let mut map: HashMap<i32, i32> = (0..8).map(|x|(x, x*10)).collect();
974+
/// let drained = map.drain_filter(|&k, _| k % 2 == 0);
975+
/// assert_eq!(drained.count(), 4);
976+
/// assert_eq!(map.len(), 4);
977+
/// ```
978+
pub fn drain_filter<F>(&mut self, f: F) -> DrainFilter<'_, K, V, F>
979+
where
980+
F: FnMut(&K, &mut V) -> bool,
981+
{
982+
DrainFilter {
983+
f,
984+
iter: unsafe { self.table.iter() },
985+
table: &mut self.table,
986+
}
987+
}
959988
}
960989

961990
impl<K, V, S> HashMap<K, V, S> {
@@ -1236,6 +1265,66 @@ impl<K, V> Drain<'_, K, V> {
12361265
}
12371266
}
12381267

1268+
/// A draining iterator over entries of a `HashMap` which don't satisfy the predicate `f`.
1269+
///
1270+
/// This `struct` is created by the [`drain_filter`] method on [`HashMap`]. See its
1271+
/// documentation for more.
1272+
///
1273+
/// [`drain_filter`]: struct.HashMap.html#method.drain_filter
1274+
/// [`HashMap`]: struct.HashMap.html
1275+
pub struct DrainFilter<'a, K, V, F>
1276+
where
1277+
F: FnMut(&K, &mut V) -> bool,
1278+
{
1279+
f: F,
1280+
iter: RawIter<(K, V)>,
1281+
table: &'a mut RawTable<(K, V)>,
1282+
}
1283+
1284+
impl<'a, K, V, F> Drop for DrainFilter<'a, K, V, F>
1285+
where
1286+
F: FnMut(&K, &mut V) -> bool,
1287+
{
1288+
fn drop(&mut self) {
1289+
struct DropGuard<'r, 'a, K, V, F>(&'r mut DrainFilter<'a, K, V, F>)
1290+
where
1291+
F: FnMut(&K, &mut V) -> bool;
1292+
1293+
impl<'r, 'a, K, V, F> Drop for DropGuard<'r, 'a, K, V, F>
1294+
where
1295+
F: FnMut(&K, &mut V) -> bool,
1296+
{
1297+
fn drop(&mut self) {
1298+
while let Some(_) = self.0.next() {}
1299+
}
1300+
}
1301+
while let Some(item) = self.next() {
1302+
let guard = DropGuard(self);
1303+
drop(item);
1304+
mem::forget(guard);
1305+
}
1306+
}
1307+
}
1308+
1309+
impl<K, V, F> Iterator for DrainFilter<'_, K, V, F>
1310+
where
1311+
F: FnMut(&K, &mut V) -> bool,
1312+
{
1313+
type Item = (K, V);
1314+
fn next(&mut self) -> Option<Self::Item> {
1315+
unsafe {
1316+
while let Some(item) = self.iter.next() {
1317+
let &mut (ref key, ref mut value) = item.as_mut();
1318+
if !(self.f)(key, value) {
1319+
self.table.erase_no_drop(&item);
1320+
return Some(item.read());
1321+
}
1322+
}
1323+
}
1324+
None
1325+
}
1326+
}
1327+
12391328
/// A mutable iterator over the values of a `HashMap`.
12401329
///
12411330
/// This `struct` is created by the [`values_mut`] method on [`HashMap`]. See its
@@ -2625,7 +2714,6 @@ mod test_map {
26252714
use super::DefaultHashBuilder;
26262715
use super::Entry::{Occupied, Vacant};
26272716
use super::{HashMap, RawEntryMut};
2628-
#[cfg(not(miri))]
26292717
use crate::CollectionAllocErr::*;
26302718
use rand::{rngs::SmallRng, Rng, SeedableRng};
26312719
use std::cell::RefCell;
@@ -2883,7 +2971,7 @@ mod test_map {
28832971
}
28842972

28852973
#[test]
2886-
#[cfg(not(miri))] // FIXME: https://github.com/rust-lang/miri/issues/654
2974+
#[cfg_attr(miri, ignore)] // FIXME: takes too long
28872975
fn test_lots_of_insertions() {
28882976
let mut m = HashMap::new();
28892977

@@ -3377,7 +3465,6 @@ mod test_map {
33773465

33783466
let mut m = HashMap::new();
33793467

3380-
// FIXME: https://github.com/rust-lang/miri/issues/653
33813468
let mut rng = {
33823469
let seed = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16];
33833470
SmallRng::from_seed(seed)
@@ -3491,7 +3578,24 @@ mod test_map {
34913578
}
34923579

34933580
#[test]
3494-
#[cfg(not(miri))] // FIXME: https://github.com/rust-lang/miri/issues/655
3581+
fn test_drain_filter() {
3582+
{
3583+
let mut map: HashMap<i32, i32> = (0..8).map(|x| (x, x * 10)).collect();
3584+
let drained = map.drain_filter(|&k, _| k % 2 == 0);
3585+
let mut out = drained.collect::<Vec<_>>();
3586+
out.sort_unstable();
3587+
assert_eq!(vec![(1, 10), (3, 30), (5, 50), (7, 70)], out);
3588+
assert_eq!(map.len(), 4);
3589+
}
3590+
{
3591+
let mut map: HashMap<i32, i32> = (0..8).map(|x| (x, x * 10)).collect();
3592+
drop(map.drain_filter(|&k, _| k % 2 == 0));
3593+
assert_eq!(map.len(), 4);
3594+
}
3595+
}
3596+
3597+
#[test]
3598+
#[cfg_attr(miri, ignore)] // FIXME: no OOM signalling (https://github.com/rust-lang/miri/issues/613)
34953599
fn test_try_reserve() {
34963600
let mut empty_bytes: HashMap<u8, u8> = HashMap::new();
34973601

tests/set.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#![cfg(not(miri))] // FIXME: takes too long
22

33
use hashbrown::HashSet;
4-
use rand::{distributions::Alphanumeric, Rng, SeedableRng, XorShiftRng};
4+
use rand::{distributions::Alphanumeric, rngs::SmallRng, Rng, SeedableRng};
55

66
#[test]
77
fn test_hashset_insert_remove() {
@@ -12,8 +12,7 @@ fn test_hashset_insert_remove() {
1212
130, 220, 246, 217, 111, 124, 221, 189, 190, 234, 121, 93, 67, 95, 100, 43,
1313
];
1414

15-
let mut rng: XorShiftRng = SeedableRng::from_seed(seed);
16-
//let mut rng: XorShiftRng = XorShiftRng::new_unseeded();
15+
let rng = &mut SmallRng::from_seed(seed);
1716
let tx: Vec<Vec<char>> = (0..4096)
1817
.map(|_| (rng.sample_iter(&Alphanumeric).take(32).collect()))
1918
.collect();

0 commit comments

Comments
 (0)