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.
12 * Generic hashing support.
14 * This module provides a generic way to compute the hash of a value. The
15 * simplest way to make a type hashable is to use `#[deriving(Hash)]`:
21 * use std::hash::Hash;
30 * let person1 = Person { id: 5, name: "Janet".to_owned(), phone: 555_666_7777 };
31 * let person2 = Person { id: 5, name: "Bob".to_owned(), phone: 555_666_7777 };
33 * assert!(hash::hash(&person1) != hash::hash(&person2));
36 * If you need more control over how a value is hashed, you need to implement
41 * use std::hash::Hash;
42 * use std::hash::sip::SipState;
50 * impl Hash for Person {
51 * fn hash(&self, state: &mut SipState) {
52 * self.id.hash(state);
53 * self.phone.hash(state);
57 * let person1 = Person { id: 5, name: "Janet".to_owned(), phone: 555_666_7777 };
58 * let person2 = Person { id: 5, name: "Bob".to_owned(), phone: 555_666_7777 };
60 * assert!(hash::hash(&person1) == hash::hash(&person2));
64 #![allow(unused_must_use)]
66 use container::Container;
67 use intrinsics::TypeId;
69 use option::{Option, Some, None};
72 use result::{Result, Ok, Err};
73 use slice::{Vector, ImmutableVector};
74 use str::{Str, StrSlice};
77 /// Reexport the `sip::hash` function as our default hasher.
78 pub use hash = self::sip::hash;
80 pub use Writer = io::Writer;
84 /// A trait that represents a hashable type. The `S` type parameter is an
85 /// abstract hash state that is used by the `Hash` to compute the hash.
86 /// It defaults to `std::hash::sip::SipState`.
87 pub trait Hash<S = sip::SipState> {
88 /// Compute a hash of the value.
89 fn hash(&self, state: &mut S);
92 /// A trait that computes a hash for a value. The main users of this trait are
93 /// containers like `HashMap`, which need a generic way hash multiple types.
95 /// Compute a hash of the value.
96 fn hash<T: Hash<S>>(&self, value: &T) -> u64;
99 //////////////////////////////////////////////////////////////////////////////
101 macro_rules! impl_hash(
102 ( $( $ty:ty => $method:ident;)* ) => (
104 impl<S: Writer> Hash<S> for $ty {
106 fn hash(&self, state: &mut S) {
107 state.$method(*self);
119 uint => write_le_uint;
127 impl<S: Writer> Hash<S> for bool {
129 fn hash(&self, state: &mut S) {
130 (*self as u8).hash(state);
134 impl<S: Writer> Hash<S> for char {
136 fn hash(&self, state: &mut S) {
137 (*self as u32).hash(state);
141 impl<'a, S: Writer> Hash<S> for &'a str {
143 fn hash(&self, state: &mut S) {
144 state.write(self.as_bytes());
145 state.write_u8(0xFF);
149 macro_rules! impl_hash_tuple(
151 impl<S: Writer> Hash<S> for () {
153 fn hash(&self, state: &mut S) {
159 ($A:ident $($B:ident)*) => (
162 $A: Hash<S> $(, $B: Hash<S>)*
163 > Hash<S> for ($A, $($B),*) {
165 fn hash(&self, state: &mut S) {
167 (ref $A, $(ref $B),*) => {
177 impl_hash_tuple!($($B)*)
181 impl_hash_tuple!(a0 a1 a2 a3 a4 a5 a6 a7)
183 impl<'a, S: Writer, T: Hash<S>> Hash<S> for &'a [T] {
185 fn hash(&self, state: &mut S) {
186 self.len().hash(state);
187 for elt in self.iter() {
194 impl<'a, S: Writer, T: Hash<S>> Hash<S> for &'a mut [T] {
196 fn hash(&self, state: &mut S) {
197 self.as_slice().hash(state);
201 impl<S: Writer, T: Hash<S>> Hash<S> for ~[T] {
203 fn hash(&self, state: &mut S) {
204 self.as_slice().hash(state);
208 impl<S: Writer, T: Hash<S>> Hash<S> for Vec<T> {
210 fn hash(&self, state: &mut S) {
211 self.as_slice().hash(state);
215 impl<'a, S: Writer, T: Hash<S>> Hash<S> for &'a T {
217 fn hash(&self, state: &mut S) {
218 (**self).hash(state);
222 impl<'a, S: Writer, T: Hash<S>> Hash<S> for &'a mut T {
224 fn hash(&self, state: &mut S) {
225 (**self).hash(state);
229 impl<S: Writer, T: Hash<S>> Hash<S> for Box<T> {
231 fn hash(&self, state: &mut S) {
232 (**self).hash(state);
236 impl<S: Writer, T: Hash<S>> Hash<S> for @T {
238 fn hash(&self, state: &mut S) {
239 (**self).hash(state);
243 impl<S: Writer, T: Hash<S>> Hash<S> for Rc<T> {
245 fn hash(&self, state: &mut S) {
246 (**self).hash(state);
250 impl<S: Writer, T: Hash<S>> Hash<S> for Option<T> {
252 fn hash(&self, state: &mut S) {
265 impl<S: Writer, T> Hash<S> for *T {
267 fn hash(&self, state: &mut S) {
268 // NB: raw-pointer Hash does _not_ dereference
269 // to the target; it just gives you the pointer-bytes.
270 (*self as uint).hash(state);
274 impl<S: Writer, T> Hash<S> for *mut T {
276 fn hash(&self, state: &mut S) {
277 // NB: raw-pointer Hash does _not_ dereference
278 // to the target; it just gives you the pointer-bytes.
279 (*self as uint).hash(state);
283 impl<S: Writer> Hash<S> for TypeId {
285 fn hash(&self, state: &mut S) {
286 self.hash().hash(state)
290 impl<S: Writer, T: Hash<S>, U: Hash<S>> Hash<S> for Result<T, U> {
292 fn hash(&self, state: &mut S) {
294 Ok(ref t) => { 1u.hash(state); t.hash(state); }
295 Err(ref t) => { 2u.hash(state); t.hash(state); }
300 //////////////////////////////////////////////////////////////////////////////
305 use io::{IoResult, Writer};
306 use iter::{Iterator};
307 use option::{Some, None};
309 use slice::ImmutableVector;
311 use super::{Hash, Hasher};
313 struct MyWriterHasher;
315 impl Hasher<MyWriter> for MyWriterHasher {
316 fn hash<T: Hash<MyWriter>>(&self, value: &T) -> u64 {
317 let mut state = MyWriter { hash: 0 };
318 value.hash(&mut state);
327 impl Writer for MyWriter {
328 // Most things we'll just add up the bytes.
329 fn write(&mut self, buf: &[u8]) -> IoResult<()> {
330 for byte in buf.iter() {
331 self.hash += *byte as u64;
338 fn test_writer_hasher() {
339 let hasher = MyWriterHasher;
341 assert_eq!(hasher.hash(&()), 0);
343 assert_eq!(hasher.hash(&5u8), 5);
344 assert_eq!(hasher.hash(&5u16), 5);
345 assert_eq!(hasher.hash(&5u32), 5);
346 assert_eq!(hasher.hash(&5u64), 5);
347 assert_eq!(hasher.hash(&5u), 5);
349 assert_eq!(hasher.hash(&5i8), 5);
350 assert_eq!(hasher.hash(&5i16), 5);
351 assert_eq!(hasher.hash(&5i32), 5);
352 assert_eq!(hasher.hash(&5i64), 5);
353 assert_eq!(hasher.hash(&5i), 5);
355 assert_eq!(hasher.hash(&false), 0);
356 assert_eq!(hasher.hash(&true), 1);
358 assert_eq!(hasher.hash(&'a'), 97);
360 assert_eq!(hasher.hash(&("a")), 97 + 0xFF);
361 assert_eq!(hasher.hash(& &[1u8, 2u8, 3u8]), 9);
364 let ptr: *int = mem::transmute(5);
365 assert_eq!(hasher.hash(&ptr), 5);
369 let ptr: *mut int = mem::transmute(5);
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);