Skip to content

Commit afd9e18

Browse files
ogxdvirtualritz
andauthored
Improve usability of HashSet/Map type aliases (#56)
Co-authored-by: Moritz Mœller <[email protected]>
1 parent a6b6544 commit afd9e18

File tree

3 files changed

+79
-8
lines changed

3 files changed

+79
-8
lines changed

README.md

+10
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,16 @@ let mut hashset = gxhash::GxHashSet::default();
2222
hashset.insert("hello world");
2323
```
2424

25+
GxHash provides an implementation of the [`Hasher`](core::hash::Hasher) trait.
26+
For convenience, this crate also provides the type aliases `gxhash::HashMap` and `gxhash::HashSet`.
27+
28+
```rust
29+
use gxhash::{HashMap, HashMapExt};
30+
31+
let mut map: HashMap<&str, i32> = HashMap::new();
32+
map.insert("answer", 42);
33+
```
34+
2535
## Features
2636

2737
### Blazingly Fast 🚀

benches/hashset.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ fn benchmark<T>(c: &mut Criterion, name: &str, value: T)
2727
iterate(b, &value, &mut set);
2828
});
2929

30-
let mut set: HashSet::<T, GxBuildHasher> = GxHashSet::<T>::default();
30+
let mut set: HashSet::<T, GxBuildHasher> = gxhash::HashSet::<T>::default();
3131
group.bench_function("GxHash", |b| {
3232
iterate(b, &value, &mut set);
3333
});

src/hasher.rs

+68-7
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
use std::collections::{HashMap, HashSet};
21
use std::hash::{BuildHasher, Hasher};
32

43
use crate::gxhash::platform::*;
@@ -159,10 +158,55 @@ impl BuildHasher for GxBuildHasher {
159158
}
160159

161160
/// A `HashMap` using a (DOS-resistant) [`GxBuildHasher`].
162-
pub type GxHashMap<K, V> = HashMap<K, V, GxBuildHasher>;
161+
pub type HashMap<K, V> = std::collections::HashMap<K, V, GxBuildHasher>;
162+
163+
/// A convenience trait that can be used together with the type aliases defined
164+
/// to get access to the `new()` and `with_capacity()` methods for the
165+
/// [`HashMap`] type alias.
166+
pub trait HashMapExt {
167+
/// Constructs a new HashMap.
168+
fn new() -> Self;
169+
/// Constructs a new HashMap with a given initial capacity.
170+
fn with_capacity(capacity: usize) -> Self;
171+
}
172+
173+
impl<K, V, S> HashMapExt for std::collections::HashMap<K, V, S>
174+
where
175+
S: BuildHasher + Default,
176+
{
177+
fn new() -> Self {
178+
std::collections::HashMap::with_hasher(S::default())
179+
}
180+
181+
fn with_capacity(capacity: usize) -> Self {
182+
std::collections::HashMap::with_capacity_and_hasher(capacity, S::default())
183+
}
184+
}
163185

164186
/// A `HashSet` using a (DOS-resistant) [`GxBuildHasher`].
165-
pub type GxHashSet<T> = HashSet<T, GxBuildHasher>;
187+
pub type HashSet<T> = std::collections::HashSet<T, GxBuildHasher>;
188+
189+
/// A convenience trait that can be used together with the type aliases defined
190+
/// to get access to the `new()` and `with_capacity()` methods for the
191+
/// [`HashSet`] type alias.
192+
pub trait HashSetExt {
193+
/// Constructs a new HashMap.
194+
fn new() -> Self;
195+
/// Constructs a new HashMap with a given initial capacity.
196+
fn with_capacity(capacity: usize) -> Self;
197+
}
198+
199+
impl<K, S> HashSetExt for std::collections::HashSet<K, S>
200+
where S: BuildHasher + Default,
201+
{
202+
fn new() -> Self {
203+
std::collections::HashSet::with_hasher(S::default())
204+
}
205+
206+
fn with_capacity(capacity: usize) -> Self {
207+
std::collections::HashSet::with_capacity_and_hasher(capacity, S::default())
208+
}
209+
}
166210

167211
#[cfg(test)]
168212
mod tests {
@@ -171,14 +215,31 @@ mod tests {
171215

172216
use super::*;
173217

218+
#[test]
219+
fn contructors_work() {
220+
let mut map: std::collections::HashMap<&str, i32, GxBuildHasher> = HashMap::new();
221+
assert_eq!(true, map.insert("foo", 1).is_none());
222+
223+
let mut map = HashMap::with_capacity(3);
224+
assert_eq!(3, map.capacity());
225+
assert_eq!(true, map.insert("bar", 2).is_none());
226+
227+
let mut set: std::collections::HashSet<i32, GxBuildHasher> = HashSet::new();
228+
assert_eq!(true, set.insert(42));
229+
230+
let mut set = HashSet::with_capacity(3);
231+
assert_eq!(true, set.insert(42));
232+
assert_eq!(3, set.capacity());
233+
}
234+
174235
#[test]
175236
fn hasher_produces_stable_hashes() {
176-
let mut hashset = GxHashSet::default();
237+
let mut hashset = HashSet::default();
177238
assert!(hashset.insert(1234));
178239
assert!(!hashset.insert(1234));
179240
assert!(hashset.insert(42));
180241

181-
let mut hashset = GxHashSet::default();
242+
let mut hashset = HashSet::default();
182243
assert!(hashset.insert("hello"));
183244
assert!(hashset.insert("world"));
184245
assert!(!hashset.insert("hello"));
@@ -199,8 +260,8 @@ mod tests {
199260
// This is important for DOS resistance
200261
#[test]
201262
fn gxhashset_uses_default_gxhasherbuilder() {
202-
let hashset_1 = GxHashSet::<u32>::default();
203-
let hashset_2 = GxHashSet::<u32>::default();
263+
let hashset_1 = HashSet::<u32>::default();
264+
let hashset_2 = HashSet::<u32>::default();
204265

205266
let mut hasher_1 = hashset_1.hasher().build_hasher();
206267
let mut hasher_2 = hashset_2.hasher().build_hasher();

0 commit comments

Comments
 (0)