1 // Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 //! Generic hashing support.
13 //! This module provides a generic way to compute the hash of a value. The
14 //! simplest way to make a type hashable is to use `#[deriving(Hash)]`:
20 //! use std::hash::Hash;
29 //! let person1 = Person { id: 5, name: "Janet".to_string(), phone: 555_666_7777 };
30 //! let person2 = Person { id: 5, name: "Bob".to_string(), phone: 555_666_7777 };
32 //! assert!(hash::hash(&person1) != hash::hash(&person2));
35 //! If you need more control over how a value is hashed, you need to implement
40 //! use std::hash::Hash;
41 //! use std::hash::sip::SipState;
49 //! impl Hash for Person {
50 //! fn hash(&self, state: &mut SipState) {
51 //! self.id.hash(state);
52 //! self.phone.hash(state);
56 //! let person1 = Person { id: 5, name: "Janet".to_string(), phone: 555_666_7777 };
57 //! let person2 = Person { id: 5, name: "Bob".to_string(), phone: 555_666_7777 };
59 //! assert!(hash::hash(&person1) == hash::hash(&person2));
62 #![allow(unused_must_use)]
66 use alloc::boxed::Box;
68 use core::borrow::{Cow, ToOwned};
69 use core::intrinsics::TypeId;
75 /// Reexport the `sip::hash` function as our default hasher.
76 pub use self::sip::hash as hash;
80 /// A hashable type. The `S` type parameter is an abstract hash state that is
81 /// used by the `Hash` to compute the hash. It defaults to
82 /// `std::hash::sip::SipState`.
83 pub trait Hash<S = sip::SipState> for Sized? {
84 /// Computes the hash of a value.
85 fn hash(&self, state: &mut S);
88 /// A trait that computes a hash for a value. The main users of this trait are
89 /// containers like `HashMap`, which need a generic way hash multiple types.
91 /// Compute the hash of a value.
92 fn hash<Sized? T: Hash<S>>(&self, value: &T) -> u64;
96 fn write(&mut self, bytes: &[u8]);
99 //////////////////////////////////////////////////////////////////////////////
101 macro_rules! impl_hash {
102 ($ty:ident, $uty:ident) => {
103 impl<S: Writer> Hash<S> for $ty {
105 fn hash(&self, state: &mut S) {
106 let a: [u8, ..::core::$ty::BYTES] = unsafe {
107 mem::transmute((*self as $uty).to_le() as $ty)
109 state.write(a.as_slice())
119 impl_hash!(uint, uint)
124 impl_hash!(int, uint)
126 impl<S: Writer> Hash<S> for bool {
128 fn hash(&self, state: &mut S) {
129 (*self as u8).hash(state);
133 impl<S: Writer> Hash<S> for char {
135 fn hash(&self, state: &mut S) {
136 (*self as u32).hash(state);
140 impl<S: Writer> Hash<S> for str {
142 fn hash(&self, state: &mut S) {
143 state.write(self.as_bytes());
148 macro_rules! impl_hash_tuple(
150 impl<S: Writer> Hash<S> for () {
152 fn hash(&self, state: &mut S) {
158 ( $($name:ident)+) => (
159 impl<S: Writer, $($name: Hash<S>),*> Hash<S> for ($($name,)*) {
161 #[allow(non_snake_case)]
162 fn hash(&self, state: &mut S) {
164 ($(ref $name,)*) => {
177 impl_hash_tuple!(A B)
178 impl_hash_tuple!(A B C)
179 impl_hash_tuple!(A B C D)
180 impl_hash_tuple!(A B C D E)
181 impl_hash_tuple!(A B C D E F)
182 impl_hash_tuple!(A B C D E F G)
183 impl_hash_tuple!(A B C D E F G H)
184 impl_hash_tuple!(A B C D E F G H I)
185 impl_hash_tuple!(A B C D E F G H I J)
186 impl_hash_tuple!(A B C D E F G H I J K)
187 impl_hash_tuple!(A B C D E F G H I J K L)
189 impl<S: Writer, T: Hash<S>> Hash<S> for [T] {
191 fn hash(&self, state: &mut S) {
192 self.len().hash(state);
193 for elt in self.iter() {
200 impl<S: Writer, T: Hash<S>> Hash<S> for Vec<T> {
202 fn hash(&self, state: &mut S) {
203 self.as_slice().hash(state);
207 impl<'a, S: Writer, Sized? T: Hash<S>> Hash<S> for &'a T {
209 fn hash(&self, state: &mut S) {
210 (**self).hash(state);
214 impl<'a, S: Writer, Sized? T: Hash<S>> Hash<S> for &'a mut T {
216 fn hash(&self, state: &mut S) {
217 (**self).hash(state);
221 impl<S: Writer, Sized? T: Hash<S>> Hash<S> for Box<T> {
223 fn hash(&self, state: &mut S) {
224 (**self).hash(state);
228 // FIXME (#18248) Make `T` `Sized?`
229 impl<S: Writer, T: Hash<S>> Hash<S> for Rc<T> {
231 fn hash(&self, state: &mut S) {
232 (**self).hash(state);
236 impl<S: Writer, T: Hash<S>> Hash<S> for Option<T> {
238 fn hash(&self, state: &mut S) {
251 impl<S: Writer, T> Hash<S> for *const T {
253 fn hash(&self, state: &mut S) {
254 // NB: raw-pointer Hash does _not_ dereference
255 // to the target; it just gives you the pointer-bytes.
256 (*self as uint).hash(state);
260 impl<S: Writer, T> Hash<S> for *mut T {
262 fn hash(&self, state: &mut S) {
263 // NB: raw-pointer Hash does _not_ dereference
264 // to the target; it just gives you the pointer-bytes.
265 (*self as uint).hash(state);
269 impl<S: Writer> Hash<S> for TypeId {
271 fn hash(&self, state: &mut S) {
272 self.hash().hash(state)
276 impl<S: Writer, T: Hash<S>, U: Hash<S>> Hash<S> for Result<T, U> {
278 fn hash(&self, state: &mut S) {
280 Ok(ref t) => { 1u.hash(state); t.hash(state); }
281 Err(ref t) => { 2u.hash(state); t.hash(state); }
286 impl<'a, T, Sized? B, S> Hash<S> for Cow<'a, T, B> where B: Hash<S> + ToOwned<T> {
288 fn hash(&self, state: &mut S) {
289 Hash::hash(&**self, state)
293 //////////////////////////////////////////////////////////////////////////////
297 use core::kinds::Sized;
300 use slice::SlicePrelude;
301 use super::{Hash, Hasher, Writer};
303 struct MyWriterHasher;
305 impl Hasher<MyWriter> for MyWriterHasher {
306 fn hash<Sized? T: Hash<MyWriter>>(&self, value: &T) -> u64 {
307 let mut state = MyWriter { hash: 0 };
308 value.hash(&mut state);
317 impl Writer for MyWriter {
318 // Most things we'll just add up the bytes.
319 fn write(&mut self, buf: &[u8]) {
320 for byte in buf.iter() {
321 self.hash += *byte as u64;
327 fn test_writer_hasher() {
328 use alloc::boxed::Box;
330 let hasher = MyWriterHasher;
332 assert_eq!(hasher.hash(&()), 0);
334 assert_eq!(hasher.hash(&5u8), 5);
335 assert_eq!(hasher.hash(&5u16), 5);
336 assert_eq!(hasher.hash(&5u32), 5);
337 assert_eq!(hasher.hash(&5u64), 5);
338 assert_eq!(hasher.hash(&5u), 5);
340 assert_eq!(hasher.hash(&5i8), 5);
341 assert_eq!(hasher.hash(&5i16), 5);
342 assert_eq!(hasher.hash(&5i32), 5);
343 assert_eq!(hasher.hash(&5i64), 5);
344 assert_eq!(hasher.hash(&5i), 5);
346 assert_eq!(hasher.hash(&false), 0);
347 assert_eq!(hasher.hash(&true), 1);
349 assert_eq!(hasher.hash(&'a'), 97);
352 assert_eq!(hasher.hash(& s), 97 + 0xFF);
353 // FIXME (#18283) Enable test
354 //let s: Box<str> = box "a";
355 //assert_eq!(hasher.hash(& s), 97 + 0xFF);
356 let cs: &[u8] = &[1u8, 2u8, 3u8];
357 assert_eq!(hasher.hash(& cs), 9);
358 let cs: Box<[u8]> = box [1u8, 2u8, 3u8];
359 assert_eq!(hasher.hash(& cs), 9);
361 // FIXME (#18248) Add tests for hashing Rc<str> and Rc<[T]>
364 let ptr: *const int = mem::transmute(5i);
365 assert_eq!(hasher.hash(&ptr), 5);
369 let ptr: *mut int = mem::transmute(5i);
370 assert_eq!(hasher.hash(&ptr), 5);
378 impl Hash<u64> for Custom {
379 fn hash(&self, state: &mut u64) {
385 fn test_custom_state() {
386 let custom = Custom { hash: 5 };
388 custom.hash(&mut state);
389 assert_eq!(state, 5);