Skip to content

Commit

Permalink
auto merge of #8186 : huonw/rust/hashmap-=rt, r=Aatch
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
bors committed Aug 3, 2013
2 parents 2765811 + c852a5b commit 6be014d
Showing 1 changed file with 26 additions and 28 deletions.
54 changes: 26 additions & 28 deletions src/libstd/hashmap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,27 +61,7 @@ enum SearchResult {

#[inline]
fn resize_at(capacity: uint) -> uint {
((capacity as float) * 3. / 4.) as uint
}

/// Creates a new hash map with the specified capacity.
pub fn linear_map_with_capacity<K:Eq + Hash,V>(
initial_capacity: uint) -> HashMap<K, V> {
let mut r = rand::task_rng();
linear_map_with_capacity_and_keys(r.gen(), r.gen(),
initial_capacity)
}

fn linear_map_with_capacity_and_keys<K:Eq + Hash,V>(
k0: u64, k1: u64,
initial_capacity: uint) -> HashMap<K, V> {
let cap = num::max(INITIAL_CAPACITY, initial_capacity);
HashMap {
k0: k0, k1: k1,
resize_at: resize_at(cap),
size: 0,
buckets: vec::from_fn(cap, |_| None)
}
(capacity * 3) / 4
}

impl<K:Hash + Eq,V> HashMap<K, V> {
Expand Down Expand Up @@ -352,10 +332,28 @@ impl<K: Hash + Eq, V> HashMap<K, V> {
HashMap::with_capacity(INITIAL_CAPACITY)
}

/// Create an empty HashMap with space for at least `n` elements in
/// the hash table.
/// Create an empty HashMap with space for at least `capacity`
/// elements in the hash table.
pub fn with_capacity(capacity: uint) -> HashMap<K, V> {
linear_map_with_capacity(capacity)
let mut r = rand::task_rng();
HashMap::with_capacity_and_keys(r.gen(), r.gen(), capacity)
}

/// Create an empty HashMap with space for at least `capacity`
/// elements, using `k0` and `k1` as the keys.
///
/// Warning: `k0` and `k1` are normally randomly generated, and
/// are designed to allow HashMaps to be resistant to attacks that
/// cause many collisions and very poor performance. Setting them
/// manually using this function can expose a DoS attack vector.
pub fn with_capacity_and_keys(k0: u64, k1: u64, capacity: uint) -> HashMap<K, V> {
let cap = num::max(INITIAL_CAPACITY, capacity);
HashMap {
k0: k0, k1: k1,
resize_at: resize_at(cap),
size: 0,
buckets: vec::from_fn(cap, |_| None)
}
}

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

#[test]
fn test_insert_conflicts() {
let mut m = linear_map_with_capacity(4);
let mut m = HashMap::with_capacity(4);
assert!(m.insert(1, 2));
assert!(m.insert(5, 3));
assert!(m.insert(9, 4));
Expand All @@ -855,7 +853,7 @@ mod test_map {

#[test]
fn test_conflict_remove() {
let mut m = linear_map_with_capacity(4);
let mut m = HashMap::with_capacity(4);
assert!(m.insert(1, 2));
assert!(m.insert(5, 3));
assert!(m.insert(9, 4));
Expand All @@ -866,7 +864,7 @@ mod test_map {

#[test]
fn test_is_empty() {
let mut m = linear_map_with_capacity(4);
let mut m = HashMap::with_capacity(4);
assert!(m.insert(1, 2));
assert!(!m.is_empty());
assert!(m.remove(&1));
Expand Down Expand Up @@ -927,7 +925,7 @@ mod test_map {

#[test]
fn test_iterate() {
let mut m = linear_map_with_capacity(4);
let mut m = HashMap::with_capacity(4);
foreach i in range(0u, 32) {
assert!(m.insert(i, i*2));
}
Expand Down

0 comments on commit 6be014d

Please sign in to comment.