auto merge of #12544 : erickt/rust/hash, r=acrichto

This PR allows `HashMap`s to work with custom hashers. Also with this patch are:

* a couple generic implementations of `Hash` for a variety of types.
* added `Default`, `Clone` impls to the hashers.
* added a `HashMap::with_hasher()` constructor.
This commit is contained in:
bors 2014-02-28 00:26:34 -08:00
commit 31e9c947a3
6 changed files with 181 additions and 110 deletions

View File

@ -55,7 +55,8 @@
use std::cmp::max;
use std::default::Default;
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;
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
/// is randomized by keying each hash map randomly on creation.
///
/// It is required that the keys implement the `Eq` and `Hash` traits.
pub struct HashMap<K,V> {
priv k0: u64,
priv k1: u64,
/// 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,
priv resize_at: uint,
priv size: uint,
priv buckets: Vec<Option<Bucket<K, V>>>
@ -98,7 +99,7 @@ fn resize_at(capacity: uint) -> uint {
(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]
fn to_bucket(&self, h: uint) -> uint {
// A good hash function with entropy spread over all of the
@ -127,14 +128,13 @@ fn bucket_sequence(&self, hash: uint, op: |uint| -> bool) -> bool {
#[inline]
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)
}
#[inline]
fn bucket_for_key_equiv<Q:Hash + Equiv<K>>(&self, k: &Q)
-> SearchResult {
let hash = sip::hash_with_keys(self.k0, self.k1, k) as uint;
fn bucket_for_key_equiv<Q:Hash<S> + Equiv<K>>(&self, k: &Q) -> SearchResult {
let hash = self.hasher.hash(k) as uint;
self.bucket_for_key_with_hash_equiv(hash, k)
}
@ -285,12 +285,12 @@ fn pop_internal(&mut self, hash: uint, k: &K) -> Option<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
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.
fn clear(&mut self) {
for bkt in self.buckets.as_mut_slice().mut_iter() {
@ -300,7 +300,7 @@ fn clear(&mut self) {
}
}
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
fn find<'a>(&'a self, k: &K) -> Option<&'a V> {
match self.bucket_for_key(k) {
@ -310,7 +310,7 @@ fn find<'a>(&'a self, k: &K) -> Option<&'a 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
fn find_mut<'a>(&'a mut self, k: &K) -> Option<&'a mut V> {
let idx = match self.bucket_for_key(k) {
@ -335,21 +335,21 @@ fn swap(&mut self, k: K, v: V) -> Option<V> {
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)
}
/// 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> {
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)
}
}
impl<K: Hash + Eq, V> HashMap<K, V> {
/// Create an empty HashMap
pub fn new() -> HashMap<K, V> {
pub fn new() -> HashMap<K, V, SipHasher> {
HashMap::with_capacity(INITIAL_CAPACITY)
}
@ -357,20 +357,27 @@ pub fn new() -> HashMap<K, V> {
/// elements in the hash table.
pub fn with_capacity(capacity: uint) -> HashMap<K, V> {
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`
/// elements, using `k0` and `k1` as the keys.
/// elements, using `hasher` to hash the keys.
///
/// Warning: `k0` and `k1` are normally randomly generated, and
/// are designed to allow HashMaps to be resistant to attacks that
/// cause many collisions and very poor performance. Setting them
/// 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
/// 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);
HashMap {
k0: k0, k1: k1,
hasher: hasher,
resize_at: resize_at(cap),
size: 0,
buckets: Vec::from_fn(cap, |_| None)
@ -442,7 +449,7 @@ pub fn mangle<'a,
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) {
TableFull => fail!("Internal logic error"),
FoundEntry(idx) => { found(&k, self.mut_value_for_bucket(idx), a); idx }
@ -502,7 +509,7 @@ pub fn get_mut<'a>(&'a mut self, k: &K) -> &'a mut V {
/// Return true if the map contains a value for the specified key,
/// 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) {
FoundEntry(_) => {true}
TableFull | FoundHole(_) => {false}
@ -511,8 +518,7 @@ pub fn contains_key_equiv<Q:Hash + Equiv<K>>(&self, key: &Q) -> bool {
/// Return the value corresponding to the key in the map, using
/// equivalence
pub fn find_equiv<'a, Q:Hash + Equiv<K>>(&'a self, k: &Q)
-> Option<&'a V> {
pub fn find_equiv<'a, Q:Hash<S> + Equiv<K>>(&'a self, k: &Q) -> Option<&'a V> {
match self.bucket_for_key_equiv(k) {
FoundEntry(idx) => Some(self.value_for_bucket(idx)),
TableFull | FoundHole(_) => None,
@ -552,7 +558,7 @@ pub fn move_iter(self) -> MoveEntries<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.
pub fn find_copy(&self, k: &K) -> Option<V> {
self.find(k).map(|v| (*v).clone())
@ -564,8 +570,8 @@ pub fn get_copy(&self, k: &K) -> V {
}
}
impl<K:Hash + Eq,V:Eq> Eq for HashMap<K, V> {
fn eq(&self, other: &HashMap<K, V>) -> bool {
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 {
if self.len() != other.len() { return false; }
self.iter().all(|(key, value)| {
@ -576,12 +582,12 @@ fn eq(&self, other: &HashMap<K, V>) -> bool {
})
}
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> {
fn clone(&self) -> HashMap<K,V> {
let mut new_map = HashMap::with_capacity(self.len());
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> {
let mut new_map = HashMap::with_capacity_and_hasher(self.hasher.clone(), self.len());
for (key, value) in self.iter() {
new_map.insert((*key).clone(), (*value).clone());
}
@ -589,7 +595,7 @@ fn clone(&self) -> 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 {
try!(write!(f.buf, r"\{"))
let mut first = true;
@ -705,16 +711,16 @@ fn next(&mut self) -> Option<K> {
}
}
impl<K: Eq + Hash, V> FromIterator<(K, V)> for HashMap<K, V> {
fn from_iterator<T: Iterator<(K, V)>>(iter: &mut T) -> 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, H> {
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
}
}
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) {
for (k, v) in *iter {
self.insert(k, v);
@ -722,54 +728,56 @@ fn extend<T: Iterator<(K, V)>>(&mut self, iter: &mut T) {
}
}
impl<K: Eq + Hash, V> Default for HashMap<K, V> {
fn default() -> HashMap<K, V> { HashMap::new() }
impl<K: Hash<S> + Eq, V, S, H: Hasher<S> + Default> Default for HashMap<K, V, H> {
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
/// HashMap where the value is (). As with the `HashMap` type, a `HashSet`
/// requires that the elements implement the `Eq` and `Hash` traits.
pub struct HashSet<T> {
priv map: HashMap<T, ()>
pub struct HashSet<T, H = SipHasher> {
priv map: HashMap<T, (), H>
}
impl<T:Hash + Eq> Eq for HashSet<T> {
fn eq(&self, other: &HashSet<T>) -> bool { self.map == other.map }
fn ne(&self, other: &HashSet<T>) -> bool { self.map != other.map }
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 }
}
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
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.
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
fn contains(&self, value: &T) -> bool { self.map.contains_key(value) }
/// Return true if the set has no elements in common with `other`.
/// 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))
}
/// 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))
}
/// 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)
}
}
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
/// present in the set.
fn insert(&mut self, value: T) -> bool { self.map.insert(value, ()) }
@ -779,27 +787,35 @@ fn insert(&mut self, value: T) -> bool { self.map.insert(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
pub fn new() -> HashSet<T> {
pub fn new() -> HashSet<T, SipHasher> {
HashSet::with_capacity(INITIAL_CAPACITY)
}
/// Create an empty HashSet with space for at least `n` elements in
/// 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) }
}
}
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`
/// 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
/// cause many collisions and very poor performance. Setting them
/// manually using this function can expose a DoS attack vector.
pub fn with_capacity_and_keys(k0: u64, k1: u64, capacity: uint) -> HashSet<T> {
HashSet { map: HashMap::with_capacity_and_keys(k0, k1, capacity) }
pub fn with_capacity_and_hasher(hasher: H, capacity: uint) -> HashSet<T, H> {
HashSet {
map: HashMap::with_capacity_and_hasher(hasher, capacity)
}
}
/// Reserve space for at least `n` elements in the hash table.
@ -809,7 +825,7 @@ pub fn reserve(&mut self, n: uint) {
/// Returns true if the hash set contains a value equivalent to the
/// 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)
}
@ -827,7 +843,7 @@ pub fn move_iter(self) -> SetMoveItems<T> {
}
/// 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)
.zip(self.iter())
.filter_map(|(other, elt)| {
@ -836,14 +852,14 @@ pub fn difference<'a>(&'a self, other: &'a HashSet<T>) -> SetAlgebraItems<'a, T>
}
/// Visit the values representing the symmetric difference
pub fn symmetric_difference<'a>(&'a self, other: &'a HashSet<T>)
-> Chain<SetAlgebraItems<'a, T>, SetAlgebraItems<'a, T>> {
pub fn symmetric_difference<'a>(&'a self, other: &'a HashSet<T, H>)
-> Chain<SetAlgebraItems<'a, T, H>, SetAlgebraItems<'a, T, H>> {
self.difference(other).chain(other.difference(self))
}
/// Visit the values representing the intersection
pub fn intersection<'a>(&'a self, other: &'a HashSet<T>)
-> SetAlgebraItems<'a, T> {
pub fn intersection<'a>(&'a self, other: &'a HashSet<T, H>)
-> SetAlgebraItems<'a, T, H> {
Repeat::new(other)
.zip(self.iter())
.filter_map(|(other, elt)| {
@ -852,22 +868,22 @@ pub fn intersection<'a>(&'a self, other: &'a HashSet<T>)
}
/// Visit the values representing the union
pub fn union<'a>(&'a self, other: &'a HashSet<T>)
-> Chain<SetItems<'a, T>, SetAlgebraItems<'a, T>> {
pub fn union<'a>(&'a self, other: &'a HashSet<T, H>)
-> Chain<SetItems<'a, T>, SetAlgebraItems<'a, T, H>> {
self.iter().chain(other.difference(self))
}
}
impl<T:Hash + Eq + Clone> Clone for HashSet<T> {
fn clone(&self) -> HashSet<T> {
impl<T: Hash<S> + Eq + Clone, S, H: Hasher<S> + Clone> Clone for HashSet<T, H> {
fn clone(&self) -> HashSet<T, H> {
HashSet {
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 {
try!(write!(f.buf, r"\{"))
let mut first = true;
@ -883,33 +899,37 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
}
}
impl<K: Eq + Hash> FromIterator<K> for HashSet<K> {
fn from_iterator<T: Iterator<K>>(iter: &mut T) -> HashSet<K> {
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> {
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
}
}
impl<K: Eq + Hash> Extendable<K> for HashSet<K> {
fn extend<T: Iterator<K>>(&mut self, iter: &mut T) {
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) {
for k in *iter {
self.insert(k);
}
}
}
impl<K: Eq + Hash> Default for HashSet<K> {
fn default() -> HashSet<K> { HashSet::new() }
impl<T: Hash<S> + Eq, S, H: Hasher<S> + Default> Default for HashSet<T, H> {
fn default() -> HashSet<T, H> {
HashSet {
map: Default::default(),
}
}
}
// `Repeat` is used to feed the filter closure an explicit capture
// of a reference to the other set
/// Set operations iterator
pub type SetAlgebraItems<'a, T> =
FilterMap<'static,(&'a HashSet<T>, &'a T), &'a T,
Zip<Repeat<&'a HashSet<T>>,SetItems<'a,T>>>;
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>>>;
#[cfg(test)]
mod test_map {

View File

@ -17,7 +17,11 @@
#[crate_type = "dylib"];
#[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;

View File

@ -4883,7 +4883,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
/// 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 {
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! hash( ($e:expr) => { $e.hash(&mut state) } );

View File

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

View File

@ -20,7 +20,11 @@
#[license = "MIT/ASL2"];
#[allow(missing_doc)];
#[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
#[cfg(test)]

View File

@ -24,7 +24,9 @@
* discouraged.
*/
use clone::Clone;
use container::Container;
use default::Default;
use io::{IoResult, Writer};
use iter::Iterator;
use result::Ok;
@ -81,7 +83,13 @@ macro_rules! compress (
impl SipState {
/// Create a `SipState` that is keyed off the provided keys.
#[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 {
k0: key0,
k1: key1,
@ -206,9 +214,25 @@ fn write(&mut self, msg: &[u8]) -> IoResult<()> {
}
}
/// `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 {
priv state: SipState,
priv k0: u64,
priv k1: u64,
}
impl SipHasher {
@ -222,7 +246,8 @@ pub fn new() -> SipHasher {
#[inline]
pub fn new_with_keys(key0: u64, key1: u64) -> SipHasher {
SipHasher {
state: SipState::new(key0, key1),
k0: key0,
k1: key1,
}
}
}
@ -230,23 +255,31 @@ pub fn new_with_keys(key0: u64, key1: u64) -> SipHasher {
impl Hasher<SipState> for SipHasher {
#[inline]
fn hash<T: Hash<SipState>>(&self, value: &T) -> u64 {
let mut state = self.state; // implicitly copy the state.
let mut state = SipState::new_with_keys(self.k0, self.k1);
value.hash(&mut state);
state.result()
}
}
impl Default for SipHasher {
#[inline]
fn default() -> SipHasher {
SipHasher::new()
}
}
/// Hash a value using the SipHash algorithm.
#[inline]
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.
#[inline]
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);
state.result()
}
@ -350,8 +383,8 @@ fn test_siphash() {
let k1 = 0x_0f_0e_0d_0c_0b_0a_09_08_u64;
let mut buf : ~[u8] = ~[];
let mut t = 0;
let mut state_inc = SipState::new(k0, k1);
let mut state_full = SipState::new(k0, k1);
let mut state_inc = SipState::new_with_keys(k0, k1);
let mut state_full = SipState::new_with_keys(k0, k1);
fn to_hex_str(r: &[u8, ..8]) -> ~str {
let mut s = ~"";