rust/src/libstd/map.rs

763 lines
22 KiB
Rust
Raw Normal View History

//! A map type
2011-10-26 13:28:23 -05:00
#[forbid(deprecated_mode)];
#[forbid(deprecated_pattern)];
2012-09-04 13:23:53 -05:00
use io::WriterUtil;
use to_str::ToStr;
use mutable::Mut;
2012-09-04 13:23:53 -05:00
use send_map::linear::LinearMap;
use core::cmp::Eq;
use hash::Hash;
use to_bytes::IterBytes;
export HashMap, hashfn, eqfn, Set, Map, chained, set_add;
export hash_from_vec;
export vec_from_set;
/// A convenience type to treat a hashmap as a set
2012-09-10 17:38:28 -05:00
type Set<K:Eq IterBytes Hash> = HashMap<K, ()>;
2012-09-10 17:38:28 -05:00
type HashMap<K:Eq IterBytes Hash, V> = chained::T<K, V>;
2012-09-10 17:38:28 -05:00
trait Map<K:Eq IterBytes Hash Copy, V: Copy> {
/// Return the number of elements in the map
2012-08-27 18:26:35 -05:00
pure fn size() -> uint;
2011-10-26 13:28:23 -05:00
/**
* Add a value to the map.
*
* If the map already contains a value for the specified key then the
* original value is replaced.
*
* Returns true if the key did not already exist in the map
*/
fn insert(+v: K, +v: V) -> bool;
2011-10-26 13:28:23 -05:00
/// Returns true if the map contains a value for the specified key
fn contains_key(+key: K) -> bool;
/// Returns true if the map contains a value for the specified
/// key, taking the key by reference.
fn contains_key_ref(key: &K) -> bool;
2011-10-26 13:28:23 -05:00
/**
* Get the value for the specified key. Fails if the key does not exist in
* the map.
*/
fn get(+key: K) -> V;
/**
* Get the value for the specified key. If the key does not exist in
* the map then returns none.
*/
2012-08-27 18:26:35 -05:00
pure fn find(+key: K) -> Option<V>;
2011-10-26 13:28:23 -05:00
/**
* Remove and return a value from the map. Returns true if the
* key was present in the map, otherwise false.
*/
fn remove(+key: K) -> bool;
2011-10-26 13:28:23 -05:00
/// Clear the map, removing all key/value pairs.
fn clear();
/// Iterate over all the key/value pairs in the map by value
2012-08-27 18:26:35 -05:00
pure fn each(fn(+key: K, +value: V) -> bool);
/// Iterate over all the keys in the map by value
2012-08-27 18:26:35 -05:00
pure fn each_key(fn(+key: K) -> bool);
/// Iterate over all the values in the map by value
2012-08-27 18:26:35 -05:00
pure fn each_value(fn(+value: V) -> bool);
2011-10-26 13:28:23 -05:00
/// Iterate over all the key/value pairs in the map by reference
2012-08-27 18:26:35 -05:00
pure fn each_ref(fn(key: &K, value: &V) -> bool);
2012-01-27 22:39:16 -06:00
/// Iterate over all the keys in the map by reference
2012-08-27 18:26:35 -05:00
pure fn each_key_ref(fn(key: &K) -> bool);
/// Iterate over all the values in the map by reference
2012-08-27 18:26:35 -05:00
pure fn each_value_ref(fn(value: &V) -> bool);
}
2011-10-26 13:28:23 -05:00
2012-08-02 13:26:52 -05:00
mod util {
#[legacy_exports];
2012-09-10 17:38:28 -05:00
type Rational = {num: int, den: int}; // : int::positive(*.den);
2012-08-02 13:26:52 -05:00
2012-09-10 17:38:28 -05:00
pure fn rational_leq(x: Rational, y: Rational) -> bool {
2012-08-02 13:26:52 -05:00
// NB: Uses the fact that rationals have positive denominators WLOG:
x.num * y.den <= y.num * x.den
}
}
// FIXME (#2344): package this up and export it as a datatype usable for
// external code that doesn't want to pay the cost of a box.
2011-12-06 21:56:47 -06:00
mod chained {
#[legacy_exports];
2012-09-10 17:38:28 -05:00
export T, mk, HashMap;
2012-05-22 12:02:34 -05:00
const initial_capacity: uint = 32u; // 2^5
2012-09-10 17:38:28 -05:00
struct Entry<K, V> {
hash: uint,
key: K,
value: V,
2012-09-10 17:38:28 -05:00
mut next: Option<@Entry<K, V>>
2011-12-06 21:56:47 -06:00
}
2012-09-10 17:38:28 -05:00
struct HashMap_<K:Eq IterBytes Hash, V> {
mut count: uint,
2012-09-10 17:38:28 -05:00
mut chains: ~[mut Option<@Entry<K,V>>]
}
2012-09-10 17:38:28 -05:00
type T<K:Eq IterBytes Hash, V> = @HashMap_<K, V>;
2012-09-10 17:38:28 -05:00
enum SearchResult<K, V> {
NotFound,
FoundFirst(uint, @Entry<K,V>),
FoundAfter(@Entry<K,V>, @Entry<K,V>)
2011-12-06 21:56:47 -06:00
}
2012-09-10 17:38:28 -05:00
priv impl<K:Eq IterBytes Hash, V: Copy> T<K, V> {
2012-08-27 18:26:35 -05:00
pure fn search_rem(k: &K, h: uint, idx: uint,
2012-09-10 17:38:28 -05:00
e_root: @Entry<K,V>) -> SearchResult<K,V> {
2012-05-22 12:02:34 -05:00
let mut e0 = e_root;
let mut comp = 1u; // for logging
loop {
2012-08-06 14:34:08 -05:00
match copy e0.next {
2012-08-20 14:23:37 -05:00
None => {
2012-08-22 19:24:52 -05:00
debug!("search_tbl: absent, comp %u, hash %u, idx %u",
comp, h, idx);
2012-09-10 17:38:28 -05:00
return NotFound;
2012-05-22 12:02:34 -05:00
}
2012-08-20 14:23:37 -05:00
Some(e1) => {
2012-05-22 12:02:34 -05:00
comp += 1u;
unsafe {
if e1.hash == h && e1.key == *k {
2012-08-27 18:26:35 -05:00
debug!("search_tbl: present, comp %u, \
hash %u, idx %u",
comp, h, idx);
2012-09-10 17:38:28 -05:00
return FoundAfter(e0, e1);
2012-08-27 18:26:35 -05:00
} else {
e0 = e1;
}
2012-05-22 12:02:34 -05:00
}
}
}
};
}
2012-09-10 17:38:28 -05:00
pure fn search_tbl(k: &K, h: uint) -> SearchResult<K,V> {
2012-05-22 12:02:34 -05:00
let idx = h % vec::len(self.chains);
2012-08-06 14:34:08 -05:00
match copy self.chains[idx] {
2012-08-20 14:23:37 -05:00
None => {
2012-08-22 19:24:52 -05:00
debug!("search_tbl: none, comp %u, hash %u, idx %u",
0u, h, idx);
2012-09-10 17:38:28 -05:00
return NotFound;
2011-12-06 21:56:47 -06:00
}
2012-08-20 14:23:37 -05:00
Some(e) => {
unsafe {
if e.hash == h && e.key == *k {
2012-08-27 18:26:35 -05:00
debug!("search_tbl: present, comp %u, hash %u, \
idx %u", 1u, h, idx);
2012-09-10 17:38:28 -05:00
return FoundFirst(idx, e);
2012-08-27 18:26:35 -05:00
} else {
return self.search_rem(k, h, idx, e);
}
2011-12-06 21:56:47 -06:00
}
}
}
}
2012-05-22 12:02:34 -05:00
fn rehash() {
let n_old_chains = self.chains.len();
2012-05-22 12:02:34 -05:00
let n_new_chains: uint = uint::next_power_of_two(n_old_chains+1u);
let new_chains = chains(n_new_chains);
2012-06-30 18:19:07 -05:00
for self.each_entry |entry| {
2012-05-22 12:02:34 -05:00
let idx = entry.hash % n_new_chains;
entry.next = new_chains[idx];
2012-08-20 14:23:37 -05:00
new_chains[idx] = Some(entry);
2012-05-22 12:02:34 -05:00
}
self.chains <- new_chains;
2011-12-06 21:56:47 -06:00
}
2012-09-10 17:38:28 -05:00
pure fn each_entry(blk: fn(@Entry<K,V>) -> bool) {
// n.b. we can't use vec::iter() here because self.chains
// is stored in a mutable location.
let mut i = 0u, n = self.chains.len();
2012-05-22 12:02:34 -05:00
while i < n {
let mut chain = self.chains[i];
loop {
2012-08-06 14:34:08 -05:00
chain = match chain {
2012-08-20 14:23:37 -05:00
None => break,
Some(entry) => {
2012-05-22 12:02:34 -05:00
let next = entry.next;
2012-08-01 19:30:05 -05:00
if !blk(entry) { return; }
2012-05-22 12:02:34 -05:00
next
}
}
}
2012-05-22 12:02:34 -05:00
i += 1u;
}
2011-12-06 21:56:47 -06:00
}
}
2012-09-10 17:38:28 -05:00
impl<K:Eq IterBytes Hash Copy, V: Copy> T<K, V>: Map<K, V> {
2012-08-27 18:26:35 -05:00
pure fn size() -> uint { self.count }
2011-12-06 21:56:47 -06:00
fn contains_key(+k: K) -> bool {
self.contains_key_ref(&k)
}
fn contains_key_ref(k: &K) -> bool {
let hash = k.hash_keyed(0,0) as uint;
2012-08-06 14:34:08 -05:00
match self.search_tbl(k, hash) {
2012-09-10 17:38:28 -05:00
NotFound => false,
FoundFirst(*) | FoundAfter(*) => true
2012-05-22 12:02:34 -05:00
}
}
fn insert(+k: K, +v: V) -> bool {
let hash = k.hash_keyed(0,0) as uint;
2012-08-06 14:34:08 -05:00
match self.search_tbl(&k, hash) {
2012-09-10 17:38:28 -05:00
NotFound => {
2012-05-22 12:02:34 -05:00
self.count += 1u;
let idx = hash % vec::len(self.chains);
let old_chain = self.chains[idx];
2012-09-10 17:38:28 -05:00
self.chains[idx] = Some(@Entry {
2012-05-22 12:02:34 -05:00
hash: hash,
key: k,
value: v,
next: old_chain});
2012-05-22 12:02:34 -05:00
// consider rehashing if more 3/4 full
let nchains = vec::len(self.chains);
let load = {num: (self.count + 1u) as int,
den: nchains as int};
2012-05-22 12:02:34 -05:00
if !util::rational_leq(load, {num:3, den:4}) {
self.rehash();
}
2012-08-01 19:30:05 -05:00
return true;
2012-05-22 12:02:34 -05:00
}
2012-09-10 17:38:28 -05:00
FoundFirst(idx, entry) => {
self.chains[idx] = Some(@Entry {
hash: hash,
key: k,
value: v,
next: entry.next});
2012-08-01 19:30:05 -05:00
return false;
2012-05-22 12:02:34 -05:00
}
2012-09-10 17:38:28 -05:00
FoundAfter(prev, entry) => {
prev.next = Some(@Entry {
hash: hash,
key: k,
value: v,
next: entry.next});
return false;
2012-05-22 12:02:34 -05:00
}
}
2011-12-06 21:56:47 -06:00
}
2012-08-27 18:26:35 -05:00
pure fn find(+k: K) -> Option<V> {
unsafe {
match self.search_tbl(&k, k.hash_keyed(0,0) as uint) {
2012-09-10 17:38:28 -05:00
NotFound => None,
FoundFirst(_, entry) => Some(entry.value),
FoundAfter(_, entry) => Some(entry.value)
2012-08-27 18:26:35 -05:00
}
2012-05-22 12:02:34 -05:00
}
}
2011-12-06 21:56:47 -06:00
fn get(+k: K) -> V {
let opt_v = self.find(k);
if opt_v.is_none() {
2012-08-22 19:24:52 -05:00
fail fmt!("Key not found in table: %?", k);
}
2012-09-11 19:17:54 -05:00
option::unwrap(move opt_v)
2012-05-22 12:02:34 -05:00
}
2011-12-06 21:56:47 -06:00
fn remove(+k: K) -> bool {
match self.search_tbl(&k, k.hash_keyed(0,0) as uint) {
2012-09-10 17:38:28 -05:00
NotFound => false,
FoundFirst(idx, entry) => {
2012-05-22 12:02:34 -05:00
self.count -= 1u;
self.chains[idx] = entry.next;
true
2012-05-22 12:02:34 -05:00
}
2012-09-10 17:38:28 -05:00
FoundAfter(eprev, entry) => {
2012-05-22 12:02:34 -05:00
self.count -= 1u;
eprev.next = entry.next;
true
2012-05-22 12:02:34 -05:00
}
}
}
2011-12-06 21:56:47 -06:00
fn clear() {
self.count = 0u;
self.chains = chains(initial_capacity);
}
2012-08-27 18:26:35 -05:00
pure fn each(blk: fn(+key: K, +value: V) -> bool) {
self.each_ref(|k, v| blk(*k, *v))
}
2012-08-27 18:26:35 -05:00
pure fn each_key(blk: fn(+key: K) -> bool) {
self.each_key_ref(|p| blk(*p))
}
2012-08-27 18:26:35 -05:00
pure fn each_value(blk: fn(+value: V) -> bool) {
self.each_value_ref(|p| blk(*p))
}
2012-08-27 18:26:35 -05:00
pure fn each_ref(blk: fn(key: &K, value: &V) -> bool) {
2012-06-30 18:19:07 -05:00
for self.each_entry |entry| {
if !blk(&entry.key, &entry.value) { break; }
2012-05-22 12:02:34 -05:00
}
}
2011-12-06 21:56:47 -06:00
2012-08-27 18:26:35 -05:00
pure fn each_key_ref(blk: fn(key: &K) -> bool) {
self.each_ref(|k, _v| blk(k))
}
2011-12-06 21:56:47 -06:00
2012-08-27 18:26:35 -05:00
pure fn each_value_ref(blk: fn(value: &V) -> bool) {
self.each_ref(|_k, v| blk(v))
}
2012-05-22 12:02:34 -05:00
}
2011-12-06 21:56:47 -06:00
2012-09-10 17:38:28 -05:00
impl<K:Eq IterBytes Hash Copy ToStr, V: ToStr Copy> T<K, V>: ToStr {
2012-08-14 15:38:35 -05:00
fn to_writer(wr: io::Writer) {
2012-07-13 02:01:26 -05:00
if self.count == 0u {
wr.write_str(~"{}");
2012-08-01 19:30:05 -05:00
return;
2012-07-13 02:01:26 -05:00
}
wr.write_str(~"{ ");
2012-07-13 02:01:26 -05:00
let mut first = true;
for self.each_entry |entry| {
if !first {
wr.write_str(~", ");
2012-07-13 02:01:26 -05:00
}
first = false;
wr.write_str(entry.key.to_str());
wr.write_str(~": ");
2012-07-13 02:01:26 -05:00
wr.write_str((copy entry.value).to_str());
};
wr.write_str(~" }");
2012-07-13 02:01:26 -05:00
}
fn to_str() -> ~str {
do io::with_str_writer |wr| { self.to_writer(wr) }
}
}
2012-09-10 17:38:28 -05:00
impl<K:Eq IterBytes Hash Copy, V: Copy> T<K, V>: ops::Index<K, V> {
pure fn index(&&k: K) -> V {
unsafe {
self.get(k)
}
}
}
2012-09-10 17:38:28 -05:00
fn chains<K,V>(nchains: uint) -> ~[mut Option<@Entry<K,V>>] {
2012-08-20 14:23:37 -05:00
vec::to_mut(vec::from_elem(nchains, None))
2011-12-06 21:56:47 -06:00
}
2012-09-10 17:38:28 -05:00
fn mk<K:Eq IterBytes Hash, V: Copy>() -> T<K,V> {
let slf: T<K, V> = @HashMap_ {count: 0u,
chains: chains(initial_capacity)};
slf
2011-12-06 21:56:47 -06:00
}
}
2011-12-07 10:14:57 -06:00
/*
Function: hashmap
2011-12-07 10:14:57 -06:00
Construct a hashmap.
*/
2012-09-10 17:38:28 -05:00
fn HashMap<K:Eq IterBytes Hash Const, V: Copy>()
-> HashMap<K, V> {
chained::mk()
2011-12-06 21:56:47 -06:00
}
/// Convenience function for adding keys to a hashmap with nil type keys
2012-09-10 17:38:28 -05:00
fn set_add<K:Eq IterBytes Hash Const Copy>(set: Set<K>, +key: K) -> bool {
set.insert(key, ())
2012-05-31 12:26:05 -05:00
}
2012-01-17 21:05:07 -06:00
/// Convert a set into a vector.
2012-09-10 17:38:28 -05:00
fn vec_from_set<T:Eq IterBytes Hash Copy>(s: Set<T>) -> ~[T] {
do vec::build_sized(s.size()) |push| {
for s.each_key() |k| {
push(k);
}
}
}
/// Construct a hashmap from a vector
fn hash_from_vec<K: Eq IterBytes Hash Const Copy, V: Copy>(
2012-09-10 17:38:28 -05:00
items: &[(K, V)]) -> HashMap<K, V> {
let map = HashMap();
for vec::each(items) |item| {
match *item {
(key, value) => {
map.insert(key, value);
}
}
}
map
}
// XXX Transitional
impl<K: Eq IterBytes Hash Copy, V: Copy> @Mut<LinearMap<K, V>>:
2012-09-10 17:38:28 -05:00
Map<K, V> {
2012-08-27 18:26:35 -05:00
pure fn size() -> uint {
unsafe {
2012-08-27 18:26:35 -05:00
do self.borrow_const |p| {
p.len()
}
}
}
fn insert(+key: K, +value: V) -> bool {
do self.borrow_mut |p| {
p.insert(key, value)
}
}
fn contains_key(+key: K) -> bool {
do self.borrow_const |p| {
p.contains_key(&key)
}
}
fn contains_key_ref(key: &K) -> bool {
do self.borrow_const |p| {
p.contains_key(key)
}
}
fn get(+key: K) -> V {
do self.borrow_const |p| {
p.get(&key)
}
}
2012-08-27 18:26:35 -05:00
pure fn find(+key: K) -> Option<V> {
unsafe {
2012-08-27 18:26:35 -05:00
do self.borrow_const |p| {
p.find(&key)
}
}
}
fn remove(+key: K) -> bool {
do self.borrow_mut |p| {
p.remove(&key)
}
}
fn clear() {
do self.borrow_mut |p| {
p.clear()
}
}
2012-08-27 18:26:35 -05:00
pure fn each(op: fn(+key: K, +value: V) -> bool) {
unsafe {
2012-08-27 18:26:35 -05:00
do self.borrow_imm |p| {
p.each(|k, v| op(*k, *v))
2012-08-27 18:26:35 -05:00
}
}
}
2012-08-27 18:26:35 -05:00
pure fn each_key(op: fn(+key: K) -> bool) {
unsafe {
2012-08-27 18:26:35 -05:00
do self.borrow_imm |p| {
p.each_key(|k| op(*k))
2012-08-27 18:26:35 -05:00
}
}
}
2012-08-27 18:26:35 -05:00
pure fn each_value(op: fn(+value: V) -> bool) {
unsafe {
2012-08-27 18:26:35 -05:00
do self.borrow_imm |p| {
p.each_value(|v| op(*v))
2012-08-27 18:26:35 -05:00
}
}
}
2012-08-27 18:26:35 -05:00
pure fn each_ref(op: fn(key: &K, value: &V) -> bool) {
unsafe {
2012-08-27 18:26:35 -05:00
do self.borrow_imm |p| {
p.each(op)
2012-08-27 18:26:35 -05:00
}
}
}
2012-08-27 18:26:35 -05:00
pure fn each_key_ref(op: fn(key: &K) -> bool) {
unsafe {
2012-08-27 18:26:35 -05:00
do self.borrow_imm |p| {
p.each_key(op)
2012-08-27 18:26:35 -05:00
}
}
}
2012-08-27 18:26:35 -05:00
pure fn each_value_ref(op: fn(value: &V) -> bool) {
unsafe {
2012-08-27 18:26:35 -05:00
do self.borrow_imm |p| {
p.each_value(op)
2012-08-27 18:26:35 -05:00
}
}
}
}
2012-01-17 21:05:07 -06:00
#[cfg(test)]
mod tests {
#[legacy_exports];
2012-01-17 21:05:07 -06:00
#[test]
fn test_simple() {
2012-08-22 19:24:52 -05:00
debug!("*** starting test_simple");
pure fn eq_uint(x: &uint, y: &uint) -> bool { *x == *y }
pure fn uint_id(x: &uint) -> uint { *x }
2012-08-22 19:24:52 -05:00
debug!("uint -> uint");
2012-09-10 17:38:28 -05:00
let hm_uu: map::HashMap<uint, uint> =
map::HashMap::<uint, uint>();
2012-01-17 21:05:07 -06:00
assert (hm_uu.insert(10u, 12u));
assert (hm_uu.insert(11u, 13u));
assert (hm_uu.insert(12u, 14u));
assert (hm_uu.get(11u) == 13u);
assert (hm_uu.get(12u) == 14u);
assert (hm_uu.get(10u) == 12u);
assert (!hm_uu.insert(12u, 14u));
assert (hm_uu.get(12u) == 14u);
assert (!hm_uu.insert(12u, 12u));
assert (hm_uu.get(12u) == 12u);
let ten: ~str = ~"ten";
let eleven: ~str = ~"eleven";
let twelve: ~str = ~"twelve";
2012-08-22 19:24:52 -05:00
debug!("str -> uint");
2012-09-10 17:38:28 -05:00
let hm_su: map::HashMap<~str, uint> =
map::HashMap::<~str, uint>();
assert (hm_su.insert(~"ten", 12u));
2012-01-17 21:05:07 -06:00
assert (hm_su.insert(eleven, 13u));
assert (hm_su.insert(~"twelve", 14u));
2012-01-17 21:05:07 -06:00
assert (hm_su.get(eleven) == 13u);
assert (hm_su.get(~"eleven") == 13u);
assert (hm_su.get(~"twelve") == 14u);
assert (hm_su.get(~"ten") == 12u);
assert (!hm_su.insert(~"twelve", 14u));
assert (hm_su.get(~"twelve") == 14u);
assert (!hm_su.insert(~"twelve", 12u));
assert (hm_su.get(~"twelve") == 12u);
2012-08-22 19:24:52 -05:00
debug!("uint -> str");
2012-09-10 17:38:28 -05:00
let hm_us: map::HashMap<uint, ~str> =
map::HashMap::<uint, ~str>();
assert (hm_us.insert(10u, ~"twelve"));
assert (hm_us.insert(11u, ~"thirteen"));
assert (hm_us.insert(12u, ~"fourteen"));
assert hm_us.get(11u) == ~"thirteen";
assert hm_us.get(12u) == ~"fourteen";
assert hm_us.get(10u) == ~"twelve";
assert (!hm_us.insert(12u, ~"fourteen"));
assert hm_us.get(12u) == ~"fourteen";
assert (!hm_us.insert(12u, ~"twelve"));
assert hm_us.get(12u) == ~"twelve";
2012-08-22 19:24:52 -05:00
debug!("str -> str");
2012-09-10 17:38:28 -05:00
let hm_ss: map::HashMap<~str, ~str> =
map::HashMap::<~str, ~str>();
assert (hm_ss.insert(ten, ~"twelve"));
assert (hm_ss.insert(eleven, ~"thirteen"));
assert (hm_ss.insert(twelve, ~"fourteen"));
assert hm_ss.get(~"eleven") == ~"thirteen";
assert hm_ss.get(~"twelve") == ~"fourteen";
assert hm_ss.get(~"ten") == ~"twelve";
assert (!hm_ss.insert(~"twelve", ~"fourteen"));
assert hm_ss.get(~"twelve") == ~"fourteen";
assert (!hm_ss.insert(~"twelve", ~"twelve"));
assert hm_ss.get(~"twelve") == ~"twelve";
2012-08-22 19:24:52 -05:00
debug!("*** finished test_simple");
2012-01-17 21:05:07 -06:00
}
/**
* Force map growth
*/
#[test]
fn test_growth() {
2012-08-22 19:24:52 -05:00
debug!("*** starting test_growth");
2012-01-17 21:05:07 -06:00
let num_to_insert: uint = 64u;
pure fn eq_uint(x: &uint, y: &uint) -> bool { *x == *y }
pure fn uint_id(x: &uint) -> uint { *x }
2012-08-22 19:24:52 -05:00
debug!("uint -> uint");
2012-09-10 17:38:28 -05:00
let hm_uu: map::HashMap<uint, uint> =
map::HashMap::<uint, uint>();
let mut i: uint = 0u;
2012-01-17 21:05:07 -06:00
while i < num_to_insert {
assert (hm_uu.insert(i, i * i));
2012-08-22 19:24:52 -05:00
debug!("inserting %u -> %u", i, i*i);
2012-01-17 21:05:07 -06:00
i += 1u;
}
2012-08-22 19:24:52 -05:00
debug!("-----");
2012-01-17 21:05:07 -06:00
i = 0u;
while i < num_to_insert {
2012-08-22 19:24:52 -05:00
debug!("get(%u) = %u", i, hm_uu.get(i));
2012-01-17 21:05:07 -06:00
assert (hm_uu.get(i) == i * i);
i += 1u;
}
assert (hm_uu.insert(num_to_insert, 17u));
assert (hm_uu.get(num_to_insert) == 17u);
2012-08-22 19:24:52 -05:00
debug!("-----");
2012-01-17 21:05:07 -06:00
i = 0u;
while i < num_to_insert {
2012-08-22 19:24:52 -05:00
debug!("get(%u) = %u", i, hm_uu.get(i));
2012-01-17 21:05:07 -06:00
assert (hm_uu.get(i) == i * i);
i += 1u;
}
2012-08-22 19:24:52 -05:00
debug!("str -> str");
2012-09-10 17:38:28 -05:00
let hm_ss: map::HashMap<~str, ~str> =
map::HashMap::<~str, ~str>();
2012-01-17 21:05:07 -06:00
i = 0u;
while i < num_to_insert {
assert hm_ss.insert(uint::to_str(i, 2u), uint::to_str(i * i, 2u));
2012-08-22 19:24:52 -05:00
debug!("inserting \"%s\" -> \"%s\"",
2012-01-17 21:05:07 -06:00
uint::to_str(i, 2u),
2012-08-22 19:24:52 -05:00
uint::to_str(i*i, 2u));
2012-01-17 21:05:07 -06:00
i += 1u;
}
2012-08-22 19:24:52 -05:00
debug!("-----");
2012-01-17 21:05:07 -06:00
i = 0u;
while i < num_to_insert {
2012-08-22 19:24:52 -05:00
debug!("get(\"%s\") = \"%s\"",
2012-01-17 21:05:07 -06:00
uint::to_str(i, 2u),
2012-08-22 19:24:52 -05:00
hm_ss.get(uint::to_str(i, 2u)));
assert hm_ss.get(uint::to_str(i, 2u)) == uint::to_str(i * i, 2u);
2012-01-17 21:05:07 -06:00
i += 1u;
}
assert (hm_ss.insert(uint::to_str(num_to_insert, 2u),
uint::to_str(17u, 2u)));
assert hm_ss.get(uint::to_str(num_to_insert, 2u)) ==
uint::to_str(17u, 2u);
2012-08-22 19:24:52 -05:00
debug!("-----");
2012-01-17 21:05:07 -06:00
i = 0u;
while i < num_to_insert {
2012-08-22 19:24:52 -05:00
debug!("get(\"%s\") = \"%s\"",
2012-01-17 21:05:07 -06:00
uint::to_str(i, 2u),
2012-08-22 19:24:52 -05:00
hm_ss.get(uint::to_str(i, 2u)));
assert hm_ss.get(uint::to_str(i, 2u)) == uint::to_str(i * i, 2u);
2012-01-17 21:05:07 -06:00
i += 1u;
}
2012-08-22 19:24:52 -05:00
debug!("*** finished test_growth");
2012-01-17 21:05:07 -06:00
}
#[test]
fn test_removal() {
2012-08-22 19:24:52 -05:00
debug!("*** starting test_removal");
2012-01-17 21:05:07 -06:00
let num_to_insert: uint = 64u;
2012-09-10 17:38:28 -05:00
let hm: map::HashMap<uint, uint> =
map::HashMap::<uint, uint>();
let mut i: uint = 0u;
2012-01-17 21:05:07 -06:00
while i < num_to_insert {
assert (hm.insert(i, i * i));
2012-08-22 19:24:52 -05:00
debug!("inserting %u -> %u", i, i*i);
2012-01-17 21:05:07 -06:00
i += 1u;
}
assert (hm.size() == num_to_insert);
2012-08-22 19:24:52 -05:00
debug!("-----");
debug!("removing evens");
2012-01-17 21:05:07 -06:00
i = 0u;
while i < num_to_insert {
let v = hm.remove(i);
2012-08-21 19:02:40 -05:00
assert v;
2012-01-17 21:05:07 -06:00
i += 2u;
}
assert (hm.size() == num_to_insert / 2u);
2012-08-22 19:24:52 -05:00
debug!("-----");
2012-01-17 21:05:07 -06:00
i = 1u;
while i < num_to_insert {
2012-08-22 19:24:52 -05:00
debug!("get(%u) = %u", i, hm.get(i));
2012-01-17 21:05:07 -06:00
assert (hm.get(i) == i * i);
i += 2u;
}
2012-08-22 19:24:52 -05:00
debug!("-----");
2012-01-17 21:05:07 -06:00
i = 1u;
while i < num_to_insert {
2012-08-22 19:24:52 -05:00
debug!("get(%u) = %u", i, hm.get(i));
2012-01-17 21:05:07 -06:00
assert (hm.get(i) == i * i);
i += 2u;
}
2012-08-22 19:24:52 -05:00
debug!("-----");
2012-01-17 21:05:07 -06:00
i = 0u;
while i < num_to_insert {
assert (hm.insert(i, i * i));
2012-08-22 19:24:52 -05:00
debug!("inserting %u -> %u", i, i*i);
2012-01-17 21:05:07 -06:00
i += 2u;
}
assert (hm.size() == num_to_insert);
2012-08-22 19:24:52 -05:00
debug!("-----");
2012-01-17 21:05:07 -06:00
i = 0u;
while i < num_to_insert {
2012-08-22 19:24:52 -05:00
debug!("get(%u) = %u", i, hm.get(i));
2012-01-17 21:05:07 -06:00
assert (hm.get(i) == i * i);
i += 1u;
}
2012-08-22 19:24:52 -05:00
debug!("-----");
2012-01-17 21:05:07 -06:00
assert (hm.size() == num_to_insert);
i = 0u;
while i < num_to_insert {
2012-08-22 19:24:52 -05:00
debug!("get(%u) = %u", i, hm.get(i));
2012-01-17 21:05:07 -06:00
assert (hm.get(i) == i * i);
i += 1u;
}
2012-08-22 19:24:52 -05:00
debug!("*** finished test_removal");
2012-01-17 21:05:07 -06:00
}
#[test]
fn test_contains_key() {
let key = ~"k";
2012-09-10 17:38:28 -05:00
let map = map::HashMap::<~str, ~str>();
2012-01-17 21:05:07 -06:00
assert (!map.contains_key(key));
map.insert(key, ~"val");
2012-01-17 21:05:07 -06:00
assert (map.contains_key(key));
}
#[test]
fn test_find() {
let key = ~"k";
2012-09-10 17:38:28 -05:00
let map = map::HashMap::<~str, ~str>();
2012-09-21 21:37:57 -05:00
assert (option::is_none(&map.find(key)));
map.insert(key, ~"val");
2012-09-21 21:37:57 -05:00
assert (option::get(&map.find(key)) == ~"val");
2012-01-17 21:05:07 -06:00
}
#[test]
fn test_clear() {
let key = ~"k";
2012-09-10 17:38:28 -05:00
let map = map::HashMap::<~str, ~str>();
map.insert(key, ~"val");
assert (map.size() == 1);
assert (map.contains_key(key));
map.clear();
assert (map.size() == 0);
assert (!map.contains_key(key));
}
#[test]
fn test_hash_from_vec() {
let map = map::hash_from_vec(~[
(~"a", 1),
(~"b", 2),
(~"c", 3)
]);
assert map.size() == 3u;
assert map.get(~"a") == 1;
assert map.get(~"b") == 2;
assert map.get(~"c") == 3;
}
2012-01-27 22:39:16 -06:00
}