1
Fork 0

collections: allow HashMap to work with generic hashers

This commit is contained in:
Erick Tryzelaar 2014-02-25 08:04:38 -08:00
parent f01a9a8d02
commit 72b5e30f6c
6 changed files with 181 additions and 110 deletions

View file

@ -55,7 +55,8 @@
use std::cmp::max; use std::cmp::max;
use std::default::Default; use std::default::Default;
use std::fmt; use std::fmt;
use std::hash::{Hash, Hasher, sip}; use std::hash::{Hash, Hasher};
use std::hash::sip::{SipState, SipHasher};
use std::iter::{FilterMap, Chain, Repeat, Zip}; use std::iter::{FilterMap, Chain, Repeat, Zip};
use std::iter; use std::iter;
use std::mem::replace; use std::mem::replace;
@ -78,10 +79,10 @@ struct Bucket<K,V> {
/// hash function for internal state. This means that the order of all hash maps /// hash function for internal state. This means that the order of all hash maps
/// is randomized by keying each hash map randomly on creation. /// is randomized by keying each hash map randomly on creation.
/// ///
/// It is required that the keys implement the `Eq` and `Hash` traits. /// It is required that the keys implement the `Eq` and `Hash` traits, although
pub struct HashMap<K,V> { /// this can frequently be achieved by using `#[deriving(Eq, Hash)]`.
priv k0: u64, pub struct HashMap<K, V, H = SipHasher> {
priv k1: u64, priv hasher: H,
priv resize_at: uint, priv resize_at: uint,
priv size: uint, priv size: uint,
priv buckets: Vec<Option<Bucket<K, V>>> priv buckets: Vec<Option<Bucket<K, V>>>
@ -98,7 +99,7 @@ fn resize_at(capacity: uint) -> uint {
(capacity * 3) / 4 (capacity * 3) / 4
} }
impl<K:Hash + Eq, V> HashMap<K, V> { impl<K: Hash<S> + Eq, V, S, H: Hasher<S>> HashMap<K, V, H> {
#[inline] #[inline]
fn to_bucket(&self, h: uint) -> uint { fn to_bucket(&self, h: uint) -> uint {
// A good hash function with entropy spread over all of the // A good hash function with entropy spread over all of the
@ -127,14 +128,13 @@ impl<K:Hash + Eq, V> HashMap<K, V> {
#[inline] #[inline]
fn bucket_for_key(&self, k: &K) -> SearchResult { fn bucket_for_key(&self, k: &K) -> SearchResult {
let hash = sip::hash_with_keys(self.k0, self.k1, k) as uint; let hash = self.hasher.hash(k) as uint;
self.bucket_for_key_with_hash(hash, k) self.bucket_for_key_with_hash(hash, k)
} }
#[inline] #[inline]
fn bucket_for_key_equiv<Q:Hash + Equiv<K>>(&self, k: &Q) fn bucket_for_key_equiv<Q:Hash<S> + Equiv<K>>(&self, k: &Q) -> SearchResult {
-> SearchResult { let hash = self.hasher.hash(k) as uint;
let hash = sip::hash_with_keys(self.k0, self.k1, k) as uint;
self.bucket_for_key_with_hash_equiv(hash, k) self.bucket_for_key_with_hash_equiv(hash, k)
} }
@ -285,12 +285,12 @@ impl<K:Hash + Eq, V> HashMap<K, V> {
} }
} }
impl<K:Hash + Eq,V> Container for HashMap<K, V> { impl<K: Hash<S> + Eq, V, S, H: Hasher<S>> Container for HashMap<K, V, H> {
/// Return the number of elements in the map /// Return the number of elements in the map
fn len(&self) -> uint { self.size } fn len(&self) -> uint { self.size }
} }
impl<K:Hash + Eq,V> Mutable for HashMap<K, V> { impl<K: Hash<S> + Eq, V, S, H: Hasher<S>> Mutable for HashMap<K, V, H> {
/// Clear the map, removing all key-value pairs. /// Clear the map, removing all key-value pairs.
fn clear(&mut self) { fn clear(&mut self) {
for bkt in self.buckets.as_mut_slice().mut_iter() { for bkt in self.buckets.as_mut_slice().mut_iter() {
@ -300,7 +300,7 @@ impl<K:Hash + Eq,V> Mutable for HashMap<K, V> {
} }
} }
impl<K:Hash + Eq,V> Map<K, V> for HashMap<K, V> { impl<K: Hash<S> + Eq, V, S, H: Hasher<S>> Map<K, V> for HashMap<K, V, H> {
/// Return a reference to the value corresponding to the key /// Return a reference to the value corresponding to the key
fn find<'a>(&'a self, k: &K) -> Option<&'a V> { fn find<'a>(&'a self, k: &K) -> Option<&'a V> {
match self.bucket_for_key(k) { match self.bucket_for_key(k) {
@ -310,7 +310,7 @@ impl<K:Hash + Eq,V> Map<K, V> for HashMap<K, V> {
} }
} }
impl<K:Hash + Eq,V> MutableMap<K, V> for HashMap<K, V> { impl<K: Hash<S> + Eq, V, S, H: Hasher<S>> MutableMap<K, V> for HashMap<K, V, H> {
/// Return a mutable reference to the value corresponding to the key /// Return a mutable reference to the value corresponding to the key
fn find_mut<'a>(&'a mut self, k: &K) -> Option<&'a mut V> { fn find_mut<'a>(&'a mut self, k: &K) -> Option<&'a mut V> {
let idx = match self.bucket_for_key(k) { let idx = match self.bucket_for_key(k) {
@ -335,21 +335,21 @@ impl<K:Hash + Eq,V> MutableMap<K, V> for HashMap<K, V> {
self.expand(); self.expand();
} }
let hash = sip::hash_with_keys(self.k0, self.k1, &k) as uint; let hash = self.hasher.hash(&k) as uint;
self.insert_internal(hash, k, v) self.insert_internal(hash, k, v)
} }
/// Removes a key from the map, returning the value at the key if the key /// Removes a key from the map, returning the value at the key if the key
/// was previously in the map. /// was previously in the map.
fn pop(&mut self, k: &K) -> Option<V> { fn pop(&mut self, k: &K) -> Option<V> {
let hash = sip::hash_with_keys(self.k0, self.k1, k) as uint; let hash = self.hasher.hash(k) as uint;
self.pop_internal(hash, k) self.pop_internal(hash, k)
} }
} }
impl<K: Hash + Eq, V> HashMap<K, V> { impl<K: Hash + Eq, V> HashMap<K, V> {
/// Create an empty HashMap /// Create an empty HashMap
pub fn new() -> HashMap<K, V> { pub fn new() -> HashMap<K, V, SipHasher> {
HashMap::with_capacity(INITIAL_CAPACITY) HashMap::with_capacity(INITIAL_CAPACITY)
} }
@ -357,20 +357,27 @@ impl<K: Hash + Eq, V> HashMap<K, V> {
/// elements in the hash table. /// elements in the hash table.
pub fn with_capacity(capacity: uint) -> HashMap<K, V> { pub fn with_capacity(capacity: uint) -> HashMap<K, V> {
let mut r = rand::task_rng(); let mut r = rand::task_rng();
HashMap::with_capacity_and_keys(r.gen(), r.gen(), capacity) let hasher = SipHasher::new_with_keys(r.gen(), r.gen());
HashMap::with_capacity_and_hasher(hasher, capacity)
}
}
impl<K: Hash<S> + Eq, V, S, H: Hasher<S>> HashMap<K, V, H> {
pub fn with_hasher(hasher: H) -> HashMap<K, V, H> {
HashMap::with_capacity_and_hasher(hasher, INITIAL_CAPACITY)
} }
/// Create an empty HashMap with space for at least `capacity` /// Create an empty HashMap with space for at least `capacity`
/// elements, using `k0` and `k1` as the keys. /// elements, using `hasher` to hash the keys.
/// ///
/// Warning: `k0` and `k1` are normally randomly generated, and /// Warning: `hasher` is normally randomly generated, and
/// are designed to allow HashMaps to be resistant to attacks that /// is designed to allow HashMaps to be resistant to attacks that
/// cause many collisions and very poor performance. Setting them /// cause many collisions and very poor performance. Setting it
/// manually using this function can expose a DoS attack vector. /// 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> { pub fn with_capacity_and_hasher(hasher: H, capacity: uint) -> HashMap<K, V, H> {
let cap = max(INITIAL_CAPACITY, capacity); let cap = max(INITIAL_CAPACITY, capacity);
HashMap { HashMap {
k0: k0, k1: k1, hasher: hasher,
resize_at: resize_at(cap), resize_at: resize_at(cap),
size: 0, size: 0,
buckets: Vec::from_fn(cap, |_| None) buckets: Vec::from_fn(cap, |_| None)
@ -442,7 +449,7 @@ impl<K: Hash + Eq, V> HashMap<K, V> {
self.expand(); self.expand();
} }
let hash = sip::hash_with_keys(self.k0, self.k1, &k) as uint; let hash = self.hasher.hash(&k) as uint;
let idx = match self.bucket_for_key_with_hash(hash, &k) { let idx = match self.bucket_for_key_with_hash(hash, &k) {
TableFull => fail!("Internal logic error"), TableFull => fail!("Internal logic error"),
FoundEntry(idx) => { found(&k, self.mut_value_for_bucket(idx), a); idx } FoundEntry(idx) => { found(&k, self.mut_value_for_bucket(idx), a); idx }
@ -502,7 +509,7 @@ impl<K: Hash + Eq, V> HashMap<K, V> {
/// Return true if the map contains a value for the specified key, /// Return true if the map contains a value for the specified key,
/// using equivalence /// using equivalence
pub fn contains_key_equiv<Q:Hash + Equiv<K>>(&self, key: &Q) -> bool { pub fn contains_key_equiv<Q:Hash<S> + Equiv<K>>(&self, key: &Q) -> bool {
match self.bucket_for_key_equiv(key) { match self.bucket_for_key_equiv(key) {
FoundEntry(_) => {true} FoundEntry(_) => {true}
TableFull | FoundHole(_) => {false} TableFull | FoundHole(_) => {false}
@ -511,8 +518,7 @@ impl<K: Hash + Eq, V> HashMap<K, V> {
/// Return the value corresponding to the key in the map, using /// Return the value corresponding to the key in the map, using
/// equivalence /// equivalence
pub fn find_equiv<'a, Q:Hash + Equiv<K>>(&'a self, k: &Q) pub fn find_equiv<'a, Q:Hash<S> + Equiv<K>>(&'a self, k: &Q) -> Option<&'a V> {
-> Option<&'a V> {
match self.bucket_for_key_equiv(k) { match self.bucket_for_key_equiv(k) {
FoundEntry(idx) => Some(self.value_for_bucket(idx)), FoundEntry(idx) => Some(self.value_for_bucket(idx)),
TableFull | FoundHole(_) => None, TableFull | FoundHole(_) => None,
@ -552,7 +558,7 @@ impl<K: Hash + Eq, V> HashMap<K, V> {
} }
} }
impl<K: Hash + Eq, V: Clone> HashMap<K, V> { impl<K: Hash<S> + Eq, V: Clone, S, H: Hasher<S>> HashMap<K, V, H> {
/// Like `find`, but returns a copy of the value. /// Like `find`, but returns a copy of the value.
pub fn find_copy(&self, k: &K) -> Option<V> { pub fn find_copy(&self, k: &K) -> Option<V> {
self.find(k).map(|v| (*v).clone()) self.find(k).map(|v| (*v).clone())
@ -564,8 +570,8 @@ impl<K: Hash + Eq, V: Clone> HashMap<K, V> {
} }
} }
impl<K:Hash + Eq,V:Eq> Eq for HashMap<K, V> { impl<K: Hash<S> + Eq, V: Eq, S, H: Hasher<S>> Eq for HashMap<K, V, H> {
fn eq(&self, other: &HashMap<K, V>) -> bool { fn eq(&self, other: &HashMap<K, V, H>) -> bool {
if self.len() != other.len() { return false; } if self.len() != other.len() { return false; }
self.iter().all(|(key, value)| { self.iter().all(|(key, value)| {
@ -576,12 +582,12 @@ impl<K:Hash + Eq,V:Eq> Eq for HashMap<K, V> {
}) })
} }
fn ne(&self, other: &HashMap<K, V>) -> bool { !self.eq(other) } fn ne(&self, other: &HashMap<K, V, H>) -> bool { !self.eq(other) }
} }
impl<K:Hash + Eq + Clone,V:Clone> Clone for HashMap<K,V> { 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> { fn clone(&self) -> HashMap<K, V, H> {
let mut new_map = HashMap::with_capacity(self.len()); let mut new_map = HashMap::with_capacity_and_hasher(self.hasher.clone(), self.len());
for (key, value) in self.iter() { for (key, value) in self.iter() {
new_map.insert((*key).clone(), (*value).clone()); new_map.insert((*key).clone(), (*value).clone());
} }
@ -589,7 +595,7 @@ impl<K:Hash + Eq + Clone,V:Clone> Clone for HashMap<K,V> {
} }
} }
impl<A: fmt::Show + Hash + Eq, B: fmt::Show> fmt::Show for HashMap<A, B> { impl<K: fmt::Show + Hash<S> + Eq, V: fmt::Show, S, H: Hasher<S>> fmt::Show for HashMap<K, V, H> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
try!(write!(f.buf, r"\{")) try!(write!(f.buf, r"\{"))
let mut first = true; let mut first = true;
@ -705,16 +711,16 @@ impl<K> Iterator<K> for SetMoveItems<K> {
} }
} }
impl<K: Eq + Hash, V> FromIterator<(K, V)> for HashMap<K, V> { 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> { fn from_iterator<T: Iterator<(K, V)>>(iter: &mut T) -> HashMap<K, V, H> {
let (lower, _) = iter.size_hint(); let (lower, _) = iter.size_hint();
let mut map = HashMap::with_capacity(lower); let mut map = HashMap::with_capacity_and_hasher(Default::default(), lower);
map.extend(iter); map.extend(iter);
map map
} }
} }
impl<K: Eq + Hash, V> Extendable<(K, V)> for HashMap<K, V> { impl<K: Hash<S> + Eq, V, S, H: Hasher<S> + Default> Extendable<(K, V)> for HashMap<K, V, H> {
fn extend<T: Iterator<(K, V)>>(&mut self, iter: &mut T) { fn extend<T: Iterator<(K, V)>>(&mut self, iter: &mut T) {
for (k, v) in *iter { for (k, v) in *iter {
self.insert(k, v); self.insert(k, v);
@ -722,54 +728,56 @@ impl<K: Eq + Hash, V> Extendable<(K, V)> for HashMap<K, V> {
} }
} }
impl<K: Eq + Hash, V> Default for HashMap<K, V> { impl<K: Hash<S> + Eq, V, S, H: Hasher<S> + Default> Default for HashMap<K, V, H> {
fn default() -> HashMap<K, V> { HashMap::new() } fn default() -> HashMap<K, V, H> {
HashMap::with_capacity_and_hasher(Default::default(), INITIAL_CAPACITY)
}
} }
/// An implementation of a hash set using the underlying representation of a /// An implementation of a hash set using the underlying representation of a
/// HashMap where the value is (). As with the `HashMap` type, a `HashSet` /// HashMap where the value is (). As with the `HashMap` type, a `HashSet`
/// requires that the elements implement the `Eq` and `Hash` traits. /// requires that the elements implement the `Eq` and `Hash` traits.
pub struct HashSet<T> { pub struct HashSet<T, H = SipHasher> {
priv map: HashMap<T, ()> priv map: HashMap<T, (), H>
} }
impl<T:Hash + Eq> Eq for HashSet<T> { impl<T: Hash<S> + Eq, S, H: Hasher<S>> Eq for HashSet<T, H> {
fn eq(&self, other: &HashSet<T>) -> bool { self.map == other.map } fn eq(&self, other: &HashSet<T, H>) -> bool { self.map == other.map }
fn ne(&self, other: &HashSet<T>) -> bool { self.map != other.map } fn ne(&self, other: &HashSet<T, H>) -> bool { self.map != other.map }
} }
impl<T:Hash + Eq> Container for HashSet<T> { impl<T: Hash<S> + Eq, S, H: Hasher<S>> Container for HashSet<T, H> {
/// Return the number of elements in the set /// Return the number of elements in the set
fn len(&self) -> uint { self.map.len() } fn len(&self) -> uint { self.map.len() }
} }
impl<T:Hash + Eq> Mutable for HashSet<T> { impl<T: Hash<S> + Eq, S, H: Hasher<S>> Mutable for HashSet<T, H> {
/// Clear the set, removing all values. /// Clear the set, removing all values.
fn clear(&mut self) { self.map.clear() } fn clear(&mut self) { self.map.clear() }
} }
impl<T:Hash + Eq> Set<T> for HashSet<T> { impl<T: Hash<S> + Eq, S, H: Hasher<S>> Set<T> for HashSet<T, H> {
/// Return true if the set contains a value /// Return true if the set contains a value
fn contains(&self, value: &T) -> bool { self.map.contains_key(value) } fn contains(&self, value: &T) -> bool { self.map.contains_key(value) }
/// Return true if the set has no elements in common with `other`. /// Return true if the set has no elements in common with `other`.
/// This is equivalent to checking for an empty intersection. /// This is equivalent to checking for an empty intersection.
fn is_disjoint(&self, other: &HashSet<T>) -> bool { fn is_disjoint(&self, other: &HashSet<T, H>) -> bool {
self.iter().all(|v| !other.contains(v)) self.iter().all(|v| !other.contains(v))
} }
/// Return true if the set is a subset of another /// Return true if the set is a subset of another
fn is_subset(&self, other: &HashSet<T>) -> bool { fn is_subset(&self, other: &HashSet<T, H>) -> bool {
self.iter().all(|v| other.contains(v)) self.iter().all(|v| other.contains(v))
} }
/// Return true if the set is a superset of another /// Return true if the set is a superset of another
fn is_superset(&self, other: &HashSet<T>) -> bool { fn is_superset(&self, other: &HashSet<T, H>) -> bool {
other.is_subset(self) other.is_subset(self)
} }
} }
impl<T:Hash + Eq> MutableSet<T> for HashSet<T> { impl<T: Hash<S> + Eq, S, H: Hasher<S>> MutableSet<T> for HashSet<T, H> {
/// Add a value to the set. Return true if the value was not already /// Add a value to the set. Return true if the value was not already
/// present in the set. /// present in the set.
fn insert(&mut self, value: T) -> bool { self.map.insert(value, ()) } fn insert(&mut self, value: T) -> bool { self.map.insert(value, ()) }
@ -779,27 +787,35 @@ impl<T:Hash + Eq> MutableSet<T> for HashSet<T> {
fn remove(&mut self, value: &T) -> bool { self.map.remove(value) } fn remove(&mut self, value: &T) -> bool { self.map.remove(value) }
} }
impl<T:Hash + Eq> HashSet<T> { impl<T: Hash<SipState> + Eq> HashSet<T, SipHasher> {
/// Create an empty HashSet /// Create an empty HashSet
pub fn new() -> HashSet<T> { pub fn new() -> HashSet<T, SipHasher> {
HashSet::with_capacity(INITIAL_CAPACITY) HashSet::with_capacity(INITIAL_CAPACITY)
} }
/// Create an empty HashSet with space for at least `n` elements in /// Create an empty HashSet with space for at least `n` elements in
/// the hash table. /// the hash table.
pub fn with_capacity(capacity: uint) -> HashSet<T> { pub fn with_capacity(capacity: uint) -> HashSet<T, SipHasher> {
HashSet { map: HashMap::with_capacity(capacity) } HashSet { map: HashMap::with_capacity(capacity) }
} }
}
impl<T: Hash<S> + Eq, S, H: Hasher<S>> HashSet<T, H> {
pub fn with_hasher(hasher: H) -> HashSet<T, H> {
HashSet::with_capacity_and_hasher(hasher, INITIAL_CAPACITY)
}
/// Create an empty HashSet with space for at least `capacity` /// Create an empty HashSet with space for at least `capacity`
/// elements in the hash table, using `k0` and `k1` as the keys. /// elements in the hash table, using `k0` and `k1` as the keys.
/// ///
/// Warning: `k0` and `k1` are normally randomly generated, and /// Warning: `hasher` is normally randomly generated, and
/// are designed to allow HashSets to be resistant to attacks that /// are designed to allow HashSets to be resistant to attacks that
/// cause many collisions and very poor performance. Setting them /// cause many collisions and very poor performance. Setting them
/// manually using this function can expose a DoS attack vector. /// manually using this function can expose a DoS attack vector.
pub fn with_capacity_and_keys(k0: u64, k1: u64, capacity: uint) -> HashSet<T> { pub fn with_capacity_and_hasher(hasher: H, capacity: uint) -> HashSet<T, H> {
HashSet { map: HashMap::with_capacity_and_keys(k0, k1, capacity) } HashSet {
map: HashMap::with_capacity_and_hasher(hasher, capacity)
}
} }
/// Reserve space for at least `n` elements in the hash table. /// Reserve space for at least `n` elements in the hash table.
@ -809,7 +825,7 @@ impl<T:Hash + Eq> HashSet<T> {
/// Returns true if the hash set contains a value equivalent to the /// Returns true if the hash set contains a value equivalent to the
/// given query value. /// given query value.
pub fn contains_equiv<Q:Hash + Equiv<T>>(&self, value: &Q) -> bool { pub fn contains_equiv<Q: Hash<S> + Equiv<T>>(&self, value: &Q) -> bool {
self.map.contains_key_equiv(value) self.map.contains_key_equiv(value)
} }
@ -827,7 +843,7 @@ impl<T:Hash + Eq> HashSet<T> {
} }
/// Visit the values representing the difference /// Visit the values representing the difference
pub fn difference<'a>(&'a self, other: &'a HashSet<T>) -> SetAlgebraItems<'a, T> { pub fn difference<'a>(&'a self, other: &'a HashSet<T, H>) -> SetAlgebraItems<'a, T, H> {
Repeat::new(other) Repeat::new(other)
.zip(self.iter()) .zip(self.iter())
.filter_map(|(other, elt)| { .filter_map(|(other, elt)| {
@ -836,14 +852,14 @@ impl<T:Hash + Eq> HashSet<T> {
} }
/// Visit the values representing the symmetric difference /// Visit the values representing the symmetric difference
pub fn symmetric_difference<'a>(&'a self, other: &'a HashSet<T>) pub fn symmetric_difference<'a>(&'a self, other: &'a HashSet<T, H>)
-> Chain<SetAlgebraItems<'a, T>, SetAlgebraItems<'a, T>> { -> Chain<SetAlgebraItems<'a, T, H>, SetAlgebraItems<'a, T, H>> {
self.difference(other).chain(other.difference(self)) self.difference(other).chain(other.difference(self))
} }
/// Visit the values representing the intersection /// Visit the values representing the intersection
pub fn intersection<'a>(&'a self, other: &'a HashSet<T>) pub fn intersection<'a>(&'a self, other: &'a HashSet<T, H>)
-> SetAlgebraItems<'a, T> { -> SetAlgebraItems<'a, T, H> {
Repeat::new(other) Repeat::new(other)
.zip(self.iter()) .zip(self.iter())
.filter_map(|(other, elt)| { .filter_map(|(other, elt)| {
@ -852,22 +868,22 @@ impl<T:Hash + Eq> HashSet<T> {
} }
/// Visit the values representing the union /// Visit the values representing the union
pub fn union<'a>(&'a self, other: &'a HashSet<T>) pub fn union<'a>(&'a self, other: &'a HashSet<T, H>)
-> Chain<SetItems<'a, T>, SetAlgebraItems<'a, T>> { -> Chain<SetItems<'a, T>, SetAlgebraItems<'a, T, H>> {
self.iter().chain(other.difference(self)) self.iter().chain(other.difference(self))
} }
} }
impl<T:Hash + Eq + Clone> Clone for HashSet<T> { impl<T: Hash<S> + Eq + Clone, S, H: Hasher<S> + Clone> Clone for HashSet<T, H> {
fn clone(&self) -> HashSet<T> { fn clone(&self) -> HashSet<T, H> {
HashSet { HashSet {
map: self.map.clone() map: self.map.clone()
} }
} }
} }
impl<A: fmt::Show + Hash + Eq> fmt::Show for HashSet<A> { impl<T: fmt::Show + Hash<S> + Eq, S, H: Hasher<S>> fmt::Show for HashSet<T, H> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
try!(write!(f.buf, r"\{")) try!(write!(f.buf, r"\{"))
let mut first = true; let mut first = true;
@ -883,33 +899,37 @@ impl<A: fmt::Show + Hash + Eq> fmt::Show for HashSet<A> {
} }
} }
impl<K: Eq + Hash> FromIterator<K> for HashSet<K> { impl<T: Hash<S> + Eq, S, H: Hasher<S> + Default> FromIterator<T> for HashSet<T, H> {
fn from_iterator<T: Iterator<K>>(iter: &mut T) -> HashSet<K> { fn from_iterator<Iter: Iterator<T>>(iter: &mut Iter) -> HashSet<T, H> {
let (lower, _) = iter.size_hint(); let (lower, _) = iter.size_hint();
let mut set = HashSet::with_capacity(lower); let mut set = HashSet::with_capacity_and_hasher(Default::default(), lower);
set.extend(iter); set.extend(iter);
set set
} }
} }
impl<K: Eq + Hash> Extendable<K> for HashSet<K> { impl<T: Hash<S> + Eq, S, H: Hasher<S> + Default> Extendable<T> for HashSet<T, H> {
fn extend<T: Iterator<K>>(&mut self, iter: &mut T) { fn extend<Iter: Iterator<T>>(&mut self, iter: &mut Iter) {
for k in *iter { for k in *iter {
self.insert(k); self.insert(k);
} }
} }
} }
impl<K: Eq + Hash> Default for HashSet<K> { impl<T: Hash<S> + Eq, S, H: Hasher<S> + Default> Default for HashSet<T, H> {
fn default() -> HashSet<K> { HashSet::new() } fn default() -> HashSet<T, H> {
HashSet {
map: Default::default(),
}
}
} }
// `Repeat` is used to feed the filter closure an explicit capture // `Repeat` is used to feed the filter closure an explicit capture
// of a reference to the other set // of a reference to the other set
/// Set operations iterator /// Set operations iterator
pub type SetAlgebraItems<'a, T> = pub type SetAlgebraItems<'a, T, H> =
FilterMap<'static,(&'a HashSet<T>, &'a T), &'a T, FilterMap<'static,(&'a HashSet<T, H>, &'a T), &'a T,
Zip<Repeat<&'a HashSet<T>>,SetItems<'a,T>>>; Zip<Repeat<&'a HashSet<T, H>>, SetItems<'a, T>>>;
#[cfg(test)] #[cfg(test)]
mod test_map { mod test_map {

View file

@ -17,7 +17,11 @@
#[crate_type = "dylib"]; #[crate_type = "dylib"];
#[license = "MIT/ASL2"]; #[license = "MIT/ASL2"];
#[feature(macro_rules, managed_boxes)]; #[feature(macro_rules, managed_boxes, default_type_params)];
// NOTE remove the following two attributes after the next snapshot.
#[allow(unrecognized_lint)];
#[allow(default_type_param_usage)];
#[cfg(test)] extern crate test; #[cfg(test)] extern crate test;

View file

@ -4926,7 +4926,7 @@ pub fn trait_method_of_method(tcx: ctxt,
/// Creates a hash of the type `t` which will be the same no matter what crate /// Creates a hash of the type `t` which will be the same no matter what crate
/// context it's calculated within. This is used by the `type_id` intrinsic. /// context it's calculated within. This is used by the `type_id` intrinsic.
pub fn hash_crate_independent(tcx: ctxt, t: t, local_hash: ~str) -> u64 { pub fn hash_crate_independent(tcx: ctxt, t: t, local_hash: ~str) -> u64 {
let mut state = sip::SipState::new(0, 0); let mut state = sip::SipState::new();
macro_rules! byte( ($b:expr) => { ($b as u8).hash(&mut state) } ); macro_rules! byte( ($b:expr) => { ($b as u8).hash(&mut state) } );
macro_rules! hash( ($e:expr) => { $e.hash(&mut state) } ); macro_rules! hash( ($e:expr) => { $e.hash(&mut state) } );

View file

@ -11,7 +11,8 @@
//! Implementations of serialization for structures found in libcollections //! Implementations of serialization for structures found in libcollections
use std::uint; use std::uint;
use std::hash::Hash; use std::default::Default;
use std::hash::{Hash, Hasher};
use {Decodable, Encodable, Decoder, Encoder}; use {Decodable, Encodable, Decoder, Encoder};
use collections::{DList, RingBuf, TreeMap, TreeSet, Deque, HashMap, HashSet, use collections::{DList, RingBuf, TreeMap, TreeSet, Deque, HashMap, HashSet,
@ -164,9 +165,11 @@ impl<
impl< impl<
E: Encoder, E: Encoder,
K: Encodable<E> + Hash + Eq, K: Encodable<E> + Hash<S> + Eq,
V: Encodable<E> V: Encodable<E>,
> Encodable<E> for HashMap<K, V> { S,
H: Hasher<S>
> Encodable<E> for HashMap<K, V, H> {
fn encode(&self, e: &mut E) { fn encode(&self, e: &mut E) {
e.emit_map(self.len(), |e| { e.emit_map(self.len(), |e| {
let mut i = 0; let mut i = 0;
@ -181,12 +184,15 @@ impl<
impl< impl<
D: Decoder, D: Decoder,
K: Decodable<D> + Hash + Eq, K: Decodable<D> + Hash<S> + Eq,
V: Decodable<D> V: Decodable<D>,
> Decodable<D> for HashMap<K, V> { S,
fn decode(d: &mut D) -> HashMap<K, V> { H: Hasher<S> + Default
> Decodable<D> for HashMap<K, V, H> {
fn decode(d: &mut D) -> HashMap<K, V, H> {
d.read_map(|d, len| { d.read_map(|d, len| {
let mut map = HashMap::with_capacity(len); let hasher = Default::default();
let mut map = HashMap::with_capacity_and_hasher(hasher, len);
for i in range(0u, len) { for i in range(0u, len) {
let key = d.read_map_elt_key(i, |d| Decodable::decode(d)); let key = d.read_map_elt_key(i, |d| Decodable::decode(d));
let val = d.read_map_elt_val(i, |d| Decodable::decode(d)); let val = d.read_map_elt_val(i, |d| Decodable::decode(d));
@ -198,10 +204,12 @@ impl<
} }
impl< impl<
S: Encoder, E: Encoder,
T: Encodable<S> + Hash + Eq T: Encodable<E> + Hash<S> + Eq,
> Encodable<S> for HashSet<T> { S,
fn encode(&self, s: &mut S) { H: Hasher<S>
> Encodable<E> for HashSet<T, H> {
fn encode(&self, s: &mut E) {
s.emit_seq(self.len(), |s| { s.emit_seq(self.len(), |s| {
let mut i = 0; let mut i = 0;
for e in self.iter() { for e in self.iter() {
@ -214,11 +222,13 @@ impl<
impl< impl<
D: Decoder, D: Decoder,
T: Decodable<D> + Hash + Eq T: Decodable<D> + Hash<S> + Eq,
> Decodable<D> for HashSet<T> { S,
fn decode(d: &mut D) -> HashSet<T> { H: Hasher<S> + Default
> Decodable<D> for HashSet<T, H> {
fn decode(d: &mut D) -> HashSet<T, H> {
d.read_seq(|d, len| { d.read_seq(|d, len| {
let mut set = HashSet::with_capacity(len); let mut set = HashSet::with_capacity_and_hasher(Default::default(), len);
for i in range(0u, len) { for i in range(0u, len) {
set.insert(d.read_seq_elt(i, |d| Decodable::decode(d))); set.insert(d.read_seq_elt(i, |d| Decodable::decode(d)));
} }

View file

@ -20,7 +20,11 @@ Core encoding and decoding interfaces.
#[license = "MIT/ASL2"]; #[license = "MIT/ASL2"];
#[allow(missing_doc)]; #[allow(missing_doc)];
#[forbid(non_camel_case_types)]; #[forbid(non_camel_case_types)];
#[feature(macro_rules,managed_boxes)]; #[feature(macro_rules, managed_boxes, default_type_params)];
// NOTE remove the following two attributes after the next snapshot.
#[allow(unrecognized_lint)];
#[allow(default_type_param_usage)];
// test harness access // test harness access
#[cfg(test)] #[cfg(test)]

View file

@ -24,7 +24,9 @@
* discouraged. * discouraged.
*/ */
use clone::Clone;
use container::Container; use container::Container;
use default::Default;
use io::{IoResult, Writer}; use io::{IoResult, Writer};
use iter::Iterator; use iter::Iterator;
use result::Ok; use result::Ok;
@ -81,7 +83,13 @@ macro_rules! compress (
impl SipState { impl SipState {
/// Create a `SipState` that is keyed off the provided keys. /// Create a `SipState` that is keyed off the provided keys.
#[inline] #[inline]
pub fn new(key0: u64, key1: u64) -> SipState { pub fn new() -> SipState {
SipState::new_with_keys(0, 0)
}
/// Create a `SipState` that is keyed off the provided keys.
#[inline]
pub fn new_with_keys(key0: u64, key1: u64) -> SipState {
let mut state = SipState { let mut state = SipState {
k0: key0, k0: key0,
k1: key1, k1: key1,
@ -206,7 +214,22 @@ impl Writer for SipState {
} }
} }
/// `Sip` computes the SipHash algorithm from a stream of bytes. impl Clone for SipState {
#[inline]
fn clone(&self) -> SipState {
*self
}
}
impl Default for SipState {
#[inline]
fn default() -> SipState {
SipState::new()
}
}
/// `SipHasher` computes the SipHash algorithm from a stream of bytes.
#[deriving(Clone)]
pub struct SipHasher { pub struct SipHasher {
priv state: SipState, priv state: SipState,
} }
@ -215,14 +238,16 @@ impl SipHasher {
/// Create a `Sip`. /// Create a `Sip`.
#[inline] #[inline]
pub fn new() -> SipHasher { pub fn new() -> SipHasher {
SipHasher::new_with_keys(0, 0) SipHasher {
state: SipState::new(),
}
} }
/// Create a `Sip` that is keyed off the provided keys. /// Create a `Sip` that is keyed off the provided keys.
#[inline] #[inline]
pub fn new_with_keys(key0: u64, key1: u64) -> SipHasher { pub fn new_with_keys(key0: u64, key1: u64) -> SipHasher {
SipHasher { SipHasher {
state: SipState::new(key0, key1), state: SipState::new_with_keys(key0, key1),
} }
} }
} }
@ -230,23 +255,31 @@ impl SipHasher {
impl Hasher<SipState> for SipHasher { impl Hasher<SipState> for SipHasher {
#[inline] #[inline]
fn hash<T: Hash<SipState>>(&self, value: &T) -> u64 { fn hash<T: Hash<SipState>>(&self, value: &T) -> u64 {
let mut state = self.state; // implicitly copy the state. let mut state = self.state.clone();
value.hash(&mut state); value.hash(&mut state);
state.result() state.result()
} }
} }
impl Default for SipHasher {
#[inline]
fn default() -> SipHasher {
SipHasher::new()
}
}
/// Hash a value using the SipHash algorithm. /// Hash a value using the SipHash algorithm.
#[inline] #[inline]
pub fn hash<T: Hash<SipState>>(value: &T) -> u64 { pub fn hash<T: Hash<SipState>>(value: &T) -> u64 {
hash_with_keys(0, 0, value) let mut state = SipState::new();
value.hash(&mut state);
state.result()
} }
/// Hash a value with the SipHash algorithm with the provided keys. /// Hash a value with the SipHash algorithm with the provided keys.
#[inline] #[inline]
pub fn hash_with_keys<T: Hash<SipState>>(k0: u64, k1: u64, value: &T) -> u64 { pub fn hash_with_keys<T: Hash<SipState>>(k0: u64, k1: u64, value: &T) -> u64 {
let mut state = SipState::new(k0, k1); let mut state = SipState::new_with_keys(k0, k1);
value.hash(&mut state); value.hash(&mut state);
state.result() state.result()
} }
@ -350,8 +383,8 @@ mod tests {
let k1 = 0x_0f_0e_0d_0c_0b_0a_09_08_u64; let k1 = 0x_0f_0e_0d_0c_0b_0a_09_08_u64;
let mut buf : ~[u8] = ~[]; let mut buf : ~[u8] = ~[];
let mut t = 0; let mut t = 0;
let mut state_inc = SipState::new(k0, k1); let mut state_inc = SipState::new_with_keys(k0, k1);
let mut state_full = SipState::new(k0, k1); let mut state_full = SipState::new_with_keys(k0, k1);
fn to_hex_str(r: &[u8, ..8]) -> ~str { fn to_hex_str(r: &[u8, ..8]) -> ~str {
let mut s = ~""; let mut s = ~"";