(index<- ) ./libstd/hash/mod.rs
git branch: * master 5200215 auto merge of #14035 : alexcrichton/rust/experimental, r=huonw
modified: Fri May 9 13:02:28 2014
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 /*!
12 * Generic hashing support.
13 *
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)]`:
16 *
17 * # Example
18 *
19 * ```rust
20 * use std::hash;
21 * use std::hash::Hash;
22 *
23 * #[deriving(Hash)]
24 * struct Person {
25 * id: uint,
26 * name: ~str,
27 * phone: u64,
28 * }
29 *
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 };
32 *
33 * assert!(hash::hash(&person1) != hash::hash(&person2));
34 * ```
35 *
36 * If you need more control over how a value is hashed, you need to implement
37 * the trait `Hash`:
38 *
39 * ```rust
40 * use std::hash;
41 * use std::hash::Hash;
42 * use std::hash::sip::SipState;
43 *
44 * struct Person {
45 * id: uint,
46 * name: ~str,
47 * phone: u64,
48 * }
49 *
50 * impl Hash for Person {
51 * fn hash(&self, state: &mut SipState) {
52 * self.id.hash(state);
53 * self.phone.hash(state);
54 * }
55 * }
56 *
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 };
59 *
60 * assert!(hash::hash(&person1) == hash::hash(&person2));
61 * ```
62 */
63
64 #![allow(unused_must_use)]
65
66 use container::Container;
67 use intrinsics::TypeId;
68 use io::Writer;
69 use iter::Iterator;
70 use option::{Option, Some, None};
71 use owned::Box;
72 use rc::Rc;
73 use result::{Result, Ok, Err};
74 use slice::{Vector, ImmutableVector};
75 use str::{Str, StrSlice};
76 use vec::Vec;
77
78 /// Reexport the `sip::hash` function as our default hasher.
79 pub use hash = self::sip::hash;
80
81 pub mod sip;
82
83 /// A trait that represents a hashable type. The `S` type parameter is an
84 /// abstract hash state that is used by the `Hash` to compute the hash.
85 /// It defaults to `std::hash::sip::SipState`.
86 pub trait Hash<S = sip::SipState> {
87 /// Compute a hash of the value.
88 fn hash(&self, state: &mut S);
89 }
90
91 /// A trait that computes a hash for a value. The main users of this trait are
92 /// containers like `HashMap`, which need a generic way hash multiple types.
93 pub trait Hasher<S> {
94 /// Compute a hash of the value.
95 fn hash<T: Hash<S>>(&self, value: &T) -> u64;
96 }
97
98 //////////////////////////////////////////////////////////////////////////////
99
100 macro_rules! impl_hash(
101 ( $( $ty:ty => $method:ident;)* ) => (
102 $(
103 impl<S: Writer> Hash<S> for $ty {
104 #[inline]
105 fn hash(&self, state: &mut S) {
106 state.$method(*self);
107 }
108 }
109 )*
110 )
111 )
112
113 impl_hash!(
114 u8 => write_u8;
115 u16 => write_le_u16;
116 u32 => write_le_u32;
117 u64 => write_le_u64;
118 uint => write_le_uint;
119 i8 => write_i8;
120 i16 => write_le_i16;
121 i32 => write_le_i32;
122 i64 => write_le_i64;
123 int => write_le_int;
124 )
125
126 impl<S: Writer> Hash<S> for bool {
127 #[inline]
128 fn hash(&self, state: &mut S) {
129 (*self as u8).hash(state);
130 }
131 }
132
133 impl<S: Writer> Hash<S> for char {
134 #[inline]
135 fn hash(&self, state: &mut S) {
136 (*self as u32).hash(state);
137 }
138 }
139
140 impl<'a, S: Writer> Hash<S> for &'a str {
141 #[inline]
142 fn hash(&self, state: &mut S) {
143 state.write(self.as_bytes());
144 state.write_u8(0xFF);
145 }
146 }
147
148 impl<S: Writer> Hash<S> for ~str {
149 #[inline]
150 fn hash(&self, state: &mut S) {
151 self.as_slice().hash(state);
152 }
153 }
154
155 macro_rules! impl_hash_tuple(
156 () => (
157 impl<S: Writer> Hash<S> for () {
158 #[inline]
159 fn hash(&self, state: &mut S) {
160 state.write([]);
161 }
162 }
163 );
164
165 ($A:ident $($B:ident)*) => (
166 impl<
167 S: Writer,
168 $A: Hash<S> $(, $B: Hash<S>)*
169 > Hash<S> for ($A, $($B),*) {
170 #[inline]
171 fn hash(&self, state: &mut S) {
172 match *self {
173 (ref $A, $(ref $B),*) => {
174 $A.hash(state);
175 $(
176 $B.hash(state);
177 )*
178 }
179 }
180 }
181 }
182
183 impl_hash_tuple!($($B)*)
184 );
185 )
186
187 impl_hash_tuple!(a0 a1 a2 a3 a4 a5 a6 a7)
188
189 impl<'a, S: Writer, T: Hash<S>> Hash<S> for &'a [T] {
190 #[inline]
191 fn hash(&self, state: &mut S) {
192 self.len().hash(state);
193 for elt in self.iter() {
194 elt.hash(state);
195 }
196 }
197 }
198
199
200 impl<'a, S: Writer, T: Hash<S>> Hash<S> for &'a mut [T] {
201 #[inline]
202 fn hash(&self, state: &mut S) {
203 self.as_slice().hash(state);
204 }
205 }
206
207 impl<S: Writer, T: Hash<S>> Hash<S> for ~[T] {
208 #[inline]
209 fn hash(&self, state: &mut S) {
210 self.as_slice().hash(state);
211 }
212 }
213
214 impl<S: Writer, T: Hash<S>> Hash<S> for Vec<T> {
215 #[inline]
216 fn hash(&self, state: &mut S) {
217 self.as_slice().hash(state);
218 }
219 }
220
221 impl<'a, S: Writer, T: Hash<S>> Hash<S> for &'a T {
222 #[inline]
223 fn hash(&self, state: &mut S) {
224 (**self).hash(state);
225 }
226 }
227
228 impl<'a, S: Writer, T: Hash<S>> Hash<S> for &'a mut T {
229 #[inline]
230 fn hash(&self, state: &mut S) {
231 (**self).hash(state);
232 }
233 }
234
235 impl<S: Writer, T: Hash<S>> Hash<S> for Box<T> {
236 #[inline]
237 fn hash(&self, state: &mut S) {
238 (**self).hash(state);
239 }
240 }
241
242 impl<S: Writer, T: Hash<S>> Hash<S> for @T {
243 #[inline]
244 fn hash(&self, state: &mut S) {
245 (**self).hash(state);
246 }
247 }
248
249 impl<S: Writer, T: Hash<S>> Hash<S> for Rc<T> {
250 #[inline]
251 fn hash(&self, state: &mut S) {
252 (**self).hash(state);
253 }
254 }
255
256 impl<S: Writer, T: Hash<S>> Hash<S> for Option<T> {
257 #[inline]
258 fn hash(&self, state: &mut S) {
259 match *self {
260 Some(ref x) => {
261 0u8.hash(state);
262 x.hash(state);
263 }
264 None => {
265 1u8.hash(state);
266 }
267 }
268 }
269 }
270
271 impl<S: Writer, T> Hash<S> for *T {
272 #[inline]
273 fn hash(&self, state: &mut S) {
274 // NB: raw-pointer Hash does _not_ dereference
275 // to the target; it just gives you the pointer-bytes.
276 (*self as uint).hash(state);
277 }
278 }
279
280 impl<S: Writer, T> Hash<S> for *mut T {
281 #[inline]
282 fn hash(&self, state: &mut S) {
283 // NB: raw-pointer Hash does _not_ dereference
284 // to the target; it just gives you the pointer-bytes.
285 (*self as uint).hash(state);
286 }
287 }
288
289 impl<S: Writer> Hash<S> for TypeId {
290 #[inline]
291 fn hash(&self, state: &mut S) {
292 self.hash().hash(state)
293 }
294 }
295
296 impl<S: Writer, T: Hash<S>, U: Hash<S>> Hash<S> for Result<T, U> {
297 #[inline]
298 fn hash(&self, state: &mut S) {
299 match *self {
300 Ok(ref t) => { 1u.hash(state); t.hash(state); }
301 Err(ref t) => { 2u.hash(state); t.hash(state); }
302 }
303 }
304 }
305
306 //////////////////////////////////////////////////////////////////////////////
307
308 #[cfg(test)]
309 mod tests {
310 use cast;
311 use io::{IoResult, Writer};
312 use iter::{Iterator};
313 use option::{Some, None};
314 use result::Ok;
315 use slice::ImmutableVector;
316
317 use super::{Hash, Hasher};
318
319 struct MyWriterHasher;
320
321 impl Hasher<MyWriter> for MyWriterHasher {
322 fn hash<T: Hash<MyWriter>>(&self, value: &T) -> u64 {
323 let mut state = MyWriter { hash: 0 };
324 value.hash(&mut state);
325 state.hash
326 }
327 }
328
329 struct MyWriter {
330 hash: u64,
331 }
332
333 impl Writer for MyWriter {
334 // Most things we'll just add up the bytes.
335 fn write(&mut self, buf: &[u8]) -> IoResult<()> {
336 for byte in buf.iter() {
337 self.hash += *byte as u64;
338 }
339 Ok(())
340 }
341 }
342
343 #[test]
344 fn test_writer_hasher() {
345 let hasher = MyWriterHasher;
346
347 assert_eq!(hasher.hash(&()), 0);
348
349 assert_eq!(hasher.hash(&5u8), 5);
350 assert_eq!(hasher.hash(&5u16), 5);
351 assert_eq!(hasher.hash(&5u32), 5);
352 assert_eq!(hasher.hash(&5u64), 5);
353 assert_eq!(hasher.hash(&5u), 5);
354
355 assert_eq!(hasher.hash(&5i8), 5);
356 assert_eq!(hasher.hash(&5i16), 5);
357 assert_eq!(hasher.hash(&5i32), 5);
358 assert_eq!(hasher.hash(&5i64), 5);
359 assert_eq!(hasher.hash(&5i), 5);
360
361 assert_eq!(hasher.hash(&false), 0);
362 assert_eq!(hasher.hash(&true), 1);
363
364 assert_eq!(hasher.hash(&'a'), 97);
365
366 assert_eq!(hasher.hash(&("a")), 97 + 0xFF);
367 assert_eq!(hasher.hash(& &[1u8, 2u8, 3u8]), 9);
368
369 unsafe {
370 let ptr: *int = cast::transmute(5);
371 assert_eq!(hasher.hash(&ptr), 5);
372 }
373
374 unsafe {
375 let ptr: *mut int = cast::transmute(5);
376 assert_eq!(hasher.hash(&ptr), 5);
377 }
378 }
379
380 struct Custom {
381 hash: u64
382 }
383
384 impl Hash<u64> for Custom {
385 fn hash(&self, state: &mut u64) {
386 *state = self.hash;
387 }
388 }
389
390 #[test]
391 fn test_custom_state() {
392 let custom = Custom { hash: 5 };
393 let mut state = 0;
394 custom.hash(&mut state);
395 assert_eq!(state, 5);
396 }
397 }