Skip to content

Commit 6be014d

Browse files
committed
auto merge of #8186 : huonw/rust/hashmap-=rt, r=Aatch
The `new` constructor uses the task-local RNG to retrieve seeds for the two key values, which requires the runtime. Exposing a constructor that takes the keys directly allows HashMaps to be used in programs that wish to avoid the runtime.
2 parents 2765811 + c852a5b commit 6be014d

File tree

1 file changed

+26
-28
lines changed

1 file changed

+26
-28
lines changed

src/libstd/hashmap.rs

Lines changed: 26 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -61,27 +61,7 @@ enum SearchResult {
6161

6262
#[inline]
6363
fn resize_at(capacity: uint) -> uint {
64-
((capacity as float) * 3. / 4.) as uint
65-
}
66-
67-
/// Creates a new hash map with the specified capacity.
68-
pub fn linear_map_with_capacity<K:Eq + Hash,V>(
69-
initial_capacity: uint) -> HashMap<K, V> {
70-
let mut r = rand::task_rng();
71-
linear_map_with_capacity_and_keys(r.gen(), r.gen(),
72-
initial_capacity)
73-
}
74-
75-
fn linear_map_with_capacity_and_keys<K:Eq + Hash,V>(
76-
k0: u64, k1: u64,
77-
initial_capacity: uint) -> HashMap<K, V> {
78-
let cap = num::max(INITIAL_CAPACITY, initial_capacity);
79-
HashMap {
80-
k0: k0, k1: k1,
81-
resize_at: resize_at(cap),
82-
size: 0,
83-
buckets: vec::from_fn(cap, |_| None)
84-
}
64+
(capacity * 3) / 4
8565
}
8666

8767
impl<K:Hash + Eq,V> HashMap<K, V> {
@@ -352,10 +332,28 @@ impl<K: Hash + Eq, V> HashMap<K, V> {
352332
HashMap::with_capacity(INITIAL_CAPACITY)
353333
}
354334

355-
/// Create an empty HashMap with space for at least `n` elements in
356-
/// the hash table.
335+
/// Create an empty HashMap with space for at least `capacity`
336+
/// elements in the hash table.
357337
pub fn with_capacity(capacity: uint) -> HashMap<K, V> {
358-
linear_map_with_capacity(capacity)
338+
let mut r = rand::task_rng();
339+
HashMap::with_capacity_and_keys(r.gen(), r.gen(), capacity)
340+
}
341+
342+
/// Create an empty HashMap with space for at least `capacity`
343+
/// elements, using `k0` and `k1` as the keys.
344+
///
345+
/// Warning: `k0` and `k1` are normally randomly generated, and
346+
/// are designed to allow HashMaps to be resistant to attacks that
347+
/// cause many collisions and very poor performance. Setting them
348+
/// manually using this function can expose a DoS attack vector.
349+
pub fn with_capacity_and_keys(k0: u64, k1: u64, capacity: uint) -> HashMap<K, V> {
350+
let cap = num::max(INITIAL_CAPACITY, capacity);
351+
HashMap {
352+
k0: k0, k1: k1,
353+
resize_at: resize_at(cap),
354+
size: 0,
355+
buckets: vec::from_fn(cap, |_| None)
356+
}
359357
}
360358

361359
/// Reserve space for at least `n` elements in the hash table.
@@ -844,7 +842,7 @@ mod test_map {
844842

845843
#[test]
846844
fn test_insert_conflicts() {
847-
let mut m = linear_map_with_capacity(4);
845+
let mut m = HashMap::with_capacity(4);
848846
assert!(m.insert(1, 2));
849847
assert!(m.insert(5, 3));
850848
assert!(m.insert(9, 4));
@@ -855,7 +853,7 @@ mod test_map {
855853

856854
#[test]
857855
fn test_conflict_remove() {
858-
let mut m = linear_map_with_capacity(4);
856+
let mut m = HashMap::with_capacity(4);
859857
assert!(m.insert(1, 2));
860858
assert!(m.insert(5, 3));
861859
assert!(m.insert(9, 4));
@@ -866,7 +864,7 @@ mod test_map {
866864

867865
#[test]
868866
fn test_is_empty() {
869-
let mut m = linear_map_with_capacity(4);
867+
let mut m = HashMap::with_capacity(4);
870868
assert!(m.insert(1, 2));
871869
assert!(!m.is_empty());
872870
assert!(m.remove(&1));
@@ -927,7 +925,7 @@ mod test_map {
927925

928926
#[test]
929927
fn test_iterate() {
930-
let mut m = linear_map_with_capacity(4);
928+
let mut m = HashMap::with_capacity(4);
931929
foreach i in range(0u, 32) {
932930
assert!(m.insert(i, i*2));
933931
}

0 commit comments

Comments
 (0)