]> git.proxmox.com Git - rustc.git/blame - src/libcore/hash/mod.rs
Imported Upstream version 1.0.0~beta.3
[rustc.git] / src / libcore / hash / mod.rs
CommitLineData
1a4d82fc
JJ
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.
4//
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.
10
11//! Generic hashing support.
12//!
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 `#[derive(Hash)]`:
15//!
16//! # Examples
17//!
18//! ```rust
c34b1796 19//! # #![feature(hash)]
1a4d82fc
JJ
20//! use std::hash::{hash, Hash, SipHasher};
21//!
22//! #[derive(Hash)]
23//! struct Person {
c34b1796 24//! id: u32,
1a4d82fc
JJ
25//! name: String,
26//! phone: u64,
27//! }
28//!
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 };
31//!
32//! assert!(hash::<_, SipHasher>(&person1) != hash::<_, SipHasher>(&person2));
33//! ```
34//!
35//! If you need more control over how a value is hashed, you need to implement
36//! the trait `Hash`:
37//!
38//! ```rust
c34b1796 39//! # #![feature(hash)]
85aaf69f 40//! use std::hash::{hash, Hash, Hasher, SipHasher};
1a4d82fc
JJ
41//!
42//! struct Person {
c34b1796 43//! id: u32,
1a4d82fc
JJ
44//! name: String,
45//! phone: u64,
46//! }
47//!
85aaf69f
SL
48//! impl Hash for Person {
49//! fn hash<H: Hasher>(&self, state: &mut H) {
1a4d82fc
JJ
50//! self.id.hash(state);
51//! self.phone.hash(state);
52//! }
53//! }
54//!
55//! let person1 = Person { id: 5, name: "Janet".to_string(), phone: 555_666_7777 };
56//! let person2 = Person { id: 5, name: "Bob".to_string(), phone: 555_666_7777 };
57//!
58//! assert_eq!(hash::<_, SipHasher>(&person1), hash::<_, SipHasher>(&person2));
59//! ```
60
85aaf69f
SL
61#![stable(feature = "rust1", since = "1.0.0")]
62
63use prelude::*;
1a4d82fc 64
85aaf69f 65use mem;
1a4d82fc
JJ
66
67pub use self::sip::SipHasher;
68
69mod sip;
70
71/// A hashable type.
72///
73/// The `H` type parameter is an abstract hash state that is used by the `Hash`
c34b1796
AL
74/// to compute the hash.
75///
76/// If you are also implementing `Eq`, there is an additional property that
77/// is important:
78///
79/// ```text
80/// k1 == k2 -> hash(k1) == hash(k2)
81/// ```
82///
83/// In other words, if two keys are equal, their hashes should also be equal.
84/// `HashMap` and `HashSet` both rely on this behavior.
85aaf69f
SL
85#[stable(feature = "rust1", since = "1.0.0")]
86pub trait Hash {
1a4d82fc 87 /// Feeds this value into the state given, updating the hasher as necessary.
85aaf69f
SL
88 #[stable(feature = "rust1", since = "1.0.0")]
89 fn hash<H: Hasher>(&self, state: &mut H);
90
91 /// Feeds a slice of this type into the state provided.
92 #[unstable(feature = "hash", reason = "module was recently redesigned")]
93 fn hash_slice<H: Hasher>(data: &[Self], state: &mut H) where Self: Sized {
94 for piece in data {
95 piece.hash(state);
96 }
97 }
1a4d82fc
JJ
98}
99
1a4d82fc 100/// A trait which represents the ability to hash an arbitrary stream of bytes.
85aaf69f 101#[stable(feature = "rust1", since = "1.0.0")]
1a4d82fc 102pub trait Hasher {
85aaf69f 103 /// Completes a round of hashing, producing the output hash generated.
c34b1796 104 #[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
105 fn finish(&self) -> u64;
106
107 /// Writes some data into this `Hasher`
85aaf69f
SL
108 #[stable(feature = "rust1", since = "1.0.0")]
109 fn write(&mut self, bytes: &[u8]);
110
111 /// Write a single `u8` into this hasher
85aaf69f
SL
112 #[inline]
113 #[unstable(feature = "hash", reason = "module was recently redesigned")]
114 fn write_u8(&mut self, i: u8) { self.write(&[i]) }
115 /// Write a single `u16` into this hasher.
85aaf69f
SL
116 #[inline]
117 #[unstable(feature = "hash", reason = "module was recently redesigned")]
118 fn write_u16(&mut self, i: u16) {
119 self.write(&unsafe { mem::transmute::<_, [u8; 2]>(i) })
120 }
121 /// Write a single `u32` into this hasher.
85aaf69f
SL
122 #[inline]
123 #[unstable(feature = "hash", reason = "module was recently redesigned")]
124 fn write_u32(&mut self, i: u32) {
125 self.write(&unsafe { mem::transmute::<_, [u8; 4]>(i) })
126 }
127 /// Write a single `u64` into this hasher.
85aaf69f
SL
128 #[inline]
129 #[unstable(feature = "hash", reason = "module was recently redesigned")]
130 fn write_u64(&mut self, i: u64) {
131 self.write(&unsafe { mem::transmute::<_, [u8; 8]>(i) })
132 }
133 /// Write a single `usize` into this hasher.
85aaf69f
SL
134 #[inline]
135 #[unstable(feature = "hash", reason = "module was recently redesigned")]
136 fn write_usize(&mut self, i: usize) {
137 if cfg!(target_pointer_width = "32") {
138 self.write_u32(i as u32)
139 } else {
140 self.write_u64(i as u64)
141 }
142 }
143
144 /// Write a single `i8` into this hasher.
85aaf69f
SL
145 #[inline]
146 #[unstable(feature = "hash", reason = "module was recently redesigned")]
147 fn write_i8(&mut self, i: i8) { self.write_u8(i as u8) }
148 /// Write a single `i16` into this hasher.
85aaf69f
SL
149 #[inline]
150 #[unstable(feature = "hash", reason = "module was recently redesigned")]
151 fn write_i16(&mut self, i: i16) { self.write_u16(i as u16) }
152 /// Write a single `i32` into this hasher.
85aaf69f
SL
153 #[inline]
154 #[unstable(feature = "hash", reason = "module was recently redesigned")]
155 fn write_i32(&mut self, i: i32) { self.write_u32(i as u32) }
156 /// Write a single `i64` into this hasher.
85aaf69f
SL
157 #[inline]
158 #[unstable(feature = "hash", reason = "module was recently redesigned")]
159 fn write_i64(&mut self, i: i64) { self.write_u64(i as u64) }
160 /// Write a single `isize` into this hasher.
85aaf69f
SL
161 #[inline]
162 #[unstable(feature = "hash", reason = "module was recently redesigned")]
163 fn write_isize(&mut self, i: isize) { self.write_usize(i as usize) }
1a4d82fc
JJ
164}
165
1a4d82fc
JJ
166/// Hash a value with the default SipHasher algorithm (two initial keys of 0).
167///
168/// The specified value will be hashed with this hasher and then the resulting
169/// hash will be returned.
85aaf69f
SL
170#[unstable(feature = "hash", reason = "module was recently redesigned")]
171pub fn hash<T: Hash, H: Hasher + Default>(value: &T) -> u64 {
172 let mut h: H = Default::default();
173 value.hash(&mut h);
174 h.finish()
175}
176
1a4d82fc
JJ
177//////////////////////////////////////////////////////////////////////////////
178
1a4d82fc
JJ
179mod impls {
180 use prelude::*;
181
85aaf69f
SL
182 use slice;
183 use super::*;
1a4d82fc 184
85aaf69f
SL
185 macro_rules! impl_write {
186 ($(($ty:ident, $meth:ident),)*) => {$(
187 #[stable(feature = "rust1", since = "1.0.0")]
188 impl Hash for $ty {
189 fn hash<H: Hasher>(&self, state: &mut H) {
190 state.$meth(*self)
191 }
192
193 fn hash_slice<H: Hasher>(data: &[$ty], state: &mut H) {
c34b1796
AL
194 // FIXME(#23542) Replace with type ascription.
195 #![allow(trivial_casts)]
9346a6ac 196 let newlen = data.len() * ::$ty::BYTES;
85aaf69f
SL
197 let ptr = data.as_ptr() as *const u8;
198 state.write(unsafe { slice::from_raw_parts(ptr, newlen) })
1a4d82fc
JJ
199 }
200 }
85aaf69f 201 )*}
1a4d82fc
JJ
202 }
203
85aaf69f
SL
204 impl_write! {
205 (u8, write_u8),
206 (u16, write_u16),
207 (u32, write_u32),
208 (u64, write_u64),
209 (usize, write_usize),
210 (i8, write_i8),
211 (i16, write_i16),
212 (i32, write_i32),
213 (i64, write_i64),
214 (isize, write_isize),
215 }
1a4d82fc 216
85aaf69f
SL
217 #[stable(feature = "rust1", since = "1.0.0")]
218 impl Hash for bool {
219 fn hash<H: Hasher>(&self, state: &mut H) {
220 state.write_u8(*self as u8)
1a4d82fc
JJ
221 }
222 }
223
85aaf69f
SL
224 #[stable(feature = "rust1", since = "1.0.0")]
225 impl Hash for char {
226 fn hash<H: Hasher>(&self, state: &mut H) {
227 state.write_u32(*self as u32)
1a4d82fc
JJ
228 }
229 }
230
85aaf69f
SL
231 #[stable(feature = "rust1", since = "1.0.0")]
232 impl Hash for str {
233 fn hash<H: Hasher>(&self, state: &mut H) {
1a4d82fc 234 state.write(self.as_bytes());
85aaf69f 235 state.write_u8(0xff)
1a4d82fc
JJ
236 }
237 }
238
239 macro_rules! impl_hash_tuple {
240 () => (
85aaf69f
SL
241 #[stable(feature = "rust1", since = "1.0.0")]
242 impl Hash for () {
243 fn hash<H: Hasher>(&self, _state: &mut H) {}
1a4d82fc
JJ
244 }
245 );
246
247 ( $($name:ident)+) => (
85aaf69f
SL
248 #[stable(feature = "rust1", since = "1.0.0")]
249 impl<$($name: Hash),*> Hash for ($($name,)*) {
1a4d82fc 250 #[allow(non_snake_case)]
85aaf69f
SL
251 fn hash<S: Hasher>(&self, state: &mut S) {
252 let ($(ref $name,)*) = *self;
253 $($name.hash(state);)*
1a4d82fc
JJ
254 }
255 }
256 );
257 }
258
259 impl_hash_tuple! {}
260 impl_hash_tuple! { A }
261 impl_hash_tuple! { A B }
262 impl_hash_tuple! { A B C }
263 impl_hash_tuple! { A B C D }
264 impl_hash_tuple! { A B C D E }
265 impl_hash_tuple! { A B C D E F }
266 impl_hash_tuple! { A B C D E F G }
267 impl_hash_tuple! { A B C D E F G H }
268 impl_hash_tuple! { A B C D E F G H I }
269 impl_hash_tuple! { A B C D E F G H I J }
270 impl_hash_tuple! { A B C D E F G H I J K }
271 impl_hash_tuple! { A B C D E F G H I J K L }
272
85aaf69f
SL
273 #[stable(feature = "rust1", since = "1.0.0")]
274 impl<T: Hash> Hash for [T] {
275 fn hash<H: Hasher>(&self, state: &mut H) {
1a4d82fc 276 self.len().hash(state);
85aaf69f 277 Hash::hash_slice(self, state)
1a4d82fc
JJ
278 }
279 }
280
281
85aaf69f
SL
282 #[stable(feature = "rust1", since = "1.0.0")]
283 impl<'a, T: ?Sized + Hash> Hash for &'a T {
284 fn hash<H: Hasher>(&self, state: &mut H) {
1a4d82fc
JJ
285 (**self).hash(state);
286 }
287 }
288
85aaf69f
SL
289 #[stable(feature = "rust1", since = "1.0.0")]
290 impl<'a, T: ?Sized + Hash> Hash for &'a mut T {
291 fn hash<H: Hasher>(&self, state: &mut H) {
1a4d82fc
JJ
292 (**self).hash(state);
293 }
294 }
295
85aaf69f
SL
296 #[stable(feature = "rust1", since = "1.0.0")]
297 impl<T> Hash for *const T {
298 fn hash<H: Hasher>(&self, state: &mut H) {
299 state.write_usize(*self as usize)
1a4d82fc
JJ
300 }
301 }
302
85aaf69f
SL
303 #[stable(feature = "rust1", since = "1.0.0")]
304 impl<T> Hash for *mut T {
305 fn hash<H: Hasher>(&self, state: &mut H) {
306 state.write_usize(*self as usize)
1a4d82fc
JJ
307 }
308 }
309}