2013-01-20 13:18:24 -06:00
|
|
|
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
|
2012-12-03 18:48:01 -06:00
|
|
|
// file at the top-level directory of this distribution and at
|
|
|
|
// http://rust-lang.org/COPYRIGHT.
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
|
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
|
|
|
// option. This file may not be copied, modified, or distributed
|
|
|
|
// except according to those terms.
|
|
|
|
|
2013-12-24 10:08:28 -06:00
|
|
|
//! Unordered containers, implemented as hash-tables (`HashSet` and `HashMap` types)
|
2013-03-27 02:03:10 -05:00
|
|
|
//!
|
|
|
|
//! The tables use a keyed hash with new random keys generated for each container, so the ordering
|
|
|
|
//! of a set of keys in a hash table is randomized.
|
2013-12-27 05:36:02 -06:00
|
|
|
//!
|
|
|
|
//! # Example
|
|
|
|
//!
|
|
|
|
//! ```rust
|
2014-02-19 21:29:58 -06:00
|
|
|
//! use collections::HashMap;
|
2013-12-27 05:36:02 -06:00
|
|
|
//!
|
|
|
|
//! // type inference lets us omit an explicit type signature (which
|
|
|
|
//! // would be `HashMap<&str, &str>` in this example).
|
|
|
|
//! let mut book_reviews = HashMap::new();
|
|
|
|
//!
|
|
|
|
//! // review some books.
|
|
|
|
//! book_reviews.insert("Adventures of Hucklebury Fin", "My favorite book.");
|
|
|
|
//! book_reviews.insert("Grimms' Fairy Tales", "Masterpiece.");
|
|
|
|
//! book_reviews.insert("Pride and Prejudice", "Very enjoyable.");
|
|
|
|
//! book_reviews.insert("The Adventures of Sherlock Holmes", "Eye lyked it alot.");
|
|
|
|
//!
|
|
|
|
//! // check for a specific one.
|
|
|
|
//! if !book_reviews.contains_key(& &"Les Misérables") {
|
|
|
|
//! println!("We've got {} reviews, but Les Misérables ain't one.",
|
|
|
|
//! book_reviews.len());
|
|
|
|
//! }
|
|
|
|
//!
|
|
|
|
//! // oops, this review has a lot of spelling mistakes, let's delete it.
|
|
|
|
//! book_reviews.remove(& &"The Adventures of Sherlock Holmes");
|
|
|
|
//!
|
|
|
|
//! // look up the values associated with some keys.
|
|
|
|
//! let to_find = ["Pride and Prejudice", "Alice's Adventure in Wonderland"];
|
|
|
|
//! for book in to_find.iter() {
|
|
|
|
//! match book_reviews.find(book) {
|
|
|
|
//! Some(review) => println!("{}: {}", *book, *review),
|
|
|
|
//! None => println!("{} is unreviewed.", *book)
|
|
|
|
//! }
|
|
|
|
//! }
|
|
|
|
//!
|
|
|
|
//! // iterate over everything.
|
|
|
|
//! for (book, review) in book_reviews.iter() {
|
|
|
|
//! println!("{}: \"{}\"", *book, *review);
|
|
|
|
//! }
|
|
|
|
//! ```
|
2012-07-26 18:09:22 -05:00
|
|
|
|
2014-02-19 21:29:58 -06:00
|
|
|
use std::cmp::max;
|
2014-02-22 19:07:11 -06:00
|
|
|
use std::default::Default;
|
2014-02-19 21:29:58 -06:00
|
|
|
use std::fmt;
|
2014-02-25 10:04:38 -06:00
|
|
|
use std::hash::{Hash, Hasher};
|
|
|
|
use std::hash::sip::{SipState, SipHasher};
|
2014-02-19 21:29:58 -06:00
|
|
|
use std::iter::{FilterMap, Chain, Repeat, Zip};
|
|
|
|
use std::iter;
|
|
|
|
use std::mem::replace;
|
|
|
|
use std::num;
|
2014-03-01 18:33:24 -06:00
|
|
|
use rand::Rng;
|
|
|
|
use rand;
|
2014-02-19 21:29:58 -06:00
|
|
|
use std::vec::{Items, MutItems};
|
|
|
|
use std::vec_ng::Vec;
|
|
|
|
use std::vec_ng;
|
|
|
|
|
2013-04-03 07:45:14 -05:00
|
|
|
static INITIAL_CAPACITY: uint = 32u; // 2^5
|
|
|
|
|
|
|
|
struct Bucket<K,V> {
|
|
|
|
hash: uint,
|
|
|
|
key: K,
|
|
|
|
value: V,
|
|
|
|
}
|
2012-12-23 16:41:37 -06:00
|
|
|
|
2013-05-28 16:35:52 -05:00
|
|
|
/// A hash map implementation which uses linear probing along with the SipHash
|
|
|
|
/// hash function for internal state. This means that the order of all hash maps
|
|
|
|
/// is randomized by keying each hash map randomly on creation.
|
|
|
|
///
|
2014-02-25 10:04:38 -06:00
|
|
|
/// It is required that the keys implement the `Eq` and `Hash` traits, although
|
|
|
|
/// this can frequently be achieved by using `#[deriving(Eq, Hash)]`.
|
|
|
|
pub struct HashMap<K, V, H = SipHasher> {
|
|
|
|
priv hasher: H,
|
2013-04-03 07:45:14 -05:00
|
|
|
priv resize_at: uint,
|
|
|
|
priv size: uint,
|
2014-01-18 06:33:41 -06:00
|
|
|
priv buckets: Vec<Option<Bucket<K, V>>>
|
2013-04-03 07:45:14 -05:00
|
|
|
}
|
2012-09-26 19:47:29 -05:00
|
|
|
|
2013-04-03 07:45:14 -05:00
|
|
|
// We could rewrite FoundEntry to have type Option<&Bucket<K, V>>
|
|
|
|
// which would be nifty
|
|
|
|
enum SearchResult {
|
|
|
|
FoundEntry(uint), FoundHole(uint), TableFull
|
|
|
|
}
|
2013-01-24 21:00:58 -06:00
|
|
|
|
2013-06-18 16:45:18 -05:00
|
|
|
#[inline]
|
2013-04-03 07:45:14 -05:00
|
|
|
fn resize_at(capacity: uint) -> uint {
|
2013-08-01 03:11:25 -05:00
|
|
|
(capacity * 3) / 4
|
2013-04-03 07:45:14 -05:00
|
|
|
}
|
2012-07-26 18:09:22 -05:00
|
|
|
|
2014-02-25 10:04:38 -06:00
|
|
|
impl<K: Hash<S> + Eq, V, S, H: Hasher<S>> HashMap<K, V, H> {
|
2013-06-18 16:45:18 -05:00
|
|
|
#[inline]
|
2013-04-03 07:45:14 -05:00
|
|
|
fn to_bucket(&self, h: uint) -> uint {
|
|
|
|
// A good hash function with entropy spread over all of the
|
|
|
|
// bits is assumed. SipHash is more than good enough.
|
|
|
|
h % self.buckets.len()
|
2012-07-26 18:09:22 -05:00
|
|
|
}
|
|
|
|
|
2013-06-18 16:45:18 -05:00
|
|
|
#[inline]
|
2013-04-03 07:45:14 -05:00
|
|
|
fn next_bucket(&self, idx: uint, len_buckets: uint) -> uint {
|
2013-06-13 02:25:28 -05:00
|
|
|
(idx + 1) % len_buckets
|
2012-08-30 21:01:22 -05:00
|
|
|
}
|
2012-07-26 18:09:22 -05:00
|
|
|
|
2013-06-18 16:45:18 -05:00
|
|
|
#[inline]
|
2013-11-18 23:15:42 -06:00
|
|
|
fn bucket_sequence(&self, hash: uint, op: |uint| -> bool) -> bool {
|
2013-05-02 17:33:18 -05:00
|
|
|
let start_idx = self.to_bucket(hash);
|
|
|
|
let len_buckets = self.buckets.len();
|
|
|
|
let mut idx = start_idx;
|
|
|
|
loop {
|
|
|
|
if !op(idx) { return false; }
|
2013-04-03 07:45:14 -05:00
|
|
|
idx = self.next_bucket(idx, len_buckets);
|
|
|
|
if idx == start_idx {
|
2013-05-02 17:33:18 -05:00
|
|
|
return true;
|
2013-04-03 07:45:14 -05:00
|
|
|
}
|
2012-08-28 13:59:31 -05:00
|
|
|
}
|
2012-07-26 18:09:22 -05:00
|
|
|
}
|
|
|
|
|
2013-06-18 16:45:18 -05:00
|
|
|
#[inline]
|
2013-04-03 07:45:14 -05:00
|
|
|
fn bucket_for_key(&self, k: &K) -> SearchResult {
|
2014-02-25 10:04:38 -06:00
|
|
|
let hash = self.hasher.hash(k) as uint;
|
2013-04-03 07:45:14 -05:00
|
|
|
self.bucket_for_key_with_hash(hash, k)
|
|
|
|
}
|
2012-07-26 18:09:22 -05:00
|
|
|
|
2013-06-18 16:45:18 -05:00
|
|
|
#[inline]
|
2014-02-25 10:04:38 -06:00
|
|
|
fn bucket_for_key_equiv<Q:Hash<S> + Equiv<K>>(&self, k: &Q) -> SearchResult {
|
|
|
|
let hash = self.hasher.hash(k) as uint;
|
2013-04-03 07:45:14 -05:00
|
|
|
self.bucket_for_key_with_hash_equiv(hash, k)
|
|
|
|
}
|
2012-07-26 18:09:22 -05:00
|
|
|
|
2013-06-18 16:45:18 -05:00
|
|
|
#[inline]
|
2013-04-03 07:45:14 -05:00
|
|
|
fn bucket_for_key_with_hash(&self,
|
|
|
|
hash: uint,
|
|
|
|
k: &K)
|
|
|
|
-> SearchResult {
|
2013-07-31 14:07:44 -05:00
|
|
|
let mut ret = TableFull;
|
2013-11-20 16:17:12 -06:00
|
|
|
self.bucket_sequence(hash, |i| {
|
2014-01-18 06:33:41 -06:00
|
|
|
match self.buckets.as_slice()[i] {
|
2013-07-31 14:07:44 -05:00
|
|
|
Some(ref bkt) if bkt.hash == hash && *k == bkt.key => {
|
|
|
|
ret = FoundEntry(i); false
|
2013-04-03 07:45:14 -05:00
|
|
|
},
|
2013-07-31 14:07:44 -05:00
|
|
|
None => { ret = FoundHole(i); false }
|
|
|
|
_ => true,
|
2012-07-26 18:09:22 -05:00
|
|
|
}
|
2013-11-20 16:17:12 -06:00
|
|
|
});
|
2013-07-31 14:07:44 -05:00
|
|
|
ret
|
2013-04-03 07:45:14 -05:00
|
|
|
}
|
2013-03-04 21:43:14 -06:00
|
|
|
|
2013-06-18 16:45:18 -05:00
|
|
|
#[inline]
|
2013-04-03 07:45:14 -05:00
|
|
|
fn bucket_for_key_with_hash_equiv<Q:Equiv<K>>(&self,
|
|
|
|
hash: uint,
|
|
|
|
k: &Q)
|
|
|
|
-> SearchResult {
|
2013-07-31 14:07:44 -05:00
|
|
|
let mut ret = TableFull;
|
2013-11-20 16:17:12 -06:00
|
|
|
self.bucket_sequence(hash, |i| {
|
2014-01-18 06:33:41 -06:00
|
|
|
match self.buckets.as_slice()[i] {
|
2013-07-31 14:07:44 -05:00
|
|
|
Some(ref bkt) if bkt.hash == hash && k.equiv(&bkt.key) => {
|
|
|
|
ret = FoundEntry(i); false
|
2013-04-03 07:45:14 -05:00
|
|
|
},
|
2013-07-31 14:07:44 -05:00
|
|
|
None => { ret = FoundHole(i); false }
|
|
|
|
_ => true,
|
2013-04-03 07:45:14 -05:00
|
|
|
}
|
2013-11-20 16:17:12 -06:00
|
|
|
});
|
2013-07-31 14:07:44 -05:00
|
|
|
ret
|
2013-04-03 07:45:14 -05:00
|
|
|
}
|
2013-03-04 21:43:14 -06:00
|
|
|
|
2013-04-03 07:45:14 -05:00
|
|
|
/// Expand the capacity of the array to the next power of two
|
|
|
|
/// and re-insert each of the existing buckets.
|
2013-06-18 16:45:18 -05:00
|
|
|
#[inline]
|
2013-04-03 07:45:14 -05:00
|
|
|
fn expand(&mut self) {
|
|
|
|
let new_capacity = self.buckets.len() * 2;
|
|
|
|
self.resize(new_capacity);
|
|
|
|
}
|
2013-02-15 00:35:15 -06:00
|
|
|
|
2013-04-03 07:45:14 -05:00
|
|
|
/// Expands the capacity of the array and re-insert each of the
|
|
|
|
/// existing buckets.
|
|
|
|
fn resize(&mut self, new_capacity: uint) {
|
|
|
|
self.resize_at = resize_at(new_capacity);
|
2012-07-26 18:09:22 -05:00
|
|
|
|
2013-05-05 23:42:54 -05:00
|
|
|
let old_buckets = replace(&mut self.buckets,
|
2014-01-18 06:33:41 -06:00
|
|
|
Vec::from_fn(new_capacity, |_| None));
|
2012-07-26 18:09:22 -05:00
|
|
|
|
2013-04-03 07:45:14 -05:00
|
|
|
self.size = 0;
|
2013-12-16 04:26:25 -06:00
|
|
|
for bucket in old_buckets.move_iter() {
|
2013-04-03 07:45:14 -05:00
|
|
|
self.insert_opt_bucket(bucket);
|
2012-07-26 18:09:22 -05:00
|
|
|
}
|
2013-04-03 07:45:14 -05:00
|
|
|
}
|
2012-07-26 18:09:22 -05:00
|
|
|
|
2013-04-03 07:45:14 -05:00
|
|
|
fn insert_opt_bucket(&mut self, bucket: Option<Bucket<K, V>>) {
|
|
|
|
match bucket {
|
|
|
|
Some(Bucket{hash: hash, key: key, value: value}) => {
|
|
|
|
self.insert_internal(hash, key, value);
|
2012-08-28 13:59:31 -05:00
|
|
|
}
|
2013-04-03 07:45:14 -05:00
|
|
|
None => {}
|
2012-07-26 18:09:22 -05:00
|
|
|
}
|
2013-04-03 07:45:14 -05:00
|
|
|
}
|
2012-07-26 18:09:22 -05:00
|
|
|
|
2013-06-18 16:45:18 -05:00
|
|
|
#[inline]
|
2013-04-10 15:11:35 -05:00
|
|
|
fn value_for_bucket<'a>(&'a self, idx: uint) -> &'a V {
|
2014-01-18 06:33:41 -06:00
|
|
|
match self.buckets.as_slice()[idx] {
|
2013-04-10 15:11:35 -05:00
|
|
|
Some(ref bkt) => &bkt.value,
|
2013-10-21 15:08:31 -05:00
|
|
|
None => fail!("HashMap::find: internal logic error"),
|
2013-04-10 15:11:35 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-06-18 16:45:18 -05:00
|
|
|
#[inline]
|
2013-04-10 15:11:35 -05:00
|
|
|
fn mut_value_for_bucket<'a>(&'a mut self, idx: uint) -> &'a mut V {
|
2014-01-18 06:33:41 -06:00
|
|
|
match self.buckets.as_mut_slice()[idx] {
|
2013-04-10 15:11:35 -05:00
|
|
|
Some(ref mut bkt) => &mut bkt.value,
|
2013-09-19 00:04:03 -05:00
|
|
|
None => unreachable!()
|
2013-04-10 15:11:35 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-04-03 07:45:14 -05:00
|
|
|
/// Inserts the key value pair into the buckets.
|
|
|
|
/// Assumes that there will be a bucket.
|
|
|
|
/// True if there was no previous entry with that key
|
2013-05-04 08:54:58 -05:00
|
|
|
fn insert_internal(&mut self, hash: uint, k: K, v: V) -> Option<V> {
|
2013-04-03 07:45:14 -05:00
|
|
|
match self.bucket_for_key_with_hash(hash, &k) {
|
2013-10-21 15:08:31 -05:00
|
|
|
TableFull => { fail!("Internal logic error"); }
|
2013-04-03 07:45:14 -05:00
|
|
|
FoundHole(idx) => {
|
2014-01-18 06:33:41 -06:00
|
|
|
self.buckets.as_mut_slice()[idx] = Some(Bucket{hash: hash, key: k, value: v});
|
2013-04-03 07:45:14 -05:00
|
|
|
self.size += 1;
|
2013-05-04 08:54:58 -05:00
|
|
|
None
|
2013-04-03 07:45:14 -05:00
|
|
|
}
|
|
|
|
FoundEntry(idx) => {
|
2014-01-18 06:33:41 -06:00
|
|
|
match self.buckets.as_mut_slice()[idx] {
|
2013-10-21 15:08:31 -05:00
|
|
|
None => { fail!("insert_internal: Internal logic error") }
|
2013-05-04 08:54:58 -05:00
|
|
|
Some(ref mut b) => {
|
|
|
|
b.hash = hash;
|
|
|
|
b.key = k;
|
|
|
|
Some(replace(&mut b.value, v))
|
|
|
|
}
|
|
|
|
}
|
2012-07-26 18:09:22 -05:00
|
|
|
}
|
|
|
|
}
|
2013-04-03 07:45:14 -05:00
|
|
|
}
|
2012-08-22 23:01:30 -05:00
|
|
|
|
2013-04-03 07:45:14 -05:00
|
|
|
fn pop_internal(&mut self, hash: uint, k: &K) -> Option<V> {
|
|
|
|
// Removing from an open-addressed hashtable
|
|
|
|
// is, well, painful. The problem is that
|
|
|
|
// the entry may lie on the probe path for other
|
|
|
|
// entries, so removing it would make you think that
|
|
|
|
// those probe paths are empty.
|
|
|
|
//
|
|
|
|
// To address this we basically have to keep walking,
|
|
|
|
// re-inserting entries we find until we reach an empty
|
|
|
|
// bucket. We know we will eventually reach one because
|
|
|
|
// we insert one ourselves at the beginning (the removed
|
|
|
|
// entry).
|
|
|
|
//
|
|
|
|
// I found this explanation elucidating:
|
|
|
|
// http://www.maths.lse.ac.uk/Courses/MA407/del-hash.pdf
|
|
|
|
let mut idx = match self.bucket_for_key_with_hash(hash, k) {
|
|
|
|
TableFull | FoundHole(_) => return None,
|
|
|
|
FoundEntry(idx) => idx
|
|
|
|
};
|
|
|
|
|
|
|
|
let len_buckets = self.buckets.len();
|
2014-01-18 06:33:41 -06:00
|
|
|
let bucket = self.buckets.as_mut_slice()[idx].take();
|
2013-04-03 07:45:14 -05:00
|
|
|
|
2013-11-20 16:17:12 -06:00
|
|
|
let value = bucket.map(|bucket| bucket.value);
|
2013-04-03 07:45:14 -05:00
|
|
|
|
|
|
|
/* re-inserting buckets may cause changes in size, so remember
|
|
|
|
what our new size is ahead of time before we start insertions */
|
|
|
|
let size = self.size - 1;
|
|
|
|
idx = self.next_bucket(idx, len_buckets);
|
2014-01-18 06:33:41 -06:00
|
|
|
while self.buckets.as_slice()[idx].is_some() {
|
|
|
|
let bucket = self.buckets.as_mut_slice()[idx].take();
|
2013-04-03 07:45:14 -05:00
|
|
|
self.insert_opt_bucket(bucket);
|
2012-10-08 09:05:01 -05:00
|
|
|
idx = self.next_bucket(idx, len_buckets);
|
|
|
|
}
|
2013-04-03 07:45:14 -05:00
|
|
|
self.size = size;
|
2012-10-08 09:05:01 -05:00
|
|
|
|
2013-04-03 07:45:14 -05:00
|
|
|
value
|
2012-07-26 18:09:22 -05:00
|
|
|
}
|
2013-04-03 07:45:14 -05:00
|
|
|
}
|
|
|
|
|
2014-02-25 10:04:38 -06:00
|
|
|
impl<K: Hash<S> + Eq, V, S, H: Hasher<S>> Container for HashMap<K, V, H> {
|
2013-04-03 07:45:14 -05:00
|
|
|
/// Return the number of elements in the map
|
2013-06-23 22:44:11 -05:00
|
|
|
fn len(&self) -> uint { self.size }
|
2013-04-03 07:45:14 -05:00
|
|
|
}
|
2013-01-21 20:59:19 -06:00
|
|
|
|
2014-02-25 10:04:38 -06:00
|
|
|
impl<K: Hash<S> + Eq, V, S, H: Hasher<S>> Mutable for HashMap<K, V, H> {
|
2013-04-03 07:45:14 -05:00
|
|
|
/// Clear the map, removing all key-value pairs.
|
|
|
|
fn clear(&mut self) {
|
2014-01-18 06:33:41 -06:00
|
|
|
for bkt in self.buckets.as_mut_slice().mut_iter() {
|
2013-08-07 09:58:56 -05:00
|
|
|
*bkt = None;
|
2013-01-21 16:25:57 -06:00
|
|
|
}
|
2013-04-03 07:45:14 -05:00
|
|
|
self.size = 0;
|
2013-01-21 16:25:57 -06:00
|
|
|
}
|
2013-04-03 07:45:14 -05:00
|
|
|
}
|
2013-01-21 16:25:57 -06:00
|
|
|
|
2014-02-25 10:04:38 -06:00
|
|
|
impl<K: Hash<S> + Eq, V, S, H: Hasher<S>> Map<K, V> for HashMap<K, V, H> {
|
2013-04-03 07:45:14 -05:00
|
|
|
/// Return a reference to the value corresponding to the key
|
2013-04-10 15:11:35 -05:00
|
|
|
fn find<'a>(&'a self, k: &K) -> Option<&'a V> {
|
|
|
|
match self.bucket_for_key(k) {
|
|
|
|
FoundEntry(idx) => Some(self.value_for_bucket(idx)),
|
|
|
|
TableFull | FoundHole(_) => None,
|
|
|
|
}
|
|
|
|
}
|
2013-07-13 21:44:36 -05:00
|
|
|
}
|
2013-04-10 15:11:35 -05:00
|
|
|
|
2014-02-25 10:04:38 -06:00
|
|
|
impl<K: Hash<S> + Eq, V, S, H: Hasher<S>> MutableMap<K, V> for HashMap<K, V, H> {
|
2013-04-03 07:45:14 -05:00
|
|
|
/// Return a mutable reference to the value corresponding to the key
|
2013-05-06 22:29:54 -05:00
|
|
|
fn find_mut<'a>(&'a mut self, k: &K) -> Option<&'a mut V> {
|
|
|
|
let idx = match self.bucket_for_key(k) {
|
|
|
|
FoundEntry(idx) => idx,
|
|
|
|
TableFull | FoundHole(_) => return None
|
|
|
|
};
|
|
|
|
Some(self.mut_value_for_bucket(idx))
|
|
|
|
}
|
|
|
|
|
2013-05-04 08:54:58 -05:00
|
|
|
/// Insert a key-value pair from the map. If the key already had a value
|
|
|
|
/// present in the map, that value is returned. Otherwise None is returned.
|
|
|
|
fn swap(&mut self, k: K, v: V) -> Option<V> {
|
|
|
|
// this could be faster.
|
|
|
|
|
2013-04-03 07:45:14 -05:00
|
|
|
if self.size >= self.resize_at {
|
|
|
|
// n.b.: We could also do this after searching, so
|
|
|
|
// that we do not resize if this call to insert is
|
|
|
|
// simply going to update a key in place. My sense
|
|
|
|
// though is that it's worse to have to search through
|
|
|
|
// buckets to find the right spot twice than to just
|
|
|
|
// resize in this corner case.
|
|
|
|
self.expand();
|
|
|
|
}
|
|
|
|
|
2014-02-25 10:04:38 -06:00
|
|
|
let hash = self.hasher.hash(&k) as uint;
|
2013-04-03 07:45:14 -05:00
|
|
|
self.insert_internal(hash, k, v)
|
2013-01-21 17:22:03 -06:00
|
|
|
}
|
2012-07-26 18:09:22 -05:00
|
|
|
|
2013-05-04 08:54:58 -05:00
|
|
|
/// Removes a key from the map, returning the value at the key if the key
|
|
|
|
/// was previously in the map.
|
|
|
|
fn pop(&mut self, k: &K) -> Option<V> {
|
2014-02-25 10:04:38 -06:00
|
|
|
let hash = self.hasher.hash(k) as uint;
|
2013-05-04 08:54:58 -05:00
|
|
|
self.pop_internal(hash, k)
|
2013-04-03 07:45:14 -05:00
|
|
|
}
|
|
|
|
}
|
2013-03-28 22:30:50 -05:00
|
|
|
|
2013-05-31 17:17:22 -05:00
|
|
|
impl<K: Hash + Eq, V> HashMap<K, V> {
|
2013-04-03 08:28:36 -05:00
|
|
|
/// Create an empty HashMap
|
2014-02-25 10:04:38 -06:00
|
|
|
pub fn new() -> HashMap<K, V, SipHasher> {
|
2013-04-03 08:28:36 -05:00
|
|
|
HashMap::with_capacity(INITIAL_CAPACITY)
|
2013-04-03 07:45:14 -05:00
|
|
|
}
|
2013-01-23 16:06:32 -06:00
|
|
|
|
2013-08-01 03:11:25 -05:00
|
|
|
/// Create an empty HashMap with space for at least `capacity`
|
|
|
|
/// elements in the hash table.
|
2013-05-31 17:17:22 -05:00
|
|
|
pub fn with_capacity(capacity: uint) -> HashMap<K, V> {
|
2013-08-01 03:11:25 -05:00
|
|
|
let mut r = rand::task_rng();
|
2014-02-25 10:04:38 -06:00
|
|
|
let hasher = SipHasher::new_with_keys(r.gen(), r.gen());
|
2014-03-06 20:07:52 -06:00
|
|
|
HashMap::with_capacity_and_hasher(capacity, hasher)
|
2014-02-25 10:04:38 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<K: Hash<S> + Eq, V, S, H: Hasher<S>> HashMap<K, V, H> {
|
|
|
|
pub fn with_hasher(hasher: H) -> HashMap<K, V, H> {
|
2014-03-06 20:07:52 -06:00
|
|
|
HashMap::with_capacity_and_hasher(INITIAL_CAPACITY, hasher)
|
2013-08-01 03:11:25 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Create an empty HashMap with space for at least `capacity`
|
2014-02-25 10:04:38 -06:00
|
|
|
/// elements, using `hasher` to hash the keys.
|
2013-08-01 03:11:25 -05:00
|
|
|
///
|
2014-02-25 10:04:38 -06:00
|
|
|
/// Warning: `hasher` is normally randomly generated, and
|
|
|
|
/// is designed to allow HashMaps to be resistant to attacks that
|
|
|
|
/// cause many collisions and very poor performance. Setting it
|
2013-08-01 03:11:25 -05:00
|
|
|
/// manually using this function can expose a DoS attack vector.
|
2014-03-06 20:07:52 -06:00
|
|
|
pub fn with_capacity_and_hasher(capacity: uint, hasher: H) -> HashMap<K, V, H> {
|
2014-02-06 01:34:33 -06:00
|
|
|
let cap = max(INITIAL_CAPACITY, capacity);
|
2013-08-01 03:11:25 -05:00
|
|
|
HashMap {
|
2014-02-25 10:04:38 -06:00
|
|
|
hasher: hasher,
|
2013-08-01 03:11:25 -05:00
|
|
|
resize_at: resize_at(cap),
|
|
|
|
size: 0,
|
2014-01-18 06:33:41 -06:00
|
|
|
buckets: Vec::from_fn(cap, |_| None)
|
2013-08-01 03:11:25 -05:00
|
|
|
}
|
2013-04-03 07:45:14 -05:00
|
|
|
}
|
2013-02-15 00:35:15 -06:00
|
|
|
|
2013-04-03 07:45:14 -05:00
|
|
|
/// Reserve space for at least `n` elements in the hash table.
|
2014-01-31 07:03:20 -06:00
|
|
|
pub fn reserve(&mut self, n: uint) {
|
2013-04-03 07:45:14 -05:00
|
|
|
if n > self.buckets.len() {
|
|
|
|
let buckets = n * 4 / 3 + 1;
|
2014-01-29 23:35:17 -06:00
|
|
|
self.resize(num::next_power_of_two(buckets));
|
2012-10-08 09:05:01 -05:00
|
|
|
}
|
2013-04-03 07:45:14 -05:00
|
|
|
}
|
2012-07-26 18:09:22 -05:00
|
|
|
|
2013-05-31 20:48:06 -05:00
|
|
|
/// Modify and return the value corresponding to the key in the map, or
|
|
|
|
/// insert and return a new value if it doesn't exist.
|
2013-12-26 07:24:10 -06:00
|
|
|
///
|
|
|
|
/// This method allows for all insertion behaviours of a hashmap,
|
|
|
|
/// see methods like `insert`, `find_or_insert` and
|
|
|
|
/// `insert_or_update_with` for less general and more friendly
|
|
|
|
/// variations of this.
|
|
|
|
///
|
|
|
|
/// # Example
|
|
|
|
///
|
|
|
|
/// ```rust
|
2014-02-19 21:29:58 -06:00
|
|
|
/// use collections::HashMap;
|
2013-12-26 07:24:10 -06:00
|
|
|
///
|
|
|
|
/// // map some strings to vectors of strings
|
|
|
|
/// let mut map = HashMap::<~str, ~[~str]>::new();
|
|
|
|
/// map.insert(~"a key", ~[~"value"]);
|
|
|
|
/// map.insert(~"z key", ~[~"value"]);
|
|
|
|
///
|
|
|
|
/// let new = ~[~"a key", ~"b key", ~"z key"];
|
|
|
|
/// for k in new.move_iter() {
|
|
|
|
/// map.mangle(k, ~"new value",
|
|
|
|
/// // if the key doesn't exist in the map yet, add it in
|
|
|
|
/// // the obvious way.
|
|
|
|
/// |_k, v| ~[v],
|
|
|
|
/// // if the key does exist either prepend or append this
|
|
|
|
/// // new value based on the first letter of the key.
|
|
|
|
/// |key, already, new| {
|
|
|
|
/// if key.starts_with("z") {
|
|
|
|
/// already.unshift(new);
|
|
|
|
/// } else {
|
|
|
|
/// already.push(new);
|
|
|
|
/// }
|
|
|
|
/// });
|
|
|
|
/// }
|
|
|
|
///
|
|
|
|
/// for (k, v) in map.iter() {
|
|
|
|
/// println!("{} -> {:?}", *k, *v);
|
|
|
|
/// }
|
|
|
|
/// ```
|
2013-11-18 23:15:42 -06:00
|
|
|
pub fn mangle<'a,
|
|
|
|
A>(
|
|
|
|
&'a mut self,
|
|
|
|
k: K,
|
|
|
|
a: A,
|
|
|
|
not_found: |&K, A| -> V,
|
|
|
|
found: |&K, &mut V, A|)
|
|
|
|
-> &'a mut V {
|
2013-05-06 22:29:54 -05:00
|
|
|
if self.size >= self.resize_at {
|
|
|
|
// n.b.: We could also do this after searching, so
|
|
|
|
// that we do not resize if this call to insert is
|
|
|
|
// simply going to update a key in place. My sense
|
|
|
|
// though is that it's worse to have to search through
|
|
|
|
// buckets to find the right spot twice than to just
|
|
|
|
// resize in this corner case.
|
|
|
|
self.expand();
|
|
|
|
}
|
|
|
|
|
2014-02-25 10:04:38 -06:00
|
|
|
let hash = self.hasher.hash(&k) as uint;
|
2013-05-06 22:29:54 -05:00
|
|
|
let idx = match self.bucket_for_key_with_hash(hash, &k) {
|
2013-10-21 15:08:31 -05:00
|
|
|
TableFull => fail!("Internal logic error"),
|
2013-05-31 20:48:06 -05:00
|
|
|
FoundEntry(idx) => { found(&k, self.mut_value_for_bucket(idx), a); idx }
|
2013-05-06 22:29:54 -05:00
|
|
|
FoundHole(idx) => {
|
2013-05-31 20:48:06 -05:00
|
|
|
let v = not_found(&k, a);
|
2014-01-18 06:33:41 -06:00
|
|
|
self.buckets.as_mut_slice()[idx] = Some(Bucket{hash: hash, key: k, value: v});
|
2013-05-06 22:29:54 -05:00
|
|
|
self.size += 1;
|
|
|
|
idx
|
2013-05-31 20:48:06 -05:00
|
|
|
}
|
2013-05-06 22:29:54 -05:00
|
|
|
};
|
|
|
|
|
2013-05-31 20:48:06 -05:00
|
|
|
self.mut_value_for_bucket(idx)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Return the value corresponding to the key in the map, or insert
|
|
|
|
/// and return the value if it doesn't exist.
|
|
|
|
pub fn find_or_insert<'a>(&'a mut self, k: K, v: V) -> &'a mut V {
|
|
|
|
self.mangle(k, v, |_k, a| a, |_k,_v,_a| ())
|
2013-05-06 22:29:54 -05:00
|
|
|
}
|
|
|
|
|
2013-04-03 07:45:14 -05:00
|
|
|
/// Return the value corresponding to the key in the map, or create,
|
|
|
|
/// insert, and return a new value if it doesn't exist.
|
2013-11-18 23:15:42 -06:00
|
|
|
pub fn find_or_insert_with<'a>(&'a mut self, k: K, f: |&K| -> V)
|
2013-05-31 20:48:06 -05:00
|
|
|
-> &'a mut V {
|
|
|
|
self.mangle(k, (), |k,_a| f(k), |_k,_v,_a| ())
|
2013-05-06 22:29:54 -05:00
|
|
|
}
|
|
|
|
|
2013-05-31 20:50:20 -05:00
|
|
|
/// Insert a key-value pair into the map if the key is not already present.
|
|
|
|
/// Otherwise, modify the existing value for the key.
|
|
|
|
/// Returns the new or modified value for the key.
|
2013-11-18 23:15:42 -06:00
|
|
|
pub fn insert_or_update_with<'a>(
|
|
|
|
&'a mut self,
|
|
|
|
k: K,
|
|
|
|
v: V,
|
|
|
|
f: |&K, &mut V|)
|
|
|
|
-> &'a mut V {
|
2013-05-31 20:50:20 -05:00
|
|
|
self.mangle(k, v, |_k,a| a, |k,v,_a| f(k,v))
|
|
|
|
}
|
|
|
|
|
2013-05-31 17:17:22 -05:00
|
|
|
/// Retrieves a value for the given key, failing if the key is not
|
|
|
|
/// present.
|
|
|
|
pub fn get<'a>(&'a self, k: &K) -> &'a V {
|
2013-04-10 15:11:35 -05:00
|
|
|
match self.find(k) {
|
|
|
|
Some(v) => v,
|
2013-10-21 15:08:31 -05:00
|
|
|
None => fail!("No entry found for key: {:?}", k),
|
2013-04-10 15:11:35 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-05-31 14:56:05 -05:00
|
|
|
/// Retrieves a (mutable) value for the given key, failing if the key
|
|
|
|
/// is not present.
|
|
|
|
pub fn get_mut<'a>(&'a mut self, k: &K) -> &'a mut V {
|
|
|
|
match self.find_mut(k) {
|
|
|
|
Some(v) => v,
|
2013-10-21 15:08:31 -05:00
|
|
|
None => fail!("No entry found for key: {:?}", k),
|
2013-05-31 14:56:05 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-04-03 07:45:14 -05:00
|
|
|
/// Return true if the map contains a value for the specified key,
|
|
|
|
/// using equivalence
|
2014-02-25 10:04:38 -06:00
|
|
|
pub fn contains_key_equiv<Q:Hash<S> + Equiv<K>>(&self, key: &Q) -> bool {
|
2013-04-03 07:45:14 -05:00
|
|
|
match self.bucket_for_key_equiv(key) {
|
|
|
|
FoundEntry(_) => {true}
|
|
|
|
TableFull | FoundHole(_) => {false}
|
2013-03-04 21:43:14 -06:00
|
|
|
}
|
2013-04-03 07:45:14 -05:00
|
|
|
}
|
2013-03-04 21:43:14 -06:00
|
|
|
|
2013-04-03 07:45:14 -05:00
|
|
|
/// Return the value corresponding to the key in the map, using
|
|
|
|
/// equivalence
|
2014-02-25 10:04:38 -06:00
|
|
|
pub fn find_equiv<'a, Q:Hash<S> + Equiv<K>>(&'a self, k: &Q) -> Option<&'a V> {
|
2013-04-10 15:11:35 -05:00
|
|
|
match self.bucket_for_key_equiv(k) {
|
|
|
|
FoundEntry(idx) => Some(self.value_for_bucket(idx)),
|
|
|
|
TableFull | FoundHole(_) => None,
|
|
|
|
}
|
|
|
|
}
|
2013-06-21 10:05:05 -05:00
|
|
|
|
2013-12-31 13:09:18 -06:00
|
|
|
/// An iterator visiting all keys in arbitrary order.
|
|
|
|
/// Iterator element type is &'a K.
|
2014-01-14 21:32:24 -06:00
|
|
|
pub fn keys<'a>(&'a self) -> Keys<'a, K, V> {
|
2013-12-31 13:09:18 -06:00
|
|
|
self.iter().map(|(k, _v)| k)
|
2013-06-24 16:45:00 -05:00
|
|
|
}
|
|
|
|
|
2013-12-31 13:09:18 -06:00
|
|
|
/// An iterator visiting all values in arbitrary order.
|
|
|
|
/// Iterator element type is &'a V.
|
2014-01-14 21:32:24 -06:00
|
|
|
pub fn values<'a>(&'a self) -> Values<'a, K, V> {
|
2013-12-31 13:09:18 -06:00
|
|
|
self.iter().map(|(_k, v)| v)
|
2013-06-24 16:45:00 -05:00
|
|
|
}
|
|
|
|
|
2013-06-21 10:05:05 -05:00
|
|
|
/// An iterator visiting all key-value pairs in arbitrary order.
|
|
|
|
/// Iterator element type is (&'a K, &'a V).
|
2014-01-14 21:32:24 -06:00
|
|
|
pub fn iter<'a>(&'a self) -> Entries<'a, K, V> {
|
2014-01-18 06:33:41 -06:00
|
|
|
Entries { iter: self.buckets.as_slice().iter() }
|
2013-06-21 10:05:05 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/// An iterator visiting all key-value pairs in arbitrary order,
|
|
|
|
/// with mutable references to the values.
|
|
|
|
/// Iterator element type is (&'a K, &'a mut V).
|
2014-01-14 21:32:24 -06:00
|
|
|
pub fn mut_iter<'a>(&'a mut self) -> MutEntries<'a, K, V> {
|
2014-01-18 06:33:41 -06:00
|
|
|
MutEntries { iter: self.buckets.as_mut_slice().mut_iter() }
|
2013-06-21 10:05:05 -05:00
|
|
|
}
|
2013-07-16 09:39:24 -05:00
|
|
|
|
|
|
|
/// Creates a consuming iterator, that is, one that moves each key-value
|
|
|
|
/// pair out of the map in arbitrary order. The map cannot be used after
|
|
|
|
/// calling this.
|
2014-01-14 21:32:24 -06:00
|
|
|
pub fn move_iter(self) -> MoveEntries<K, V> {
|
|
|
|
MoveEntries {iter: self.buckets.move_iter()}
|
2013-07-16 09:39:24 -05:00
|
|
|
}
|
2013-04-03 07:45:14 -05:00
|
|
|
}
|
2012-07-31 16:11:57 -05:00
|
|
|
|
2014-02-25 10:04:38 -06:00
|
|
|
impl<K: Hash<S> + Eq, V: Clone, S, H: Hasher<S>> HashMap<K, V, H> {
|
2013-05-05 11:17:59 -05:00
|
|
|
/// Like `find`, but returns a copy of the value.
|
2013-05-31 17:17:22 -05:00
|
|
|
pub fn find_copy(&self, k: &K) -> Option<V> {
|
2013-09-20 01:08:47 -05:00
|
|
|
self.find(k).map(|v| (*v).clone())
|
2013-05-05 11:17:59 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Like `get`, but returns a copy of the value.
|
2013-05-31 17:17:22 -05:00
|
|
|
pub fn get_copy(&self, k: &K) -> V {
|
2013-07-02 14:47:32 -05:00
|
|
|
(*self.get(k)).clone()
|
2013-05-05 11:17:59 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-02-25 10:04:38 -06:00
|
|
|
impl<K: Hash<S> + Eq, V: Eq, S, H: Hasher<S>> Eq for HashMap<K, V, H> {
|
|
|
|
fn eq(&self, other: &HashMap<K, V, H>) -> bool {
|
2013-04-03 07:45:14 -05:00
|
|
|
if self.len() != other.len() { return false; }
|
2012-12-10 11:00:52 -06:00
|
|
|
|
2013-11-20 16:17:12 -06:00
|
|
|
self.iter().all(|(key, value)| {
|
2013-04-03 07:45:14 -05:00
|
|
|
match other.find(key) {
|
2013-07-18 00:35:34 -05:00
|
|
|
None => false,
|
|
|
|
Some(v) => value == v
|
2012-12-10 11:00:52 -06:00
|
|
|
}
|
2013-11-20 16:17:12 -06:00
|
|
|
})
|
2012-12-10 11:00:52 -06:00
|
|
|
}
|
2013-01-20 13:18:24 -06:00
|
|
|
|
2014-02-25 10:04:38 -06:00
|
|
|
fn ne(&self, other: &HashMap<K, V, H>) -> bool { !self.eq(other) }
|
2013-04-03 07:45:14 -05:00
|
|
|
}
|
2013-01-20 13:18:24 -06:00
|
|
|
|
2014-02-25 10:04:38 -06:00
|
|
|
impl<K: Hash<S> + Eq + Clone, V:Clone, S, H: Hasher<S> + Clone> Clone for HashMap<K, V, H> {
|
|
|
|
fn clone(&self) -> HashMap<K, V, H> {
|
2014-03-06 20:07:52 -06:00
|
|
|
let mut new_map = HashMap::with_capacity_and_hasher(self.len(),
|
|
|
|
self.hasher.clone());
|
2013-08-03 11:45:23 -05:00
|
|
|
for (key, value) in self.iter() {
|
2013-07-02 14:47:32 -05:00
|
|
|
new_map.insert((*key).clone(), (*value).clone());
|
|
|
|
}
|
|
|
|
new_map
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-02-25 10:04:38 -06:00
|
|
|
impl<K: fmt::Show + Hash<S> + Eq, V: fmt::Show, S, H: Hasher<S>> fmt::Show for HashMap<K, V, H> {
|
2014-02-12 13:41:34 -06:00
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
2014-02-19 12:07:49 -06:00
|
|
|
try!(write!(f.buf, r"\{"))
|
2014-02-12 13:41:34 -06:00
|
|
|
let mut first = true;
|
|
|
|
for (key, value) in self.iter() {
|
|
|
|
if first {
|
|
|
|
first = false;
|
|
|
|
} else {
|
2014-02-19 12:07:49 -06:00
|
|
|
try!(write!(f.buf, ", "));
|
2014-02-12 13:41:34 -06:00
|
|
|
}
|
2014-02-19 12:07:49 -06:00
|
|
|
try!(write!(f.buf, "{}: {}", *key, *value));
|
2014-02-12 13:41:34 -06:00
|
|
|
}
|
|
|
|
write!(f.buf, r"\}")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-06-21 10:05:05 -05:00
|
|
|
/// HashMap iterator
|
2013-07-18 10:38:17 -05:00
|
|
|
#[deriving(Clone)]
|
2014-01-14 21:32:24 -06:00
|
|
|
pub struct Entries<'a, K, V> {
|
2014-01-18 06:33:41 -06:00
|
|
|
priv iter: Items<'a, Option<Bucket<K, V>>>,
|
2013-06-21 10:05:05 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/// HashMap mutable values iterator
|
2014-01-14 21:32:24 -06:00
|
|
|
pub struct MutEntries<'a, K, V> {
|
2014-01-18 06:33:41 -06:00
|
|
|
priv iter: MutItems<'a, Option<Bucket<K, V>>>,
|
2013-06-21 10:05:05 -05:00
|
|
|
}
|
|
|
|
|
2013-08-07 21:21:36 -05:00
|
|
|
/// HashMap move iterator
|
2014-01-14 21:32:24 -06:00
|
|
|
pub struct MoveEntries<K, V> {
|
2014-01-18 06:33:41 -06:00
|
|
|
priv iter: vec_ng::MoveItems<Option<Bucket<K, V>>>,
|
2013-07-15 13:43:16 -05:00
|
|
|
}
|
|
|
|
|
2013-12-31 13:09:18 -06:00
|
|
|
/// HashMap keys iterator
|
2014-01-14 21:32:24 -06:00
|
|
|
pub type Keys<'a, K, V> =
|
|
|
|
iter::Map<'static, (&'a K, &'a V), &'a K, Entries<'a, K, V>>;
|
2013-12-31 13:09:18 -06:00
|
|
|
|
|
|
|
/// HashMap values iterator
|
2014-01-14 21:32:24 -06:00
|
|
|
pub type Values<'a, K, V> =
|
|
|
|
iter::Map<'static, (&'a K, &'a V), &'a V, Entries<'a, K, V>>;
|
2013-12-31 13:09:18 -06:00
|
|
|
|
2013-06-21 10:05:05 -05:00
|
|
|
/// HashSet iterator
|
2013-07-18 10:38:17 -05:00
|
|
|
#[deriving(Clone)]
|
2014-01-14 21:32:24 -06:00
|
|
|
pub struct SetItems<'a, K> {
|
2014-01-18 06:33:41 -06:00
|
|
|
priv iter: Items<'a, Option<Bucket<K, ()>>>,
|
2013-06-21 10:05:05 -05:00
|
|
|
}
|
|
|
|
|
2013-08-07 21:21:36 -05:00
|
|
|
/// HashSet move iterator
|
2014-01-14 21:32:24 -06:00
|
|
|
pub struct SetMoveItems<K> {
|
2014-01-18 06:33:41 -06:00
|
|
|
priv iter: vec_ng::MoveItems<Option<Bucket<K, ()>>>,
|
2013-07-15 13:43:16 -05:00
|
|
|
}
|
|
|
|
|
2014-01-14 21:32:24 -06:00
|
|
|
impl<'a, K, V> Iterator<(&'a K, &'a V)> for Entries<'a, K, V> {
|
2013-06-21 10:05:05 -05:00
|
|
|
#[inline]
|
2013-12-10 01:16:18 -06:00
|
|
|
fn next(&mut self) -> Option<(&'a K, &'a V)> {
|
2013-08-03 11:45:23 -05:00
|
|
|
for elt in self.iter {
|
2013-06-21 10:05:05 -05:00
|
|
|
match elt {
|
|
|
|
&Some(ref bucket) => return Some((&bucket.key, &bucket.value)),
|
|
|
|
&None => {},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-01-14 21:32:24 -06:00
|
|
|
impl<'a, K, V> Iterator<(&'a K, &'a mut V)> for MutEntries<'a, K, V> {
|
2013-06-21 10:05:05 -05:00
|
|
|
#[inline]
|
2013-12-10 01:16:18 -06:00
|
|
|
fn next(&mut self) -> Option<(&'a K, &'a mut V)> {
|
2013-08-03 11:45:23 -05:00
|
|
|
for elt in self.iter {
|
2013-06-21 10:05:05 -05:00
|
|
|
match elt {
|
|
|
|
&Some(ref mut bucket) => return Some((&bucket.key, &mut bucket.value)),
|
|
|
|
&None => {},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-01-14 21:32:24 -06:00
|
|
|
impl<K, V> Iterator<(K, V)> for MoveEntries<K, V> {
|
2013-07-15 13:43:16 -05:00
|
|
|
#[inline]
|
|
|
|
fn next(&mut self) -> Option<(K, V)> {
|
2013-08-03 11:45:23 -05:00
|
|
|
for elt in self.iter {
|
2013-07-15 13:43:16 -05:00
|
|
|
match elt {
|
2013-11-28 14:22:53 -06:00
|
|
|
Some(Bucket {key, value, ..}) => return Some((key, value)),
|
2013-07-15 13:43:16 -05:00
|
|
|
None => {},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-01-14 21:32:24 -06:00
|
|
|
impl<'a, K> Iterator<&'a K> for SetItems<'a, K> {
|
2013-06-21 10:05:05 -05:00
|
|
|
#[inline]
|
2013-12-10 01:16:18 -06:00
|
|
|
fn next(&mut self) -> Option<&'a K> {
|
2013-08-03 11:45:23 -05:00
|
|
|
for elt in self.iter {
|
2013-06-21 10:05:05 -05:00
|
|
|
match elt {
|
|
|
|
&Some(ref bucket) => return Some(&bucket.key),
|
|
|
|
&None => {},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-01-14 21:32:24 -06:00
|
|
|
impl<K> Iterator<K> for SetMoveItems<K> {
|
2013-07-15 13:43:16 -05:00
|
|
|
#[inline]
|
|
|
|
fn next(&mut self) -> Option<K> {
|
2013-08-03 11:45:23 -05:00
|
|
|
for elt in self.iter {
|
2013-07-15 13:43:16 -05:00
|
|
|
match elt {
|
|
|
|
Some(bucket) => return Some(bucket.key),
|
|
|
|
None => {},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-02-25 10:04:38 -06:00
|
|
|
impl<K: Hash<S> + Eq, V, S, H: Hasher<S> + Default> FromIterator<(K, V)> for HashMap<K, V, H> {
|
|
|
|
fn from_iterator<T: Iterator<(K, V)>>(iter: &mut T) -> HashMap<K, V, H> {
|
2013-07-14 10:26:03 -05:00
|
|
|
let (lower, _) = iter.size_hint();
|
2014-03-06 20:07:52 -06:00
|
|
|
let mut map = HashMap::with_capacity_and_hasher(lower, Default::default());
|
2013-07-29 19:17:17 -05:00
|
|
|
map.extend(iter);
|
|
|
|
map
|
|
|
|
}
|
|
|
|
}
|
2013-07-14 10:26:03 -05:00
|
|
|
|
2014-02-25 10:04:38 -06:00
|
|
|
impl<K: Hash<S> + Eq, V, S, H: Hasher<S> + Default> Extendable<(K, V)> for HashMap<K, V, H> {
|
std: Move the iterator param on FromIterator and Extendable to the method.
If they are on the trait then it is extremely annoying to use them as
generic parameters to a function, e.g. with the iterator param on the trait
itself, if one was to pass an Extendable<int> to a function that filled it
either from a Range or a Map<VecIterator>, one needs to write something
like:
fn foo<E: Extendable<int, Range<int>> +
Extendable<int, Map<&'self int, int, VecIterator<int>>>
(e: &mut E, ...) { ... }
since using a generic, i.e. `foo<E: Extendable<int, I>, I: Iterator<int>>`
means that `foo` takes 2 type parameters, and the caller has to specify them
(which doesn't work anyway, as they'll mismatch with the iterators used in
`foo` itself).
This patch changes it to:
fn foo<E: Extendable<int>>(e: &mut E, ...) { ... }
2013-08-13 08:08:14 -05:00
|
|
|
fn extend<T: Iterator<(K, V)>>(&mut self, iter: &mut T) {
|
2013-08-03 11:45:23 -05:00
|
|
|
for (k, v) in *iter {
|
2013-07-29 19:17:17 -05:00
|
|
|
self.insert(k, v);
|
2013-07-14 10:26:03 -05:00
|
|
|
}
|
|
|
|
}
|
2013-07-14 12:18:50 -05:00
|
|
|
}
|
2013-06-21 10:05:05 -05:00
|
|
|
|
2014-02-25 10:04:38 -06:00
|
|
|
impl<K: Hash<S> + Eq, V, S, H: Hasher<S> + Default> Default for HashMap<K, V, H> {
|
|
|
|
fn default() -> HashMap<K, V, H> {
|
2014-03-06 20:07:52 -06:00
|
|
|
HashMap::with_capacity_and_hasher(INITIAL_CAPACITY, Default::default())
|
2014-02-25 10:04:38 -06:00
|
|
|
}
|
2013-09-09 21:28:05 -05:00
|
|
|
}
|
|
|
|
|
2013-05-28 16:35:52 -05:00
|
|
|
/// An implementation of a hash set using the underlying representation of a
|
|
|
|
/// HashMap where the value is (). As with the `HashMap` type, a `HashSet`
|
|
|
|
/// requires that the elements implement the `Eq` and `Hash` traits.
|
2014-02-25 10:04:38 -06:00
|
|
|
pub struct HashSet<T, H = SipHasher> {
|
|
|
|
priv map: HashMap<T, (), H>
|
2013-04-03 07:45:14 -05:00
|
|
|
}
|
2013-01-20 13:18:24 -06:00
|
|
|
|
2014-02-25 10:04:38 -06:00
|
|
|
impl<T: Hash<S> + Eq, S, H: Hasher<S>> Eq for HashSet<T, H> {
|
|
|
|
fn eq(&self, other: &HashSet<T, H>) -> bool { self.map == other.map }
|
|
|
|
fn ne(&self, other: &HashSet<T, H>) -> bool { self.map != other.map }
|
2013-04-03 07:45:14 -05:00
|
|
|
}
|
2013-01-23 15:47:27 -06:00
|
|
|
|
2014-02-25 10:04:38 -06:00
|
|
|
impl<T: Hash<S> + Eq, S, H: Hasher<S>> Container for HashSet<T, H> {
|
2013-04-03 07:45:14 -05:00
|
|
|
/// Return the number of elements in the set
|
2013-06-23 22:44:11 -05:00
|
|
|
fn len(&self) -> uint { self.map.len() }
|
2013-04-03 07:45:14 -05:00
|
|
|
}
|
2013-01-21 16:25:57 -06:00
|
|
|
|
2014-02-25 10:04:38 -06:00
|
|
|
impl<T: Hash<S> + Eq, S, H: Hasher<S>> Mutable for HashSet<T, H> {
|
2013-04-03 07:45:14 -05:00
|
|
|
/// Clear the set, removing all values.
|
|
|
|
fn clear(&mut self) { self.map.clear() }
|
|
|
|
}
|
2013-01-20 13:18:24 -06:00
|
|
|
|
2014-02-25 10:04:38 -06:00
|
|
|
impl<T: Hash<S> + Eq, S, H: Hasher<S>> Set<T> for HashSet<T, H> {
|
2013-04-03 07:45:14 -05:00
|
|
|
/// Return true if the set contains a value
|
|
|
|
fn contains(&self, value: &T) -> bool { self.map.contains_key(value) }
|
2013-01-20 13:18:24 -06:00
|
|
|
|
2013-04-03 07:45:14 -05:00
|
|
|
/// Return true if the set has no elements in common with `other`.
|
|
|
|
/// This is equivalent to checking for an empty intersection.
|
2014-02-25 10:04:38 -06:00
|
|
|
fn is_disjoint(&self, other: &HashSet<T, H>) -> bool {
|
2013-06-21 10:05:26 -05:00
|
|
|
self.iter().all(|v| !other.contains(v))
|
2013-04-03 07:45:14 -05:00
|
|
|
}
|
2013-01-29 15:07:11 -06:00
|
|
|
|
2013-04-03 07:45:14 -05:00
|
|
|
/// Return true if the set is a subset of another
|
2014-02-25 10:04:38 -06:00
|
|
|
fn is_subset(&self, other: &HashSet<T, H>) -> bool {
|
2013-06-21 10:05:26 -05:00
|
|
|
self.iter().all(|v| other.contains(v))
|
2013-04-03 07:45:14 -05:00
|
|
|
}
|
2013-01-29 18:30:26 -06:00
|
|
|
|
2013-04-03 07:45:14 -05:00
|
|
|
/// Return true if the set is a superset of another
|
2014-02-25 10:04:38 -06:00
|
|
|
fn is_superset(&self, other: &HashSet<T, H>) -> bool {
|
2013-04-03 07:45:14 -05:00
|
|
|
other.is_subset(self)
|
|
|
|
}
|
|
|
|
}
|
2013-01-20 13:18:24 -06:00
|
|
|
|
2014-02-25 10:04:38 -06:00
|
|
|
impl<T: Hash<S> + Eq, S, H: Hasher<S>> MutableSet<T> for HashSet<T, H> {
|
2013-07-13 21:44:36 -05:00
|
|
|
/// Add a value to the set. Return true if the value was not already
|
|
|
|
/// present in the set.
|
|
|
|
fn insert(&mut self, value: T) -> bool { self.map.insert(value, ()) }
|
|
|
|
|
|
|
|
/// Remove a value from the set. Return true if the value was
|
|
|
|
/// present in the set.
|
|
|
|
fn remove(&mut self, value: &T) -> bool { self.map.remove(value) }
|
|
|
|
}
|
|
|
|
|
2014-02-25 10:04:38 -06:00
|
|
|
impl<T: Hash<SipState> + Eq> HashSet<T, SipHasher> {
|
2013-04-03 08:28:36 -05:00
|
|
|
/// Create an empty HashSet
|
2014-02-25 10:04:38 -06:00
|
|
|
pub fn new() -> HashSet<T, SipHasher> {
|
2013-04-03 08:28:36 -05:00
|
|
|
HashSet::with_capacity(INITIAL_CAPACITY)
|
2013-04-03 07:45:14 -05:00
|
|
|
}
|
2013-03-28 22:30:50 -05:00
|
|
|
|
2013-04-03 08:28:36 -05:00
|
|
|
/// Create an empty HashSet with space for at least `n` elements in
|
2013-04-03 07:45:14 -05:00
|
|
|
/// the hash table.
|
2014-02-25 10:04:38 -06:00
|
|
|
pub fn with_capacity(capacity: uint) -> HashSet<T, SipHasher> {
|
2013-04-03 08:28:36 -05:00
|
|
|
HashSet { map: HashMap::with_capacity(capacity) }
|
2013-04-03 07:45:14 -05:00
|
|
|
}
|
2014-02-25 10:04:38 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
impl<T: Hash<S> + Eq, S, H: Hasher<S>> HashSet<T, H> {
|
|
|
|
pub fn with_hasher(hasher: H) -> HashSet<T, H> {
|
2014-03-06 20:07:52 -06:00
|
|
|
HashSet::with_capacity_and_hasher(INITIAL_CAPACITY, hasher)
|
2014-02-25 10:04:38 -06:00
|
|
|
}
|
2013-02-15 00:35:15 -06:00
|
|
|
|
2013-09-10 17:39:26 -05:00
|
|
|
/// Create an empty HashSet with space for at least `capacity`
|
|
|
|
/// elements in the hash table, using `k0` and `k1` as the keys.
|
|
|
|
///
|
2014-02-25 10:04:38 -06:00
|
|
|
/// Warning: `hasher` is normally randomly generated, and
|
2013-09-10 17:39:26 -05:00
|
|
|
/// are designed to allow HashSets 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.
|
2014-03-06 20:07:52 -06:00
|
|
|
pub fn with_capacity_and_hasher(capacity: uint, hasher: H) -> HashSet<T, H> {
|
2014-02-25 10:04:38 -06:00
|
|
|
HashSet {
|
2014-03-06 20:07:52 -06:00
|
|
|
map: HashMap::with_capacity_and_hasher(capacity, hasher)
|
2014-02-25 10:04:38 -06:00
|
|
|
}
|
2013-09-10 17:39:26 -05:00
|
|
|
}
|
|
|
|
|
2013-04-03 07:45:14 -05:00
|
|
|
/// Reserve space for at least `n` elements in the hash table.
|
2014-01-31 07:03:20 -06:00
|
|
|
pub fn reserve(&mut self, n: uint) {
|
|
|
|
self.map.reserve(n)
|
2013-04-03 07:45:14 -05:00
|
|
|
}
|
2013-03-21 14:41:37 -05:00
|
|
|
|
2013-05-31 17:17:22 -05:00
|
|
|
/// Returns true if the hash set contains a value equivalent to the
|
|
|
|
/// given query value.
|
2014-02-25 10:04:38 -06:00
|
|
|
pub fn contains_equiv<Q: Hash<S> + Equiv<T>>(&self, value: &Q) -> bool {
|
2013-05-11 10:42:59 -05:00
|
|
|
self.map.contains_key_equiv(value)
|
|
|
|
}
|
2013-06-21 10:05:05 -05:00
|
|
|
|
|
|
|
/// An iterator visiting all elements in arbitrary order.
|
|
|
|
/// Iterator element type is &'a T.
|
2014-01-14 21:32:24 -06:00
|
|
|
pub fn iter<'a>(&'a self) -> SetItems<'a, T> {
|
2014-01-18 06:33:41 -06:00
|
|
|
SetItems { iter: self.map.buckets.as_slice().iter() }
|
2013-06-21 10:05:05 -05:00
|
|
|
}
|
2013-07-15 20:55:52 -05:00
|
|
|
|
2013-07-16 09:39:24 -05:00
|
|
|
/// Creates a consuming iterator, that is, one that moves each value out
|
|
|
|
/// of the set in arbitrary order. The set cannot be used after calling
|
|
|
|
/// this.
|
2014-01-14 21:32:24 -06:00
|
|
|
pub fn move_iter(self) -> SetMoveItems<T> {
|
|
|
|
SetMoveItems {iter: self.map.buckets.move_iter()}
|
2013-07-16 09:39:24 -05:00
|
|
|
}
|
|
|
|
|
2013-07-15 20:55:52 -05:00
|
|
|
/// Visit the values representing the difference
|
2014-02-25 10:04:38 -06:00
|
|
|
pub fn difference<'a>(&'a self, other: &'a HashSet<T, H>) -> SetAlgebraItems<'a, T, H> {
|
2013-08-03 14:34:00 -05:00
|
|
|
Repeat::new(other)
|
|
|
|
.zip(self.iter())
|
|
|
|
.filter_map(|(other, elt)| {
|
|
|
|
if !other.contains(elt) { Some(elt) } else { None }
|
|
|
|
})
|
2013-07-15 20:55:52 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Visit the values representing the symmetric difference
|
2014-02-25 10:04:38 -06:00
|
|
|
pub fn symmetric_difference<'a>(&'a self, other: &'a HashSet<T, H>)
|
|
|
|
-> Chain<SetAlgebraItems<'a, T, H>, SetAlgebraItems<'a, T, H>> {
|
2013-11-23 04:18:51 -06:00
|
|
|
self.difference(other).chain(other.difference(self))
|
2013-07-15 20:55:52 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Visit the values representing the intersection
|
2014-02-25 10:04:38 -06:00
|
|
|
pub fn intersection<'a>(&'a self, other: &'a HashSet<T, H>)
|
|
|
|
-> SetAlgebraItems<'a, T, H> {
|
2013-08-03 14:34:00 -05:00
|
|
|
Repeat::new(other)
|
|
|
|
.zip(self.iter())
|
|
|
|
.filter_map(|(other, elt)| {
|
|
|
|
if other.contains(elt) { Some(elt) } else { None }
|
|
|
|
})
|
2013-07-15 20:55:52 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Visit the values representing the union
|
2014-02-25 10:04:38 -06:00
|
|
|
pub fn union<'a>(&'a self, other: &'a HashSet<T, H>)
|
|
|
|
-> Chain<SetItems<'a, T>, SetAlgebraItems<'a, T, H>> {
|
2013-11-23 04:18:51 -06:00
|
|
|
self.iter().chain(other.difference(self))
|
2013-07-15 20:55:52 -05:00
|
|
|
}
|
|
|
|
|
2013-04-03 07:45:14 -05:00
|
|
|
}
|
|
|
|
|
2014-02-25 10:04:38 -06:00
|
|
|
impl<T: Hash<S> + Eq + Clone, S, H: Hasher<S> + Clone> Clone for HashSet<T, H> {
|
|
|
|
fn clone(&self) -> HashSet<T, H> {
|
2013-08-09 09:44:35 -05:00
|
|
|
HashSet {
|
|
|
|
map: self.map.clone()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-02-25 10:04:38 -06:00
|
|
|
impl<T: fmt::Show + Hash<S> + Eq, S, H: Hasher<S>> fmt::Show for HashSet<T, H> {
|
2014-02-12 13:41:34 -06:00
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
2014-02-19 12:07:49 -06:00
|
|
|
try!(write!(f.buf, r"\{"))
|
2014-02-12 13:41:34 -06:00
|
|
|
let mut first = true;
|
|
|
|
for x in self.iter() {
|
|
|
|
if first {
|
|
|
|
first = false;
|
|
|
|
} else {
|
2014-02-19 12:07:49 -06:00
|
|
|
try!(write!(f.buf, ", "));
|
2014-02-12 13:41:34 -06:00
|
|
|
}
|
2014-02-19 12:07:49 -06:00
|
|
|
try!(write!(f.buf, "{}", *x));
|
2014-02-12 13:41:34 -06:00
|
|
|
}
|
|
|
|
write!(f.buf, r"\}")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-02-25 10:04:38 -06:00
|
|
|
impl<T: Hash<S> + Eq, S, H: Hasher<S> + Default> FromIterator<T> for HashSet<T, H> {
|
|
|
|
fn from_iterator<Iter: Iterator<T>>(iter: &mut Iter) -> HashSet<T, H> {
|
2013-07-14 11:20:48 -05:00
|
|
|
let (lower, _) = iter.size_hint();
|
2014-03-06 20:07:52 -06:00
|
|
|
let mut set = HashSet::with_capacity_and_hasher(lower, Default::default());
|
2013-07-29 19:17:17 -05:00
|
|
|
set.extend(iter);
|
|
|
|
set
|
|
|
|
}
|
|
|
|
}
|
2013-07-14 11:20:48 -05:00
|
|
|
|
2014-02-25 10:04:38 -06:00
|
|
|
impl<T: Hash<S> + Eq, S, H: Hasher<S> + Default> Extendable<T> for HashSet<T, H> {
|
|
|
|
fn extend<Iter: Iterator<T>>(&mut self, iter: &mut Iter) {
|
2013-08-03 11:45:23 -05:00
|
|
|
for k in *iter {
|
2013-07-29 19:17:17 -05:00
|
|
|
self.insert(k);
|
2013-07-14 11:20:48 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2013-07-14 12:18:50 -05:00
|
|
|
|
2014-02-25 10:04:38 -06:00
|
|
|
impl<T: Hash<S> + Eq, S, H: Hasher<S> + Default> Default for HashSet<T, H> {
|
|
|
|
fn default() -> HashSet<T, H> {
|
|
|
|
HashSet {
|
|
|
|
map: Default::default(),
|
|
|
|
}
|
|
|
|
}
|
2013-09-09 21:28:05 -05:00
|
|
|
}
|
|
|
|
|
2013-08-03 14:34:00 -05:00
|
|
|
// `Repeat` is used to feed the filter closure an explicit capture
|
|
|
|
// of a reference to the other set
|
2013-07-15 20:55:52 -05:00
|
|
|
/// Set operations iterator
|
2014-02-25 10:04:38 -06:00
|
|
|
pub type SetAlgebraItems<'a, T, H> =
|
|
|
|
FilterMap<'static,(&'a HashSet<T, H>, &'a T), &'a T,
|
|
|
|
Zip<Repeat<&'a HashSet<T, H>>, SetItems<'a, T>>>;
|
2013-07-15 20:55:52 -05:00
|
|
|
|
2013-04-30 06:02:29 -05:00
|
|
|
#[cfg(test)]
|
2013-04-03 07:45:14 -05:00
|
|
|
mod test_map {
|
2014-02-19 21:29:58 -06:00
|
|
|
use super::{HashMap, HashSet};
|
|
|
|
use std::fmt;
|
2013-02-10 17:30:44 -06:00
|
|
|
|
2013-05-30 12:03:11 -05:00
|
|
|
#[test]
|
|
|
|
fn test_create_capacity_zero() {
|
|
|
|
let mut m = HashMap::with_capacity(0);
|
|
|
|
assert!(m.insert(1, 1));
|
|
|
|
}
|
|
|
|
|
2012-10-08 09:05:01 -05:00
|
|
|
#[test]
|
2013-04-15 10:08:52 -05:00
|
|
|
fn test_insert() {
|
2013-04-03 08:28:36 -05:00
|
|
|
let mut m = HashMap::new();
|
2013-04-03 07:45:14 -05:00
|
|
|
assert!(m.insert(1, 2));
|
|
|
|
assert!(m.insert(2, 4));
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(*m.get(&1), 2);
|
|
|
|
assert_eq!(*m.get(&2), 4);
|
2013-04-03 07:45:14 -05:00
|
|
|
}
|
2013-03-02 04:09:36 -06:00
|
|
|
|
2013-04-03 07:45:14 -05:00
|
|
|
#[test]
|
|
|
|
fn test_find_mut() {
|
2013-04-03 08:28:36 -05:00
|
|
|
let mut m = HashMap::new();
|
2013-04-03 07:45:14 -05:00
|
|
|
assert!(m.insert(1, 12));
|
|
|
|
assert!(m.insert(2, 8));
|
|
|
|
assert!(m.insert(5, 14));
|
|
|
|
let new = 100;
|
|
|
|
match m.find_mut(&5) {
|
2013-10-21 15:08:31 -05:00
|
|
|
None => fail!(), Some(x) => *x = new
|
2013-04-03 07:45:14 -05:00
|
|
|
}
|
|
|
|
assert_eq!(m.find(&5), Some(&new));
|
|
|
|
}
|
2013-03-24 18:07:36 -05:00
|
|
|
|
2013-04-03 07:45:14 -05:00
|
|
|
#[test]
|
2013-04-15 10:08:52 -05:00
|
|
|
fn test_insert_overwrite() {
|
2013-04-03 08:28:36 -05:00
|
|
|
let mut m = HashMap::new();
|
2013-04-03 07:45:14 -05:00
|
|
|
assert!(m.insert(1, 2));
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(*m.get(&1), 2);
|
2013-04-03 07:45:14 -05:00
|
|
|
assert!(!m.insert(1, 3));
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(*m.get(&1), 3);
|
2013-04-03 07:45:14 -05:00
|
|
|
}
|
2013-03-02 04:09:36 -06:00
|
|
|
|
2013-04-03 07:45:14 -05:00
|
|
|
#[test]
|
2013-04-15 10:08:52 -05:00
|
|
|
fn test_insert_conflicts() {
|
2013-08-01 03:11:25 -05:00
|
|
|
let mut m = HashMap::with_capacity(4);
|
2013-04-03 07:45:14 -05:00
|
|
|
assert!(m.insert(1, 2));
|
|
|
|
assert!(m.insert(5, 3));
|
|
|
|
assert!(m.insert(9, 4));
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(*m.get(&9), 4);
|
|
|
|
assert_eq!(*m.get(&5), 3);
|
|
|
|
assert_eq!(*m.get(&1), 2);
|
2013-04-03 07:45:14 -05:00
|
|
|
}
|
2013-03-02 04:09:36 -06:00
|
|
|
|
2013-04-03 07:45:14 -05:00
|
|
|
#[test]
|
2013-04-15 10:08:52 -05:00
|
|
|
fn test_conflict_remove() {
|
2013-08-01 03:11:25 -05:00
|
|
|
let mut m = HashMap::with_capacity(4);
|
2013-04-03 07:45:14 -05:00
|
|
|
assert!(m.insert(1, 2));
|
|
|
|
assert!(m.insert(5, 3));
|
|
|
|
assert!(m.insert(9, 4));
|
|
|
|
assert!(m.remove(&1));
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(*m.get(&9), 4);
|
|
|
|
assert_eq!(*m.get(&5), 3);
|
2013-04-03 07:45:14 -05:00
|
|
|
}
|
2013-03-02 04:09:36 -06:00
|
|
|
|
2013-04-03 07:45:14 -05:00
|
|
|
#[test]
|
2013-04-15 10:08:52 -05:00
|
|
|
fn test_is_empty() {
|
2013-08-01 03:11:25 -05:00
|
|
|
let mut m = HashMap::with_capacity(4);
|
2013-04-03 07:45:14 -05:00
|
|
|
assert!(m.insert(1, 2));
|
|
|
|
assert!(!m.is_empty());
|
|
|
|
assert!(m.remove(&1));
|
|
|
|
assert!(m.is_empty());
|
|
|
|
}
|
2013-03-02 04:09:36 -06:00
|
|
|
|
2013-04-03 07:45:14 -05:00
|
|
|
#[test]
|
2013-04-15 10:08:52 -05:00
|
|
|
fn test_pop() {
|
2013-04-03 08:28:36 -05:00
|
|
|
let mut m = HashMap::new();
|
2013-04-03 07:45:14 -05:00
|
|
|
m.insert(1, 2);
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(m.pop(&1), Some(2));
|
|
|
|
assert_eq!(m.pop(&1), None);
|
2013-04-03 07:45:14 -05:00
|
|
|
}
|
2013-03-02 04:09:36 -06:00
|
|
|
|
2013-04-03 07:45:14 -05:00
|
|
|
#[test]
|
2013-04-15 10:08:52 -05:00
|
|
|
fn test_swap() {
|
2013-04-03 08:28:36 -05:00
|
|
|
let mut m = HashMap::new();
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(m.swap(1, 2), None);
|
|
|
|
assert_eq!(m.swap(1, 3), Some(2));
|
|
|
|
assert_eq!(m.swap(1, 4), Some(3));
|
2013-04-03 07:45:14 -05:00
|
|
|
}
|
2013-03-02 04:09:36 -06:00
|
|
|
|
2013-04-03 07:45:14 -05:00
|
|
|
#[test]
|
2013-04-15 10:08:52 -05:00
|
|
|
fn test_find_or_insert() {
|
2013-08-08 13:38:10 -05:00
|
|
|
let mut m: HashMap<int,int> = HashMap::new();
|
2013-05-31 20:48:06 -05:00
|
|
|
assert_eq!(*m.find_or_insert(1, 2), 2);
|
|
|
|
assert_eq!(*m.find_or_insert(1, 3), 2);
|
2013-04-03 07:45:14 -05:00
|
|
|
}
|
2013-03-02 04:09:36 -06:00
|
|
|
|
2013-04-03 07:45:14 -05:00
|
|
|
#[test]
|
2013-04-15 10:08:52 -05:00
|
|
|
fn test_find_or_insert_with() {
|
2013-08-08 13:38:10 -05:00
|
|
|
let mut m: HashMap<int,int> = HashMap::new();
|
2013-05-31 20:48:06 -05:00
|
|
|
assert_eq!(*m.find_or_insert_with(1, |_| 2), 2);
|
|
|
|
assert_eq!(*m.find_or_insert_with(1, |_| 3), 2);
|
2013-04-03 07:45:14 -05:00
|
|
|
}
|
2013-03-02 04:09:36 -06:00
|
|
|
|
2013-05-31 20:50:20 -05:00
|
|
|
#[test]
|
|
|
|
fn test_insert_or_update_with() {
|
2013-08-08 13:38:10 -05:00
|
|
|
let mut m: HashMap<int,int> = HashMap::new();
|
2013-05-31 20:50:20 -05:00
|
|
|
assert_eq!(*m.insert_or_update_with(1, 2, |_,x| *x+=1), 2);
|
|
|
|
assert_eq!(*m.insert_or_update_with(1, 2, |_,x| *x+=1), 3);
|
|
|
|
}
|
|
|
|
|
2013-04-03 07:45:14 -05:00
|
|
|
#[test]
|
2013-08-07 21:21:36 -05:00
|
|
|
fn test_move_iter() {
|
2013-07-15 13:43:16 -05:00
|
|
|
let hm = {
|
|
|
|
let mut hm = HashMap::new();
|
|
|
|
|
|
|
|
hm.insert('a', 1);
|
|
|
|
hm.insert('b', 2);
|
|
|
|
|
|
|
|
hm
|
|
|
|
};
|
|
|
|
|
2013-08-07 21:21:36 -05:00
|
|
|
let v = hm.move_iter().collect::<~[(char, int)]>();
|
2013-07-15 13:43:16 -05:00
|
|
|
assert!([('a', 1), ('b', 2)] == v || [('b', 2), ('a', 1)] == v);
|
|
|
|
}
|
|
|
|
|
2013-04-03 07:45:14 -05:00
|
|
|
#[test]
|
2013-04-15 10:08:52 -05:00
|
|
|
fn test_iterate() {
|
2013-08-01 03:11:25 -05:00
|
|
|
let mut m = HashMap::with_capacity(4);
|
2013-08-03 11:45:23 -05:00
|
|
|
for i in range(0u, 32) {
|
2013-04-03 07:45:14 -05:00
|
|
|
assert!(m.insert(i, i*2));
|
2012-07-31 16:11:57 -05:00
|
|
|
}
|
2013-04-03 07:45:14 -05:00
|
|
|
let mut observed = 0;
|
2013-08-03 11:45:23 -05:00
|
|
|
for (k, v) in m.iter() {
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(*v, *k * 2);
|
2014-02-28 03:23:06 -06:00
|
|
|
observed |= 1 << *k;
|
2012-09-14 17:19:54 -05:00
|
|
|
}
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(observed, 0xFFFF_FFFF);
|
2013-04-03 07:45:14 -05:00
|
|
|
}
|
2012-12-10 11:00:52 -06:00
|
|
|
|
2013-12-31 13:09:18 -06:00
|
|
|
#[test]
|
|
|
|
fn test_keys() {
|
|
|
|
let vec = ~[(1, 'a'), (2, 'b'), (3, 'c')];
|
|
|
|
let map = vec.move_iter().collect::<HashMap<int, char>>();
|
|
|
|
let keys = map.keys().map(|&k| k).collect::<~[int]>();
|
|
|
|
assert_eq!(keys.len(), 3);
|
|
|
|
assert!(keys.contains(&1));
|
|
|
|
assert!(keys.contains(&2));
|
|
|
|
assert!(keys.contains(&3));
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_values() {
|
|
|
|
let vec = ~[(1, 'a'), (2, 'b'), (3, 'c')];
|
|
|
|
let map = vec.move_iter().collect::<HashMap<int, char>>();
|
|
|
|
let values = map.values().map(|&v| v).collect::<~[char]>();
|
|
|
|
assert_eq!(values.len(), 3);
|
|
|
|
assert!(values.contains(&'a'));
|
|
|
|
assert!(values.contains(&'b'));
|
|
|
|
assert!(values.contains(&'c'));
|
|
|
|
}
|
|
|
|
|
2013-04-03 07:45:14 -05:00
|
|
|
#[test]
|
2013-04-15 10:08:52 -05:00
|
|
|
fn test_find() {
|
2013-04-03 08:28:36 -05:00
|
|
|
let mut m = HashMap::new();
|
2013-04-03 07:45:14 -05:00
|
|
|
assert!(m.find(&1).is_none());
|
|
|
|
m.insert(1, 2);
|
|
|
|
match m.find(&1) {
|
2013-10-21 15:08:31 -05:00
|
|
|
None => fail!(),
|
2013-04-03 07:45:14 -05:00
|
|
|
Some(v) => assert!(*v == 2)
|
|
|
|
}
|
|
|
|
}
|
2012-12-10 11:00:52 -06:00
|
|
|
|
2013-04-03 07:45:14 -05:00
|
|
|
#[test]
|
2013-04-15 10:08:52 -05:00
|
|
|
fn test_eq() {
|
2013-04-03 08:28:36 -05:00
|
|
|
let mut m1 = HashMap::new();
|
2013-04-03 07:45:14 -05:00
|
|
|
m1.insert(1, 2);
|
|
|
|
m1.insert(2, 3);
|
|
|
|
m1.insert(3, 4);
|
2012-12-10 11:00:52 -06:00
|
|
|
|
2013-04-03 08:28:36 -05:00
|
|
|
let mut m2 = HashMap::new();
|
2013-04-03 07:45:14 -05:00
|
|
|
m2.insert(1, 2);
|
|
|
|
m2.insert(2, 3);
|
2012-12-10 11:00:52 -06:00
|
|
|
|
2013-04-03 07:45:14 -05:00
|
|
|
assert!(m1 != m2);
|
2012-12-10 11:00:52 -06:00
|
|
|
|
2013-04-03 07:45:14 -05:00
|
|
|
m2.insert(3, 4);
|
2012-12-30 12:35:03 -06:00
|
|
|
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(m1, m2);
|
2013-04-03 07:45:14 -05:00
|
|
|
}
|
2012-12-30 12:35:03 -06:00
|
|
|
|
2013-04-03 07:45:14 -05:00
|
|
|
#[test]
|
2013-04-15 10:08:52 -05:00
|
|
|
fn test_expand() {
|
2013-04-03 08:28:36 -05:00
|
|
|
let mut m = HashMap::new();
|
2012-12-30 12:35:03 -06:00
|
|
|
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(m.len(), 0);
|
2013-04-03 07:45:14 -05:00
|
|
|
assert!(m.is_empty());
|
2012-12-30 12:35:03 -06:00
|
|
|
|
2013-04-03 07:45:14 -05:00
|
|
|
let mut i = 0u;
|
|
|
|
let old_resize_at = m.resize_at;
|
|
|
|
while old_resize_at == m.resize_at {
|
|
|
|
m.insert(i, i);
|
|
|
|
i += 1;
|
2013-03-02 04:09:36 -06:00
|
|
|
}
|
2013-04-03 07:45:14 -05:00
|
|
|
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(m.len(), i);
|
2013-04-03 07:45:14 -05:00
|
|
|
assert!(!m.is_empty());
|
2012-12-30 12:35:03 -06:00
|
|
|
}
|
2013-06-11 05:33:30 -05:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_find_equiv() {
|
|
|
|
let mut m = HashMap::new();
|
|
|
|
|
|
|
|
let (foo, bar, baz) = (1,2,3);
|
|
|
|
m.insert(~"foo", foo);
|
|
|
|
m.insert(~"bar", bar);
|
|
|
|
m.insert(~"baz", baz);
|
|
|
|
|
|
|
|
|
|
|
|
assert_eq!(m.find_equiv(&("foo")), Some(&foo));
|
|
|
|
assert_eq!(m.find_equiv(&("bar")), Some(&bar));
|
|
|
|
assert_eq!(m.find_equiv(&("baz")), Some(&baz));
|
|
|
|
|
|
|
|
assert_eq!(m.find_equiv(&("qux")), None);
|
|
|
|
}
|
2013-07-14 10:26:03 -05:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_from_iter() {
|
|
|
|
let xs = ~[(1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6)];
|
2013-07-14 12:18:50 -05:00
|
|
|
|
2013-08-09 22:09:47 -05:00
|
|
|
let map: HashMap<int, int> = xs.iter().map(|&x| x).collect();
|
2013-07-14 10:26:03 -05:00
|
|
|
|
2013-08-03 11:45:23 -05:00
|
|
|
for &(k, v) in xs.iter() {
|
2013-07-14 10:26:03 -05:00
|
|
|
assert_eq!(map.find(&k), Some(&v));
|
|
|
|
}
|
|
|
|
}
|
2014-02-12 13:41:34 -06:00
|
|
|
|
|
|
|
struct ShowableStruct {
|
|
|
|
value: int,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl fmt::Show for ShowableStruct {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
|
|
write!(f.buf, r"s{}", self.value)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_show() {
|
|
|
|
let mut table: HashMap<int, ShowableStruct> = HashMap::new();
|
|
|
|
let empty: HashMap<int, ShowableStruct> = HashMap::new();
|
|
|
|
|
|
|
|
table.insert(3, ShowableStruct { value: 4 });
|
|
|
|
table.insert(1, ShowableStruct { value: 2 });
|
|
|
|
|
|
|
|
let table_str = format!("{}", table);
|
|
|
|
|
|
|
|
assert!(table_str == ~"{1: s2, 3: s4}" || table_str == ~"{3: s4, 1: s2}");
|
|
|
|
assert_eq!(format!("{}", empty), ~"{}");
|
|
|
|
}
|
2014-02-19 21:29:58 -06:00
|
|
|
|
|
|
|
struct StructWithToStrWithoutEqOrHash {
|
|
|
|
value: int
|
|
|
|
}
|
|
|
|
|
|
|
|
impl fmt::Show for StructWithToStrWithoutEqOrHash {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
|
|
write!(f.buf, "s{}", self.value)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_hashset() {
|
|
|
|
let mut set: HashSet<int> = HashSet::new();
|
|
|
|
let empty_set: HashSet<int> = HashSet::new();
|
|
|
|
|
|
|
|
set.insert(1);
|
|
|
|
set.insert(2);
|
|
|
|
|
|
|
|
let set_str = set.to_str();
|
|
|
|
|
|
|
|
assert!(set_str == ~"{1, 2}" || set_str == ~"{2, 1}");
|
|
|
|
assert_eq!(empty_set.to_str(), ~"{}");
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_hashmap() {
|
|
|
|
let mut table: HashMap<int, StructWithToStrWithoutEqOrHash> = HashMap::new();
|
|
|
|
let empty: HashMap<int, StructWithToStrWithoutEqOrHash> = HashMap::new();
|
|
|
|
|
|
|
|
table.insert(3, StructWithToStrWithoutEqOrHash { value: 4 });
|
|
|
|
table.insert(1, StructWithToStrWithoutEqOrHash { value: 2 });
|
|
|
|
|
|
|
|
let table_str = table.to_str();
|
|
|
|
|
|
|
|
assert!(table_str == ~"{1: s2, 3: s4}" || table_str == ~"{3: s4, 1: s2}");
|
|
|
|
assert_eq!(empty.to_str(), ~"{}");
|
|
|
|
}
|
2013-04-03 07:45:14 -05:00
|
|
|
}
|
2013-01-29 15:07:11 -06:00
|
|
|
|
2013-04-30 06:02:29 -05:00
|
|
|
#[cfg(test)]
|
2013-04-03 07:45:14 -05:00
|
|
|
mod test_set {
|
2014-02-19 21:29:58 -06:00
|
|
|
use super::HashSet;
|
2013-03-02 04:09:36 -06:00
|
|
|
|
2013-04-03 07:45:14 -05:00
|
|
|
#[test]
|
|
|
|
fn test_disjoint() {
|
2013-04-03 08:28:36 -05:00
|
|
|
let mut xs = HashSet::new();
|
|
|
|
let mut ys = HashSet::new();
|
2013-04-03 07:45:14 -05:00
|
|
|
assert!(xs.is_disjoint(&ys));
|
|
|
|
assert!(ys.is_disjoint(&xs));
|
|
|
|
assert!(xs.insert(5));
|
|
|
|
assert!(ys.insert(11));
|
|
|
|
assert!(xs.is_disjoint(&ys));
|
|
|
|
assert!(ys.is_disjoint(&xs));
|
|
|
|
assert!(xs.insert(7));
|
|
|
|
assert!(xs.insert(19));
|
|
|
|
assert!(xs.insert(4));
|
|
|
|
assert!(ys.insert(2));
|
|
|
|
assert!(ys.insert(-11));
|
|
|
|
assert!(xs.is_disjoint(&ys));
|
|
|
|
assert!(ys.is_disjoint(&xs));
|
|
|
|
assert!(ys.insert(7));
|
|
|
|
assert!(!xs.is_disjoint(&ys));
|
|
|
|
assert!(!ys.is_disjoint(&xs));
|
|
|
|
}
|
2013-03-02 04:09:36 -06:00
|
|
|
|
2013-04-03 07:45:14 -05:00
|
|
|
#[test]
|
|
|
|
fn test_subset_and_superset() {
|
2013-04-03 08:28:36 -05:00
|
|
|
let mut a = HashSet::new();
|
2013-04-03 07:45:14 -05:00
|
|
|
assert!(a.insert(0));
|
|
|
|
assert!(a.insert(5));
|
|
|
|
assert!(a.insert(11));
|
|
|
|
assert!(a.insert(7));
|
|
|
|
|
2013-04-03 08:28:36 -05:00
|
|
|
let mut b = HashSet::new();
|
2013-04-03 07:45:14 -05:00
|
|
|
assert!(b.insert(0));
|
|
|
|
assert!(b.insert(7));
|
|
|
|
assert!(b.insert(19));
|
|
|
|
assert!(b.insert(250));
|
|
|
|
assert!(b.insert(11));
|
|
|
|
assert!(b.insert(200));
|
|
|
|
|
|
|
|
assert!(!a.is_subset(&b));
|
|
|
|
assert!(!a.is_superset(&b));
|
|
|
|
assert!(!b.is_subset(&a));
|
|
|
|
assert!(!b.is_superset(&a));
|
|
|
|
|
|
|
|
assert!(b.insert(5));
|
|
|
|
|
|
|
|
assert!(a.is_subset(&b));
|
|
|
|
assert!(!a.is_superset(&b));
|
|
|
|
assert!(!b.is_subset(&a));
|
|
|
|
assert!(b.is_superset(&a));
|
|
|
|
}
|
2013-01-29 18:30:26 -06:00
|
|
|
|
2013-06-21 10:05:16 -05:00
|
|
|
#[test]
|
|
|
|
fn test_iterate() {
|
|
|
|
let mut a = HashSet::new();
|
2013-08-03 11:45:23 -05:00
|
|
|
for i in range(0u, 32) {
|
2013-06-21 10:05:16 -05:00
|
|
|
assert!(a.insert(i));
|
|
|
|
}
|
|
|
|
let mut observed = 0;
|
2013-08-03 11:45:23 -05:00
|
|
|
for k in a.iter() {
|
2014-02-28 03:23:06 -06:00
|
|
|
observed |= 1 << *k;
|
2013-06-21 10:05:16 -05:00
|
|
|
}
|
|
|
|
assert_eq!(observed, 0xFFFF_FFFF);
|
|
|
|
}
|
|
|
|
|
2013-04-03 07:45:14 -05:00
|
|
|
#[test]
|
|
|
|
fn test_intersection() {
|
2013-04-03 08:28:36 -05:00
|
|
|
let mut a = HashSet::new();
|
|
|
|
let mut b = HashSet::new();
|
2013-04-03 07:45:14 -05:00
|
|
|
|
|
|
|
assert!(a.insert(11));
|
|
|
|
assert!(a.insert(1));
|
|
|
|
assert!(a.insert(3));
|
|
|
|
assert!(a.insert(77));
|
|
|
|
assert!(a.insert(103));
|
|
|
|
assert!(a.insert(5));
|
|
|
|
assert!(a.insert(-5));
|
|
|
|
|
|
|
|
assert!(b.insert(2));
|
|
|
|
assert!(b.insert(11));
|
|
|
|
assert!(b.insert(77));
|
|
|
|
assert!(b.insert(-9));
|
|
|
|
assert!(b.insert(-42));
|
|
|
|
assert!(b.insert(5));
|
|
|
|
assert!(b.insert(3));
|
|
|
|
|
|
|
|
let mut i = 0;
|
|
|
|
let expected = [3, 5, 11, 77];
|
2013-11-23 04:18:51 -06:00
|
|
|
for x in a.intersection(&b) {
|
2013-06-28 11:08:32 -05:00
|
|
|
assert!(expected.contains(x));
|
2013-04-03 07:45:14 -05:00
|
|
|
i += 1
|
|
|
|
}
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(i, expected.len());
|
2013-04-03 07:45:14 -05:00
|
|
|
}
|
2013-03-02 04:09:36 -06:00
|
|
|
|
2013-04-03 07:45:14 -05:00
|
|
|
#[test]
|
|
|
|
fn test_difference() {
|
2013-04-03 08:28:36 -05:00
|
|
|
let mut a = HashSet::new();
|
|
|
|
let mut b = HashSet::new();
|
2013-04-03 07:45:14 -05:00
|
|
|
|
|
|
|
assert!(a.insert(1));
|
|
|
|
assert!(a.insert(3));
|
|
|
|
assert!(a.insert(5));
|
|
|
|
assert!(a.insert(9));
|
|
|
|
assert!(a.insert(11));
|
|
|
|
|
|
|
|
assert!(b.insert(3));
|
|
|
|
assert!(b.insert(9));
|
|
|
|
|
|
|
|
let mut i = 0;
|
|
|
|
let expected = [1, 5, 11];
|
2013-11-23 04:18:51 -06:00
|
|
|
for x in a.difference(&b) {
|
2013-06-28 11:08:32 -05:00
|
|
|
assert!(expected.contains(x));
|
2013-04-03 07:45:14 -05:00
|
|
|
i += 1
|
|
|
|
}
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(i, expected.len());
|
2013-04-03 07:45:14 -05:00
|
|
|
}
|
2013-03-02 04:09:36 -06:00
|
|
|
|
2013-04-03 07:45:14 -05:00
|
|
|
#[test]
|
|
|
|
fn test_symmetric_difference() {
|
2013-04-03 08:28:36 -05:00
|
|
|
let mut a = HashSet::new();
|
|
|
|
let mut b = HashSet::new();
|
2013-04-03 07:45:14 -05:00
|
|
|
|
|
|
|
assert!(a.insert(1));
|
|
|
|
assert!(a.insert(3));
|
|
|
|
assert!(a.insert(5));
|
|
|
|
assert!(a.insert(9));
|
|
|
|
assert!(a.insert(11));
|
|
|
|
|
|
|
|
assert!(b.insert(-2));
|
|
|
|
assert!(b.insert(3));
|
|
|
|
assert!(b.insert(9));
|
|
|
|
assert!(b.insert(14));
|
|
|
|
assert!(b.insert(22));
|
|
|
|
|
|
|
|
let mut i = 0;
|
|
|
|
let expected = [-2, 1, 5, 11, 14, 22];
|
2013-11-23 04:18:51 -06:00
|
|
|
for x in a.symmetric_difference(&b) {
|
2013-06-28 11:08:32 -05:00
|
|
|
assert!(expected.contains(x));
|
2013-04-03 07:45:14 -05:00
|
|
|
i += 1
|
|
|
|
}
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(i, expected.len());
|
2013-04-03 07:45:14 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_union() {
|
2013-04-03 08:28:36 -05:00
|
|
|
let mut a = HashSet::new();
|
|
|
|
let mut b = HashSet::new();
|
2013-04-03 07:45:14 -05:00
|
|
|
|
|
|
|
assert!(a.insert(1));
|
|
|
|
assert!(a.insert(3));
|
|
|
|
assert!(a.insert(5));
|
|
|
|
assert!(a.insert(9));
|
|
|
|
assert!(a.insert(11));
|
|
|
|
assert!(a.insert(16));
|
|
|
|
assert!(a.insert(19));
|
|
|
|
assert!(a.insert(24));
|
|
|
|
|
|
|
|
assert!(b.insert(-2));
|
|
|
|
assert!(b.insert(1));
|
|
|
|
assert!(b.insert(5));
|
|
|
|
assert!(b.insert(9));
|
|
|
|
assert!(b.insert(13));
|
|
|
|
assert!(b.insert(19));
|
|
|
|
|
|
|
|
let mut i = 0;
|
|
|
|
let expected = [-2, 1, 3, 5, 9, 11, 13, 16, 19, 24];
|
2013-11-23 04:18:51 -06:00
|
|
|
for x in a.union(&b) {
|
2013-06-28 11:08:32 -05:00
|
|
|
assert!(expected.contains(x));
|
2013-04-03 07:45:14 -05:00
|
|
|
i += 1
|
|
|
|
}
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(i, expected.len());
|
2013-01-29 20:58:47 -06:00
|
|
|
}
|
2013-07-14 11:20:48 -05:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_from_iter() {
|
|
|
|
let xs = ~[1, 2, 3, 4, 5, 6, 7, 8, 9];
|
2013-07-14 12:18:50 -05:00
|
|
|
|
2013-08-09 22:09:47 -05:00
|
|
|
let set: HashSet<int> = xs.iter().map(|&x| x).collect();
|
2013-07-14 11:20:48 -05:00
|
|
|
|
2013-08-03 11:45:23 -05:00
|
|
|
for x in xs.iter() {
|
2013-07-14 11:20:48 -05:00
|
|
|
assert!(set.contains(x));
|
|
|
|
}
|
|
|
|
}
|
2013-07-15 13:43:16 -05:00
|
|
|
|
|
|
|
#[test]
|
2013-08-07 21:21:36 -05:00
|
|
|
fn test_move_iter() {
|
2013-07-15 13:43:16 -05:00
|
|
|
let hs = {
|
|
|
|
let mut hs = HashSet::new();
|
|
|
|
|
|
|
|
hs.insert('a');
|
|
|
|
hs.insert('b');
|
|
|
|
|
|
|
|
hs
|
|
|
|
};
|
|
|
|
|
2013-08-07 21:21:36 -05:00
|
|
|
let v = hs.move_iter().collect::<~[char]>();
|
2013-07-15 13:43:16 -05:00
|
|
|
assert!(['a', 'b'] == v || ['b', 'a'] == v);
|
|
|
|
}
|
2013-08-09 09:44:35 -05:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_eq() {
|
|
|
|
let mut s1 = HashSet::new();
|
|
|
|
s1.insert(1);
|
|
|
|
s1.insert(2);
|
|
|
|
s1.insert(3);
|
|
|
|
|
|
|
|
let mut s2 = HashSet::new();
|
|
|
|
s2.insert(1);
|
|
|
|
s2.insert(2);
|
|
|
|
|
|
|
|
assert!(s1 != s2);
|
|
|
|
|
|
|
|
s2.insert(3);
|
|
|
|
|
|
|
|
assert_eq!(s1, s2);
|
|
|
|
}
|
2014-02-12 13:41:34 -06:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_show() {
|
|
|
|
let mut set: HashSet<int> = HashSet::new();
|
|
|
|
let empty: HashSet<int> = HashSet::new();
|
|
|
|
|
|
|
|
set.insert(1);
|
|
|
|
set.insert(2);
|
|
|
|
|
|
|
|
let set_str = format!("{}", set);
|
|
|
|
|
|
|
|
assert!(set_str == ~"{1, 2}" || set_str == ~"{2, 1}");
|
|
|
|
assert_eq!(format!("{}", empty), ~"{}");
|
|
|
|
}
|
2013-01-29 15:07:11 -06:00
|
|
|
}
|