std: Stabilize the hash module
This commit is an implementation of [RFC 823][rfc] which is another pass over the `std::hash` module for stabilization. The contents of the module were not entirely marked stable, but some portions which remained quite similar to the previous incarnation are now marked `#[stable]`. Specifically: [rfc]: https://github.com/rust-lang/rfcs/blob/master/text/0823-hash-simplification.md * `std::hash` is now stable (the name) * `Hash` is now stable * `Hash::hash` is now stable * `Hasher` is now stable * `SipHasher` is now stable * `SipHasher::new` and `new_with_keys` are now stable * `Hasher for SipHasher` is now stable * Many `Hash` implementations are now stable All other portions of the `hash` module remain `#[unstable]` as they are less commonly used and were recently redesigned. This commit is a breaking change due to the modifications to the `std::hash` API and more details can be found on the [RFC][rfc]. Closes #22467 [breaking-change]
This commit is contained in:
parent
dfc5c0f1e8
commit
f83e23ad7c
54 changed files with 5004 additions and 372 deletions
|
|
@ -17,7 +17,7 @@
|
|||
use clone::Clone;
|
||||
use cmp::{PartialEq, Eq, PartialOrd, Ord, Ordering};
|
||||
use fmt;
|
||||
use hash::{Hash, Hasher, self};
|
||||
use hash::{Hash, self};
|
||||
use iter::IntoIterator;
|
||||
use marker::Copy;
|
||||
use ops::Deref;
|
||||
|
|
@ -35,11 +35,19 @@ macro_rules! array_impls {
|
|||
}
|
||||
}
|
||||
|
||||
impl<S: hash::Writer + Hasher, T: Hash<S>> Hash<S> for [T; $N] {
|
||||
#[cfg(stage0)]
|
||||
impl<S: hash::Writer + hash::Hasher, T: Hash<S>> Hash<S> for [T; $N] {
|
||||
fn hash(&self, state: &mut S) {
|
||||
Hash::hash(&self[], state)
|
||||
}
|
||||
}
|
||||
#[cfg(not(stage0))]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: Hash> Hash for [T; $N] {
|
||||
fn hash<H: hash::Hasher>(&self, state: &mut H) {
|
||||
Hash::hash(&self[], state)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: fmt::Debug> fmt::Debug for [T; $N] {
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@
|
|||
//! the trait `Hash`:
|
||||
//!
|
||||
//! ```rust
|
||||
//! use std::hash::{hash, Hash, Hasher, Writer, SipHasher};
|
||||
//! use std::hash::{hash, Hash, Hasher, SipHasher};
|
||||
//!
|
||||
//! struct Person {
|
||||
//! id: uint,
|
||||
|
|
@ -43,8 +43,8 @@
|
|||
//! phone: u64,
|
||||
//! }
|
||||
//!
|
||||
//! impl<H: Hasher + Writer> Hash<H> for Person {
|
||||
//! fn hash(&self, state: &mut H) {
|
||||
//! impl Hash for Person {
|
||||
//! fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
//! self.id.hash(state);
|
||||
//! self.phone.hash(state);
|
||||
//! }
|
||||
|
|
@ -56,15 +56,11 @@
|
|||
//! assert_eq!(hash::<_, SipHasher>(&person1), hash::<_, SipHasher>(&person2));
|
||||
//! ```
|
||||
|
||||
#![unstable(feature = "hash",
|
||||
reason = "module was recently redesigned")]
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
|
||||
use prelude::*;
|
||||
|
||||
use borrow::{Cow, ToOwned};
|
||||
use default::Default;
|
||||
use marker::Sized;
|
||||
use mem;
|
||||
use num::Int;
|
||||
|
||||
pub use self::sip::SipHasher;
|
||||
|
||||
|
|
@ -76,22 +72,123 @@ mod sip;
|
|||
/// to compute the hash. Specific implementations of this trait may specialize
|
||||
/// for particular instances of `H` in order to be able to optimize the hashing
|
||||
/// behavior.
|
||||
#[cfg(not(stage0))]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub trait Hash {
|
||||
/// Feeds this value into the state given, updating the hasher as necessary.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
fn hash<H: Hasher>(&self, state: &mut H);
|
||||
|
||||
/// Feeds a slice of this type into the state provided.
|
||||
#[unstable(feature = "hash", reason = "module was recently redesigned")]
|
||||
fn hash_slice<H: Hasher>(data: &[Self], state: &mut H) where Self: Sized {
|
||||
for piece in data {
|
||||
piece.hash(state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A hashable type.
|
||||
///
|
||||
/// The `H` type parameter is an abstract hash state that is used by the `Hash`
|
||||
/// to compute the hash. Specific implementations of this trait may specialize
|
||||
/// for particular instances of `H` in order to be able to optimize the hashing
|
||||
/// behavior.
|
||||
#[cfg(stage0)]
|
||||
pub trait Hash<H: Hasher> {
|
||||
/// Feeds this value into the state given, updating the hasher as necessary.
|
||||
fn hash(&self, state: &mut H);
|
||||
}
|
||||
|
||||
/// A trait which represents the ability to hash an arbitrary stream of bytes.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub trait Hasher {
|
||||
/// Result type of one run of hashing generated by this hasher.
|
||||
#[cfg(stage0)]
|
||||
type Output;
|
||||
|
||||
/// Resets this hasher back to its initial state (as if it were just
|
||||
/// created).
|
||||
#[cfg(stage0)]
|
||||
fn reset(&mut self);
|
||||
|
||||
/// Completes a round of hashing, producing the output hash generated.
|
||||
#[cfg(stage0)]
|
||||
fn finish(&self) -> Self::Output;
|
||||
|
||||
/// Completes a round of hashing, producing the output hash generated.
|
||||
#[cfg(not(stage0))]
|
||||
#[unstable(feature = "hash", reason = "module was recently redesigned")]
|
||||
fn finish(&self) -> u64;
|
||||
|
||||
/// Writes some data into this `Hasher`
|
||||
#[cfg(not(stage0))]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
fn write(&mut self, bytes: &[u8]);
|
||||
|
||||
/// Write a single `u8` into this hasher
|
||||
#[cfg(not(stage0))]
|
||||
#[inline]
|
||||
#[unstable(feature = "hash", reason = "module was recently redesigned")]
|
||||
fn write_u8(&mut self, i: u8) { self.write(&[i]) }
|
||||
/// Write a single `u16` into this hasher.
|
||||
#[cfg(not(stage0))]
|
||||
#[inline]
|
||||
#[unstable(feature = "hash", reason = "module was recently redesigned")]
|
||||
fn write_u16(&mut self, i: u16) {
|
||||
self.write(&unsafe { mem::transmute::<_, [u8; 2]>(i) })
|
||||
}
|
||||
/// Write a single `u32` into this hasher.
|
||||
#[cfg(not(stage0))]
|
||||
#[inline]
|
||||
#[unstable(feature = "hash", reason = "module was recently redesigned")]
|
||||
fn write_u32(&mut self, i: u32) {
|
||||
self.write(&unsafe { mem::transmute::<_, [u8; 4]>(i) })
|
||||
}
|
||||
/// Write a single `u64` into this hasher.
|
||||
#[cfg(not(stage0))]
|
||||
#[inline]
|
||||
#[unstable(feature = "hash", reason = "module was recently redesigned")]
|
||||
fn write_u64(&mut self, i: u64) {
|
||||
self.write(&unsafe { mem::transmute::<_, [u8; 8]>(i) })
|
||||
}
|
||||
/// Write a single `usize` into this hasher.
|
||||
#[cfg(not(stage0))]
|
||||
#[inline]
|
||||
#[unstable(feature = "hash", reason = "module was recently redesigned")]
|
||||
fn write_usize(&mut self, i: usize) {
|
||||
if cfg!(target_pointer_size = "32") {
|
||||
self.write_u32(i as u32)
|
||||
} else {
|
||||
self.write_u64(i as u64)
|
||||
}
|
||||
}
|
||||
|
||||
/// Write a single `i8` into this hasher.
|
||||
#[cfg(not(stage0))]
|
||||
#[inline]
|
||||
#[unstable(feature = "hash", reason = "module was recently redesigned")]
|
||||
fn write_i8(&mut self, i: i8) { self.write_u8(i as u8) }
|
||||
/// Write a single `i16` into this hasher.
|
||||
#[cfg(not(stage0))]
|
||||
#[inline]
|
||||
#[unstable(feature = "hash", reason = "module was recently redesigned")]
|
||||
fn write_i16(&mut self, i: i16) { self.write_u16(i as u16) }
|
||||
/// Write a single `i32` into this hasher.
|
||||
#[cfg(not(stage0))]
|
||||
#[inline]
|
||||
#[unstable(feature = "hash", reason = "module was recently redesigned")]
|
||||
fn write_i32(&mut self, i: i32) { self.write_u32(i as u32) }
|
||||
/// Write a single `i64` into this hasher.
|
||||
#[cfg(not(stage0))]
|
||||
#[inline]
|
||||
#[unstable(feature = "hash", reason = "module was recently redesigned")]
|
||||
fn write_i64(&mut self, i: i64) { self.write_u64(i as u64) }
|
||||
/// Write a single `isize` into this hasher.
|
||||
#[cfg(not(stage0))]
|
||||
#[inline]
|
||||
#[unstable(feature = "hash", reason = "module was recently redesigned")]
|
||||
fn write_isize(&mut self, i: isize) { self.write_usize(i as usize) }
|
||||
}
|
||||
|
||||
/// A common bound on the `Hasher` parameter to `Hash` implementations in order
|
||||
|
|
@ -99,6 +196,7 @@ pub trait Hasher {
|
|||
#[unstable(feature = "hash",
|
||||
reason = "this trait will likely be replaced by io::Writer")]
|
||||
#[allow(missing_docs)]
|
||||
#[cfg(stage0)]
|
||||
pub trait Writer {
|
||||
fn write(&mut self, bytes: &[u8]);
|
||||
}
|
||||
|
|
@ -107,148 +205,312 @@ pub trait Writer {
|
|||
///
|
||||
/// The specified value will be hashed with this hasher and then the resulting
|
||||
/// hash will be returned.
|
||||
#[cfg(stage0)]
|
||||
pub fn hash<T: Hash<H>, H: Hasher + Default>(value: &T) -> H::Output {
|
||||
let mut h: H = Default::default();
|
||||
value.hash(&mut h);
|
||||
h.finish()
|
||||
}
|
||||
|
||||
/// Hash a value with the default SipHasher algorithm (two initial keys of 0).
|
||||
///
|
||||
/// The specified value will be hashed with this hasher and then the resulting
|
||||
/// hash will be returned.
|
||||
#[cfg(not(stage0))]
|
||||
#[unstable(feature = "hash", reason = "module was recently redesigned")]
|
||||
pub fn hash<T: Hash, H: Hasher + Default>(value: &T) -> u64 {
|
||||
let mut h: H = Default::default();
|
||||
value.hash(&mut h);
|
||||
h.finish()
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
macro_rules! impl_hash {
|
||||
($ty:ident, $uty:ident) => {
|
||||
impl<S: Writer + Hasher> Hash<S> for $ty {
|
||||
#[inline]
|
||||
fn hash(&self, state: &mut S) {
|
||||
let a: [u8; ::$ty::BYTES] = unsafe {
|
||||
mem::transmute((*self as $uty).to_le() as $ty)
|
||||
};
|
||||
state.write(&a)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#[cfg(stage0)]
|
||||
mod impls {
|
||||
use prelude::*;
|
||||
|
||||
impl_hash! { u8, u8 }
|
||||
impl_hash! { u16, u16 }
|
||||
impl_hash! { u32, u32 }
|
||||
impl_hash! { u64, u64 }
|
||||
impl_hash! { uint, uint }
|
||||
impl_hash! { i8, u8 }
|
||||
impl_hash! { i16, u16 }
|
||||
impl_hash! { i32, u32 }
|
||||
impl_hash! { i64, u64 }
|
||||
impl_hash! { int, uint }
|
||||
use borrow::{Cow, ToOwned};
|
||||
use mem;
|
||||
use num::Int;
|
||||
use super::*;
|
||||
|
||||
impl<S: Writer + Hasher> Hash<S> for bool {
|
||||
#[inline]
|
||||
fn hash(&self, state: &mut S) {
|
||||
(*self as u8).hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: Writer + Hasher> Hash<S> for char {
|
||||
#[inline]
|
||||
fn hash(&self, state: &mut S) {
|
||||
(*self as u32).hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: Writer + Hasher> Hash<S> for str {
|
||||
#[inline]
|
||||
fn hash(&self, state: &mut S) {
|
||||
state.write(self.as_bytes());
|
||||
0xffu8.hash(state)
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! impl_hash_tuple {
|
||||
() => (
|
||||
impl<S: Hasher> Hash<S> for () {
|
||||
#[inline]
|
||||
fn hash(&self, _state: &mut S) {}
|
||||
}
|
||||
);
|
||||
|
||||
( $($name:ident)+) => (
|
||||
impl<S: Hasher, $($name: Hash<S>),*> Hash<S> for ($($name,)*) {
|
||||
#[inline]
|
||||
#[allow(non_snake_case)]
|
||||
fn hash(&self, state: &mut S) {
|
||||
match *self {
|
||||
($(ref $name,)*) => {
|
||||
$(
|
||||
$name.hash(state);
|
||||
)*
|
||||
}
|
||||
macro_rules! impl_hash {
|
||||
($ty:ident, $uty:ident) => {
|
||||
impl<S: Writer + Hasher> Hash<S> for $ty {
|
||||
#[inline]
|
||||
fn hash(&self, state: &mut S) {
|
||||
let a: [u8; ::$ty::BYTES] = unsafe {
|
||||
mem::transmute((*self as $uty).to_le() as $ty)
|
||||
};
|
||||
state.write(&a)
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
impl_hash_tuple! {}
|
||||
impl_hash_tuple! { A }
|
||||
impl_hash_tuple! { A B }
|
||||
impl_hash_tuple! { A B C }
|
||||
impl_hash_tuple! { A B C D }
|
||||
impl_hash_tuple! { A B C D E }
|
||||
impl_hash_tuple! { A B C D E F }
|
||||
impl_hash_tuple! { A B C D E F G }
|
||||
impl_hash_tuple! { A B C D E F G H }
|
||||
impl_hash_tuple! { A B C D E F G H I }
|
||||
impl_hash_tuple! { A B C D E F G H I J }
|
||||
impl_hash_tuple! { A B C D E F G H I J K }
|
||||
impl_hash_tuple! { A B C D E F G H I J K L }
|
||||
impl_hash! { u8, u8 }
|
||||
impl_hash! { u16, u16 }
|
||||
impl_hash! { u32, u32 }
|
||||
impl_hash! { u64, u64 }
|
||||
impl_hash! { uint, uint }
|
||||
impl_hash! { i8, u8 }
|
||||
impl_hash! { i16, u16 }
|
||||
impl_hash! { i32, u32 }
|
||||
impl_hash! { i64, u64 }
|
||||
impl_hash! { int, uint }
|
||||
|
||||
impl<S: Writer + Hasher, T: Hash<S>> Hash<S> for [T] {
|
||||
#[inline]
|
||||
fn hash(&self, state: &mut S) {
|
||||
self.len().hash(state);
|
||||
for elt in self {
|
||||
elt.hash(state);
|
||||
impl<S: Writer + Hasher> Hash<S> for bool {
|
||||
#[inline]
|
||||
fn hash(&self, state: &mut S) {
|
||||
(*self as u8).hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: Writer + Hasher> Hash<S> for char {
|
||||
#[inline]
|
||||
fn hash(&self, state: &mut S) {
|
||||
(*self as u32).hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: Writer + Hasher> Hash<S> for str {
|
||||
#[inline]
|
||||
fn hash(&self, state: &mut S) {
|
||||
state.write(self.as_bytes());
|
||||
0xffu8.hash(state)
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! impl_hash_tuple {
|
||||
() => (
|
||||
impl<S: Hasher> Hash<S> for () {
|
||||
#[inline]
|
||||
fn hash(&self, _state: &mut S) {}
|
||||
}
|
||||
);
|
||||
|
||||
( $($name:ident)+) => (
|
||||
impl<S: Hasher, $($name: Hash<S>),*> Hash<S> for ($($name,)*) {
|
||||
#[inline]
|
||||
#[allow(non_snake_case)]
|
||||
fn hash(&self, state: &mut S) {
|
||||
match *self {
|
||||
($(ref $name,)*) => {
|
||||
$(
|
||||
$name.hash(state);
|
||||
)*
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
impl_hash_tuple! {}
|
||||
impl_hash_tuple! { A }
|
||||
impl_hash_tuple! { A B }
|
||||
impl_hash_tuple! { A B C }
|
||||
impl_hash_tuple! { A B C D }
|
||||
impl_hash_tuple! { A B C D E }
|
||||
impl_hash_tuple! { A B C D E F }
|
||||
impl_hash_tuple! { A B C D E F G }
|
||||
impl_hash_tuple! { A B C D E F G H }
|
||||
impl_hash_tuple! { A B C D E F G H I }
|
||||
impl_hash_tuple! { A B C D E F G H I J }
|
||||
impl_hash_tuple! { A B C D E F G H I J K }
|
||||
impl_hash_tuple! { A B C D E F G H I J K L }
|
||||
|
||||
impl<S: Writer + Hasher, T: Hash<S>> Hash<S> for [T] {
|
||||
#[inline]
|
||||
fn hash(&self, state: &mut S) {
|
||||
self.len().hash(state);
|
||||
for elt in self {
|
||||
elt.hash(state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl<'a, S: Hasher, T: ?Sized + Hash<S>> Hash<S> for &'a T {
|
||||
#[inline]
|
||||
fn hash(&self, state: &mut S) {
|
||||
(**self).hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, S: Hasher, T: ?Sized + Hash<S>> Hash<S> for &'a mut T {
|
||||
#[inline]
|
||||
fn hash(&self, state: &mut S) {
|
||||
(**self).hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: Writer + Hasher, T> Hash<S> for *const T {
|
||||
#[inline]
|
||||
fn hash(&self, state: &mut S) {
|
||||
// NB: raw-pointer Hash does _not_ dereference
|
||||
// to the target; it just gives you the pointer-bytes.
|
||||
(*self as uint).hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: Writer + Hasher, T> Hash<S> for *mut T {
|
||||
#[inline]
|
||||
fn hash(&self, state: &mut S) {
|
||||
// NB: raw-pointer Hash does _not_ dereference
|
||||
// to the target; it just gives you the pointer-bytes.
|
||||
(*self as uint).hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T, B: ?Sized, S: Hasher> Hash<S> for Cow<'a, T, B>
|
||||
where B: Hash<S> + ToOwned<T>
|
||||
{
|
||||
#[inline]
|
||||
fn hash(&self, state: &mut S) {
|
||||
Hash::hash(&**self, state)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(stage0))]
|
||||
mod impls {
|
||||
use prelude::*;
|
||||
|
||||
impl<'a, S: Hasher, T: ?Sized + Hash<S>> Hash<S> for &'a T {
|
||||
#[inline]
|
||||
fn hash(&self, state: &mut S) {
|
||||
(**self).hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, S: Hasher, T: ?Sized + Hash<S>> Hash<S> for &'a mut T {
|
||||
#[inline]
|
||||
fn hash(&self, state: &mut S) {
|
||||
(**self).hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: Writer + Hasher, T> Hash<S> for *const T {
|
||||
#[inline]
|
||||
fn hash(&self, state: &mut S) {
|
||||
// NB: raw-pointer Hash does _not_ dereference
|
||||
// to the target; it just gives you the pointer-bytes.
|
||||
(*self as uint).hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: Writer + Hasher, T> Hash<S> for *mut T {
|
||||
#[inline]
|
||||
fn hash(&self, state: &mut S) {
|
||||
// NB: raw-pointer Hash does _not_ dereference
|
||||
// to the target; it just gives you the pointer-bytes.
|
||||
(*self as uint).hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T, B: ?Sized, S: Hasher> Hash<S> for Cow<'a, T, B>
|
||||
where B: Hash<S> + ToOwned<T>
|
||||
{
|
||||
#[inline]
|
||||
fn hash(&self, state: &mut S) {
|
||||
Hash::hash(&**self, state)
|
||||
use borrow::{Cow, ToOwned};
|
||||
use slice;
|
||||
use super::*;
|
||||
|
||||
macro_rules! impl_write {
|
||||
($(($ty:ident, $meth:ident),)*) => {$(
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl Hash for $ty {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
state.$meth(*self)
|
||||
}
|
||||
|
||||
fn hash_slice<H: Hasher>(data: &[$ty], state: &mut H) {
|
||||
let newlen = data.len() * ::$ty::BYTES;
|
||||
let ptr = data.as_ptr() as *const u8;
|
||||
state.write(unsafe { slice::from_raw_parts(ptr, newlen) })
|
||||
}
|
||||
}
|
||||
)*}
|
||||
}
|
||||
|
||||
impl_write! {
|
||||
(u8, write_u8),
|
||||
(u16, write_u16),
|
||||
(u32, write_u32),
|
||||
(u64, write_u64),
|
||||
(usize, write_usize),
|
||||
(i8, write_i8),
|
||||
(i16, write_i16),
|
||||
(i32, write_i32),
|
||||
(i64, write_i64),
|
||||
(isize, write_isize),
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl Hash for bool {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
state.write_u8(*self as u8)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl Hash for char {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
state.write_u32(*self as u32)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl Hash for str {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
state.write(self.as_bytes());
|
||||
state.write_u8(0xff)
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! impl_hash_tuple {
|
||||
() => (
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl Hash for () {
|
||||
fn hash<H: Hasher>(&self, _state: &mut H) {}
|
||||
}
|
||||
);
|
||||
|
||||
( $($name:ident)+) => (
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<$($name: Hash),*> Hash for ($($name,)*) {
|
||||
#[allow(non_snake_case)]
|
||||
fn hash<S: Hasher>(&self, state: &mut S) {
|
||||
let ($(ref $name,)*) = *self;
|
||||
$($name.hash(state);)*
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
impl_hash_tuple! {}
|
||||
impl_hash_tuple! { A }
|
||||
impl_hash_tuple! { A B }
|
||||
impl_hash_tuple! { A B C }
|
||||
impl_hash_tuple! { A B C D }
|
||||
impl_hash_tuple! { A B C D E }
|
||||
impl_hash_tuple! { A B C D E F }
|
||||
impl_hash_tuple! { A B C D E F G }
|
||||
impl_hash_tuple! { A B C D E F G H }
|
||||
impl_hash_tuple! { A B C D E F G H I }
|
||||
impl_hash_tuple! { A B C D E F G H I J }
|
||||
impl_hash_tuple! { A B C D E F G H I J K }
|
||||
impl_hash_tuple! { A B C D E F G H I J K L }
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: Hash> Hash for [T] {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.len().hash(state);
|
||||
Hash::hash_slice(self, state)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<'a, T: ?Sized + Hash> Hash for &'a T {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
(**self).hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<'a, T: ?Sized + Hash> Hash for &'a mut T {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
(**self).hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T> Hash for *const T {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
state.write_usize(*self as usize)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T> Hash for *mut T {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
state.write_usize(*self as usize)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<'a, T, B: ?Sized> Hash for Cow<'a, T, B>
|
||||
where B: Hash + ToOwned<T>
|
||||
{
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
Hash::hash(&**self, state)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,7 +15,9 @@
|
|||
use prelude::*;
|
||||
use default::Default;
|
||||
|
||||
use super::{Hasher, Writer};
|
||||
use super::Hasher;
|
||||
#[cfg(stage0)]
|
||||
use super::Writer;
|
||||
|
||||
/// An implementation of SipHash 2-4.
|
||||
///
|
||||
|
|
@ -30,6 +32,7 @@ use super::{Hasher, Writer};
|
|||
/// strong, this implementation has not been reviewed for such purposes.
|
||||
/// As such, all cryptographic uses of this implementation are strongly
|
||||
/// discouraged.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct SipHasher {
|
||||
k0: u64,
|
||||
k1: u64,
|
||||
|
|
@ -88,12 +91,14 @@ macro_rules! compress {
|
|||
impl SipHasher {
|
||||
/// Creates a new `SipHasher` with the two initial keys set to 0.
|
||||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn new() -> SipHasher {
|
||||
SipHasher::new_with_keys(0, 0)
|
||||
}
|
||||
|
||||
/// Creates a `SipHasher` that is keyed off the provided keys.
|
||||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn new_with_keys(key0: u64, key1: u64) -> SipHasher {
|
||||
let mut state = SipHasher {
|
||||
k0: key0,
|
||||
|
|
@ -114,10 +119,16 @@ impl SipHasher {
|
|||
#[unstable(feature = "hash")]
|
||||
#[deprecated(since = "1.0.0", reason = "renamed to finish")]
|
||||
pub fn result(&self) -> u64 { self.finish() }
|
||||
}
|
||||
|
||||
impl Writer for SipHasher {
|
||||
#[inline]
|
||||
fn reset(&mut self) {
|
||||
self.length = 0;
|
||||
self.v0 = self.k0 ^ 0x736f6d6570736575;
|
||||
self.v1 = self.k1 ^ 0x646f72616e646f6d;
|
||||
self.v2 = self.k0 ^ 0x6c7967656e657261;
|
||||
self.v3 = self.k1 ^ 0x7465646279746573;
|
||||
self.ntail = 0;
|
||||
}
|
||||
|
||||
fn write(&mut self, msg: &[u8]) {
|
||||
let length = msg.len();
|
||||
self.length += length;
|
||||
|
|
@ -164,16 +175,28 @@ impl Writer for SipHasher {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(stage0)]
|
||||
impl Writer for SipHasher {
|
||||
#[inline]
|
||||
fn write(&mut self, msg: &[u8]) {
|
||||
self.write(msg)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl Hasher for SipHasher {
|
||||
#[cfg(stage0)]
|
||||
type Output = u64;
|
||||
|
||||
#[cfg(stage0)]
|
||||
fn reset(&mut self) {
|
||||
self.length = 0;
|
||||
self.v0 = self.k0 ^ 0x736f6d6570736575;
|
||||
self.v1 = self.k1 ^ 0x646f72616e646f6d;
|
||||
self.v2 = self.k0 ^ 0x6c7967656e657261;
|
||||
self.v3 = self.k1 ^ 0x7465646279746573;
|
||||
self.ntail = 0;
|
||||
self.reset();
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[cfg(not(stage0))]
|
||||
fn write(&mut self, msg: &[u8]) {
|
||||
self.write(msg)
|
||||
}
|
||||
|
||||
fn finish(&self) -> u64 {
|
||||
|
|
@ -199,6 +222,7 @@ impl Hasher for SipHasher {
|
|||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl Clone for SipHasher {
|
||||
#[inline]
|
||||
fn clone(&self) -> SipHasher {
|
||||
|
|
@ -216,6 +240,7 @@ impl Clone for SipHasher {
|
|||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl Default for SipHasher {
|
||||
fn default() -> SipHasher {
|
||||
SipHasher::new()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue