(index<- ) ./libstd/hash.rs
1 // Copyright 2012 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 * Implementation of SipHash 2-4
13 *
14 * See: http://131002.net/siphash/
15 *
16 * Consider this as a main "general-purpose" hash for all hashtables: it
17 * runs at good speed (competitive with spooky and city) and permits
18 * cryptographically strong _keyed_ hashing. Key your hashtables from a
19 * CPRNG like rand::rng.
20 */
21
22 #[allow(missing_doc)];
23
24 use container::Container;
25 use iter::Iterator;
26 use option::{Some, None};
27 use rt::io::Writer;
28 use str::OwnedStr;
29 use to_bytes::IterBytes;
30 use vec::ImmutableVector;
31 use num::ToStrRadix;
32
33 // Alias `SipState` to `State`.
34 pub use State = hash::SipState;
35
36 /**
37 * Types that can meaningfully be hashed should implement this.
38 *
39 * Note that this trait is likely to change somewhat as it is
40 * closely related to `to_bytes::IterBytes` and in almost all
41 * cases presently the two are (and must be) used together.
42 *
43 * In general, most types only need to implement `IterBytes`,
44 * and the implementation of `Hash` below will take care of
45 * the rest. This is the recommended approach, since constructing
46 * good keyed hash functions is quite difficult.
47 */
48 pub trait Hash {
49 /**
50 * Compute a "keyed" hash of the value implementing the trait,
51 * taking `k0` and `k1` as "keying" parameters that randomize or
52 * otherwise perturb the hash function in such a way that a
53 * hash table built using such "keyed hash functions" cannot
54 * be made to perform linearly by an attacker controlling the
55 * hashtable's contents.
56 *
57 * In practical terms, we implement this using the SipHash 2-4
58 * function and require most types to only implement the
59 * IterBytes trait, that feeds SipHash.
60 */
61 fn hash_keyed(&self, k0: u64, k1: u64) -> u64;
62
63 #[inline]
64 fn hash(&self) -> u64 { self.hash_keyed(0,0) }
65 }
66
67 /// Streaming hash-functions should implement this.
68 pub trait Streaming {
69 fn input(&mut self, &[u8]);
70 // These can be refactored some when we have default methods.
71 fn result_bytes(&mut self) -> ~[u8];
72 fn result_str(&mut self) -> ~str;
73 fn result_u64(&mut self) -> u64;
74 fn reset(&mut self);
75 }
76
77 impl<A:IterBytes> Hash for A {
78 #[inline]
79 fn hash_keyed(&self, k0: u64, k1: u64) -> u64 {
80 let mut s = State::new(k0, k1);
81 do self.iter_bytes(true) |bytes| {
82 s.input(bytes);
83 true
84 };
85 s.result_u64()
86 }
87 }
88
89 fn hash_keyed_2<A: IterBytes,
90 B: IterBytes>(a: &A, b: &B, k0: u64, k1: u64) -> u64 {
91 let mut s = State::new(k0, k1);
92 do a.iter_bytes(true) |bytes| {
93 s.input(bytes);
94 true
95 };
96 do b.iter_bytes(true) |bytes| {
97 s.input(bytes);
98 true
99 };
100 s.result_u64()
101 }
102
103 fn hash_keyed_3<A: IterBytes,
104 B: IterBytes,
105 C: IterBytes>(a: &A, b: &B, c: &C, k0: u64, k1: u64) -> u64 {
106 let mut s = State::new(k0, k1);
107 do a.iter_bytes(true) |bytes| {
108 s.input(bytes);
109 true
110 };
111 do b.iter_bytes(true) |bytes| {
112 s.input(bytes);
113 true
114 };
115 do c.iter_bytes(true) |bytes| {
116 s.input(bytes);
117 true
118 };
119 s.result_u64()
120 }
121
122 fn hash_keyed_4<A: IterBytes,
123 B: IterBytes,
124 C: IterBytes,
125 D: IterBytes>(
126 a: &A,
127 b: &B,
128 c: &C,
129 d: &D,
130 k0: u64,
131 k1: u64)
132 -> u64 {
133 let mut s = State::new(k0, k1);
134 do a.iter_bytes(true) |bytes| {
135 s.input(bytes);
136 true
137 };
138 do b.iter_bytes(true) |bytes| {
139 s.input(bytes);
140 true
141 };
142 do c.iter_bytes(true) |bytes| {
143 s.input(bytes);
144 true
145 };
146 do d.iter_bytes(true) |bytes| {
147 s.input(bytes);
148 true
149 };
150 s.result_u64()
151 }
152
153 fn hash_keyed_5<A: IterBytes,
154 B: IterBytes,
155 C: IterBytes,
156 D: IterBytes,
157 E: IterBytes>(
158 a: &A,
159 b: &B,
160 c: &C,
161 d: &D,
162 e: &E,
163 k0: u64,
164 k1: u64)
165 -> u64 {
166 let mut s = State::new(k0, k1);
167 do a.iter_bytes(true) |bytes| {
168 s.input(bytes);
169 true
170 };
171 do b.iter_bytes(true) |bytes| {
172 s.input(bytes);
173 true
174 };
175 do c.iter_bytes(true) |bytes| {
176 s.input(bytes);
177 true
178 };
179 do d.iter_bytes(true) |bytes| {
180 s.input(bytes);
181 true
182 };
183 do e.iter_bytes(true) |bytes| {
184 s.input(bytes);
185 true
186 };
187 s.result_u64()
188 }
189
190 #[inline]
191 pub fn default_state() -> State {
192 State::new(0, 0)
193 }
194
195 struct SipState {
196 k0: u64,
197 k1: u64,
198 length: uint, // how many bytes we've processed
199 v0: u64, // hash state
200 v1: u64,
201 v2: u64,
202 v3: u64,
203 tail: [u8, ..8], // unprocessed bytes
204 ntail: uint, // how many bytes in tail are valid
205 }
206
207 impl SipState {
208 #[inline]
209 fn new(key0: u64, key1: u64) -> SipState {
210 let mut state = SipState {
211 k0: key0,
212 k1: key1,
213 length: 0,
214 v0: 0,
215 v1: 0,
216 v2: 0,
217 v3: 0,
218 tail: [ 0, 0, 0, 0, 0, 0, 0, 0 ],
219 ntail: 0,
220 };
221 state.reset();
222 state
223 }
224 }
225
226 // sadly, these macro definitions can't appear later,
227 // because they're needed in the following defs;
228 // this design could be improved.
229
230 macro_rules! u8to64_le (
231 ($buf:expr, $i:expr) =>
232 ($buf[0+$i] as u64 |
233 $buf[1+$i] as u64 << 8 |
234 $buf[2+$i] as u64 << 16 |
235 $buf[3+$i] as u64 << 24 |
236 $buf[4+$i] as u64 << 32 |
237 $buf[5+$i] as u64 << 40 |
238 $buf[6+$i] as u64 << 48 |
239 $buf[7+$i] as u64 << 56)
240 )
241
242 macro_rules! rotl (
243 ($x:expr, $b:expr) =>
244 (($x << $b) | ($x >> (64 - $b)))
245 )
246
247 macro_rules! compress (
248 ($v0:expr, $v1:expr, $v2:expr, $v3:expr) =>
249 ({
250 $v0 += $v1; $v1 = rotl!($v1, 13); $v1 ^= $v0;
251 $v0 = rotl!($v0, 32);
252 $v2 += $v3; $v3 = rotl!($v3, 16); $v3 ^= $v2;
253 $v0 += $v3; $v3 = rotl!($v3, 21); $v3 ^= $v0;
254 $v2 += $v1; $v1 = rotl!($v1, 17); $v1 ^= $v2;
255 $v2 = rotl!($v2, 32);
256 })
257 )
258
259
260 impl Writer for SipState {
261 // Methods for io::writer
262 #[inline]
263 fn write(&mut self, msg: &[u8]) {
264 let length = msg.len();
265 self.length += length;
266
267 let mut needed = 0u;
268
269 if self.ntail != 0 {
270 needed = 8 - self.ntail;
271
272 if length < needed {
273 let mut t = 0;
274 while t < length {
275 self.tail[self.ntail+t] = msg[t];
276 t += 1;
277 }
278 self.ntail += length;
279 return;
280 }
281
282 let mut t = 0;
283 while t < needed {
284 self.tail[self.ntail+t] = msg[t];
285 t += 1;
286 }
287
288 let m = u8to64_le!(self.tail, 0);
289
290 self.v3 ^= m;
291 compress!(self.v0, self.v1, self.v2, self.v3);
292 compress!(self.v0, self.v1, self.v2, self.v3);
293 self.v0 ^= m;
294
295 self.ntail = 0;
296 }
297
298 // Buffered tail is now flushed, process new input.
299 let len = length - needed;
300 let end = len & (!0x7);
301 let left = len & 0x7;
302
303 let mut i = needed;
304 while i < end {
305 let mi = u8to64_le!(msg, i);
306
307 self.v3 ^= mi;
308 compress!(self.v0, self.v1, self.v2, self.v3);
309 compress!(self.v0, self.v1, self.v2, self.v3);
310 self.v0 ^= mi;
311
312 i += 8;
313 }
314
315 let mut t = 0u;
316 while t < left {
317 self.tail[t] = msg[i+t];
318 t += 1
319 }
320 self.ntail = left;
321 }
322
323 fn flush(&mut self) {
324 // No-op
325 }
326 }
327
328 impl Streaming for SipState {
329 #[inline]
330 fn input(&mut self, buf: &[u8]) {
331 self.write(buf);
332 }
333
334 #[inline]
335 fn result_u64(&mut self) -> u64 {
336 let mut v0 = self.v0;
337 let mut v1 = self.v1;
338 let mut v2 = self.v2;
339 let mut v3 = self.v3;
340
341 let mut b : u64 = (self.length as u64 & 0xff) << 56;
342
343 if self.ntail > 0 { b |= self.tail[0] as u64 << 0; }
344 if self.ntail > 1 { b |= self.tail[1] as u64 << 8; }
345 if self.ntail > 2 { b |= self.tail[2] as u64 << 16; }
346 if self.ntail > 3 { b |= self.tail[3] as u64 << 24; }
347 if self.ntail > 4 { b |= self.tail[4] as u64 << 32; }
348 if self.ntail > 5 { b |= self.tail[5] as u64 << 40; }
349 if self.ntail > 6 { b |= self.tail[6] as u64 << 48; }
350
351 v3 ^= b;
352 compress!(v0, v1, v2, v3);
353 compress!(v0, v1, v2, v3);
354 v0 ^= b;
355
356 v2 ^= 0xff;
357 compress!(v0, v1, v2, v3);
358 compress!(v0, v1, v2, v3);
359 compress!(v0, v1, v2, v3);
360 compress!(v0, v1, v2, v3);
361
362 return (v0 ^ v1 ^ v2 ^ v3);
363 }
364
365 fn result_bytes(&mut self) -> ~[u8] {
366 let h = self.result_u64();
367 ~[(h >> 0) as u8,
368 (h >> 8) as u8,
369 (h >> 16) as u8,
370 (h >> 24) as u8,
371 (h >> 32) as u8,
372 (h >> 40) as u8,
373 (h >> 48) as u8,
374 (h >> 56) as u8,
375 ]
376 }
377
378 fn result_str(&mut self) -> ~str {
379 let r = self.result_bytes();
380 let mut s = ~"";
381 for b in r.iter() {
382 s.push_str((*b as uint).to_str_radix(16u));
383 }
384 s
385 }
386
387 #[inline]
388 fn reset(&mut self) {
389 self.length = 0;
390 self.v0 = self.k0 ^ 0x736f6d6570736575;
391 self.v1 = self.k1 ^ 0x646f72616e646f6d;
392 self.v2 = self.k0 ^ 0x6c7967656e657261;
393 self.v3 = self.k1 ^ 0x7465646279746573;
394 self.ntail = 0;
395 }
396 }
397
398 #[cfg(test)]
399 mod tests {
400 use super::*;
401 use prelude::*;
402
403 // Hash just the bytes of the slice, without length prefix
404 struct Bytes<'self>(&'self [u8]);
405 impl<'self> IterBytes for Bytes<'self> {
406 fn iter_bytes(&self, _lsb0: bool, f: &fn(&[u8]) -> bool) -> bool {
407 f(**self)
408 }
409 }
410
411 #[test]
412 fn test_siphash() {
413 let vecs : [[u8, ..8], ..64] = [
414 [ 0x31, 0x0e, 0x0e, 0xdd, 0x47, 0xdb, 0x6f, 0x72, ],
415 [ 0xfd, 0x67, 0xdc, 0x93, 0xc5, 0x39, 0xf8, 0x74, ],
416 [ 0x5a, 0x4f, 0xa9, 0xd9, 0x09, 0x80, 0x6c, 0x0d, ],
417 [ 0x2d, 0x7e, 0xfb, 0xd7, 0x96, 0x66, 0x67, 0x85, ],
418 [ 0xb7, 0x87, 0x71, 0x27, 0xe0, 0x94, 0x27, 0xcf, ],
419 [ 0x8d, 0xa6, 0x99, 0xcd, 0x64, 0x55, 0x76, 0x18, ],
420 [ 0xce, 0xe3, 0xfe, 0x58, 0x6e, 0x46, 0xc9, 0xcb, ],
421 [ 0x37, 0xd1, 0x01, 0x8b, 0xf5, 0x00, 0x02, 0xab, ],
422 [ 0x62, 0x24, 0x93, 0x9a, 0x79, 0xf5, 0xf5, 0x93, ],
423 [ 0xb0, 0xe4, 0xa9, 0x0b, 0xdf, 0x82, 0x00, 0x9e, ],
424 [ 0xf3, 0xb9, 0xdd, 0x94, 0xc5, 0xbb, 0x5d, 0x7a, ],
425 [ 0xa7, 0xad, 0x6b, 0x22, 0x46, 0x2f, 0xb3, 0xf4, ],
426 [ 0xfb, 0xe5, 0x0e, 0x86, 0xbc, 0x8f, 0x1e, 0x75, ],
427 [ 0x90, 0x3d, 0x84, 0xc0, 0x27, 0x56, 0xea, 0x14, ],
428 [ 0xee, 0xf2, 0x7a, 0x8e, 0x90, 0xca, 0x23, 0xf7, ],
429 [ 0xe5, 0x45, 0xbe, 0x49, 0x61, 0xca, 0x29, 0xa1, ],
430 [ 0xdb, 0x9b, 0xc2, 0x57, 0x7f, 0xcc, 0x2a, 0x3f, ],
431 [ 0x94, 0x47, 0xbe, 0x2c, 0xf5, 0xe9, 0x9a, 0x69, ],
432 [ 0x9c, 0xd3, 0x8d, 0x96, 0xf0, 0xb3, 0xc1, 0x4b, ],
433 [ 0xbd, 0x61, 0x79, 0xa7, 0x1d, 0xc9, 0x6d, 0xbb, ],
434 [ 0x98, 0xee, 0xa2, 0x1a, 0xf2, 0x5c, 0xd6, 0xbe, ],
435 [ 0xc7, 0x67, 0x3b, 0x2e, 0xb0, 0xcb, 0xf2, 0xd0, ],
436 [ 0x88, 0x3e, 0xa3, 0xe3, 0x95, 0x67, 0x53, 0x93, ],
437 [ 0xc8, 0xce, 0x5c, 0xcd, 0x8c, 0x03, 0x0c, 0xa8, ],
438 [ 0x94, 0xaf, 0x49, 0xf6, 0xc6, 0x50, 0xad, 0xb8, ],
439 [ 0xea, 0xb8, 0x85, 0x8a, 0xde, 0x92, 0xe1, 0xbc, ],
440 [ 0xf3, 0x15, 0xbb, 0x5b, 0xb8, 0x35, 0xd8, 0x17, ],
441 [ 0xad, 0xcf, 0x6b, 0x07, 0x63, 0x61, 0x2e, 0x2f, ],
442 [ 0xa5, 0xc9, 0x1d, 0xa7, 0xac, 0xaa, 0x4d, 0xde, ],
443 [ 0x71, 0x65, 0x95, 0x87, 0x66, 0x50, 0xa2, 0xa6, ],
444 [ 0x28, 0xef, 0x49, 0x5c, 0x53, 0xa3, 0x87, 0xad, ],
445 [ 0x42, 0xc3, 0x41, 0xd8, 0xfa, 0x92, 0xd8, 0x32, ],
446 [ 0xce, 0x7c, 0xf2, 0x72, 0x2f, 0x51, 0x27, 0x71, ],
447 [ 0xe3, 0x78, 0x59, 0xf9, 0x46, 0x23, 0xf3, 0xa7, ],
448 [ 0x38, 0x12, 0x05, 0xbb, 0x1a, 0xb0, 0xe0, 0x12, ],
449 [ 0xae, 0x97, 0xa1, 0x0f, 0xd4, 0x34, 0xe0, 0x15, ],
450 [ 0xb4, 0xa3, 0x15, 0x08, 0xbe, 0xff, 0x4d, 0x31, ],
451 [ 0x81, 0x39, 0x62, 0x29, 0xf0, 0x90, 0x79, 0x02, ],
452 [ 0x4d, 0x0c, 0xf4, 0x9e, 0xe5, 0xd4, 0xdc, 0xca, ],
453 [ 0x5c, 0x73, 0x33, 0x6a, 0x76, 0xd8, 0xbf, 0x9a, ],
454 [ 0xd0, 0xa7, 0x04, 0x53, 0x6b, 0xa9, 0x3e, 0x0e, ],
455 [ 0x92, 0x59, 0x58, 0xfc, 0xd6, 0x42, 0x0c, 0xad, ],
456 [ 0xa9, 0x15, 0xc2, 0x9b, 0xc8, 0x06, 0x73, 0x18, ],
457 [ 0x95, 0x2b, 0x79, 0xf3, 0xbc, 0x0a, 0xa6, 0xd4, ],
458 [ 0xf2, 0x1d, 0xf2, 0xe4, 0x1d, 0x45, 0x35, 0xf9, ],
459 [ 0x87, 0x57, 0x75, 0x19, 0x04, 0x8f, 0x53, 0xa9, ],
460 [ 0x10, 0xa5, 0x6c, 0xf5, 0xdf, 0xcd, 0x9a, 0xdb, ],
461 [ 0xeb, 0x75, 0x09, 0x5c, 0xcd, 0x98, 0x6c, 0xd0, ],
462 [ 0x51, 0xa9, 0xcb, 0x9e, 0xcb, 0xa3, 0x12, 0xe6, ],
463 [ 0x96, 0xaf, 0xad, 0xfc, 0x2c, 0xe6, 0x66, 0xc7, ],
464 [ 0x72, 0xfe, 0x52, 0x97, 0x5a, 0x43, 0x64, 0xee, ],
465 [ 0x5a, 0x16, 0x45, 0xb2, 0x76, 0xd5, 0x92, 0xa1, ],
466 [ 0xb2, 0x74, 0xcb, 0x8e, 0xbf, 0x87, 0x87, 0x0a, ],
467 [ 0x6f, 0x9b, 0xb4, 0x20, 0x3d, 0xe7, 0xb3, 0x81, ],
468 [ 0xea, 0xec, 0xb2, 0xa3, 0x0b, 0x22, 0xa8, 0x7f, ],
469 [ 0x99, 0x24, 0xa4, 0x3c, 0xc1, 0x31, 0x57, 0x24, ],
470 [ 0xbd, 0x83, 0x8d, 0x3a, 0xaf, 0xbf, 0x8d, 0xb7, ],
471 [ 0x0b, 0x1a, 0x2a, 0x32, 0x65, 0xd5, 0x1a, 0xea, ],
472 [ 0x13, 0x50, 0x79, 0xa3, 0x23, 0x1c, 0xe6, 0x60, ],
473 [ 0x93, 0x2b, 0x28, 0x46, 0xe4, 0xd7, 0x06, 0x66, ],
474 [ 0xe1, 0x91, 0x5f, 0x5c, 0xb1, 0xec, 0xa4, 0x6c, ],
475 [ 0xf3, 0x25, 0x96, 0x5c, 0xa1, 0x6d, 0x62, 0x9f, ],
476 [ 0x57, 0x5f, 0xf2, 0x8e, 0x60, 0x38, 0x1b, 0xe5, ],
477 [ 0x72, 0x45, 0x06, 0xeb, 0x4c, 0x32, 0x8a, 0x95, ]
478 ];
479
480 let k0 = 0x_07_06_05_04_03_02_01_00_u64;
481 let k1 = 0x_0f_0e_0d_0c_0b_0a_09_08_u64;
482 let mut buf : ~[u8] = ~[];
483 let mut t = 0;
484 let mut stream_inc = SipState::new(k0, k1);
485 let mut stream_full = SipState::new(k0, k1);
486
487 fn to_hex_str(r: &[u8, ..8]) -> ~str {
488 let mut s = ~"";
489 for b in r.iter() {
490 s.push_str((*b as uint).to_str_radix(16u));
491 }
492 s
493 }
494
495 while t < 64 {
496 debug2!("siphash test {}", t);
497 let vec = u8to64_le!(vecs[t], 0);
498 let out = Bytes(buf.as_slice()).hash_keyed(k0, k1);
499 debug2!("got {:?}, expected {:?}", out, vec);
500 assert_eq!(vec, out);
501
502 stream_full.reset();
503 stream_full.input(buf);
504 let f = stream_full.result_str();
505 let i = stream_inc.result_str();
506 let v = to_hex_str(&vecs[t]);
507 debug2!("{}: ({}) => inc={} full={}", t, v, i, f);
508
509 assert!(f == i && f == v);
510
511 buf.push(t as u8);
512 stream_inc.input([t as u8]);
513
514 t += 1;
515 }
516 }
517
518 #[test] #[cfg(target_arch = "arm")]
519 fn test_hash_uint() {
520 let val = 0xdeadbeef_deadbeef_u64;
521 assert!((val as u64).hash() != (val as uint).hash());
522 assert_eq!((val as u32).hash(), (val as uint).hash());
523 }
524 #[test] #[cfg(target_arch = "x86_64")]
525 fn test_hash_uint() {
526 let val = 0xdeadbeef_deadbeef_u64;
527 assert_eq!((val as u64).hash(), (val as uint).hash());
528 assert!((val as u32).hash() != (val as uint).hash());
529 }
530 #[test] #[cfg(target_arch = "x86")]
531 fn test_hash_uint() {
532 let val = 0xdeadbeef_deadbeef_u64;
533 assert!((val as u64).hash() != (val as uint).hash());
534 assert_eq!((val as u32).hash(), (val as uint).hash());
535 }
536
537 #[test]
538 fn test_hash_idempotent() {
539 let val64 = 0xdeadbeef_deadbeef_u64;
540 val64.hash() == val64.hash();
541 let val32 = 0xdeadbeef_u32;
542 val32.hash() == val32.hash();
543 }
544
545 #[test]
546 fn test_hash_no_bytes_dropped_64() {
547 let val = 0xdeadbeef_deadbeef_u64;
548
549 assert!(val.hash() != zero_byte(val, 0).hash());
550 assert!(val.hash() != zero_byte(val, 1).hash());
551 assert!(val.hash() != zero_byte(val, 2).hash());
552 assert!(val.hash() != zero_byte(val, 3).hash());
553 assert!(val.hash() != zero_byte(val, 4).hash());
554 assert!(val.hash() != zero_byte(val, 5).hash());
555 assert!(val.hash() != zero_byte(val, 6).hash());
556 assert!(val.hash() != zero_byte(val, 7).hash());
557
558 fn zero_byte(val: u64, byte: uint) -> u64 {
559 assert!(byte < 8);
560 val & !(0xff << (byte * 8))
561 }
562 }
563
564 #[test]
565 fn test_hash_no_bytes_dropped_32() {
566 let val = 0xdeadbeef_u32;
567
568 assert!(val.hash() != zero_byte(val, 0).hash());
569 assert!(val.hash() != zero_byte(val, 1).hash());
570 assert!(val.hash() != zero_byte(val, 2).hash());
571 assert!(val.hash() != zero_byte(val, 3).hash());
572
573 fn zero_byte(val: u32, byte: uint) -> u32 {
574 assert!(byte < 4);
575 val & !(0xff << (byte * 8))
576 }
577 }
578
579 #[test]
580 fn test_float_hashes_differ() {
581 assert!(0.0.hash() != 1.0.hash());
582 assert!(1.0.hash() != (-1.0).hash());
583 }
584
585 #[test]
586 fn test_float_hashes_of_zero() {
587 assert_eq!(0.0.hash(), (-0.0).hash());
588 }
589
590 #[test]
591 fn test_hash_no_concat_alias() {
592 let s = ("aa", "bb");
593 let t = ("aabb", "");
594 let u = ("a", "abb");
595
596 let v = (&[1u8], &[0u8, 0], &[0u8]);
597 let w = (&[1u8, 0, 0, 0], &[], &[]);
598
599 assert!(v != w);
600 assert!(s.hash() != t.hash() && s.hash() != u.hash());
601 assert!(v.hash() != w.hash());
602 }
603 }
libstd/hash.rs:67:52-67:52 -trait- definition:
/// Streaming hash-functions should implement this.
pub trait Streaming {
references:-328: impl Streaming for SipState {
libstd/hash.rs:47:4-47:4 -trait- definition:
*/
pub trait Hash {
references:-77: impl<A:IterBytes> Hash for A {
libstd/hashmap.rs:
440: pub fn find_equiv<'a, Q:Hash + Equiv<K>>(&'a self, k: &Q)
431: pub fn contains_key_equiv<Q:Hash + Equiv<K>>(&self, key: &Q) -> bool {
781: impl<K: Eq + Hash> Extendable<K> for HashSet<K> {
480: impl<K: Hash + Eq, V: Clone> HashMap<K, V> {
647: impl<T:Hash + Eq> Mutable for HashSet<T> {
764: impl<T:Hash + Eq + Clone> Clone for HashSet<T> {
642: impl<T:Hash + Eq> Container for HashSet<T> {
261: impl<K:Hash + Eq,V> Container for HashMap<K, V> {
683: impl<T:Hash + Eq> HashSet<T> {
104: fn bucket_for_key_equiv<Q:Hash + Equiv<K>>(&self, k: &Q)
266: impl<K:Hash + Eq,V> Mutable for HashMap<K, V> {
609: impl<K: Eq + Hash, V> FromIterator<(K, V)> for HashMap<K, V> {
492: impl<K:Hash + Eq,V:Eq> Eq for HashMap<K, V> {
507: impl<K:Hash + Eq + Clone,V:Clone> Clone for HashMap<K,V> {
276: impl<K:Hash + Eq,V> Map<K, V> for HashMap<K, V> {
618: impl<K: Eq + Hash, V> Extendable<(K, V)> for HashMap<K, V> {
772: impl<K: Eq + Hash> FromIterator<K> for HashSet<K> {
69: impl<K:Hash + Eq,V> HashMap<K, V> {
673: impl<T:Hash + Eq> MutableSet<T> for HashSet<T> {
713: pub fn contains_equiv<Q:Hash + Equiv<T>>(&self, value: &Q) -> bool {
789: impl<K: Eq + Hash> Default for HashSet<K> {
323: impl<K: Hash + Eq, V> HashMap<K, V> {
637: impl<T:Hash + Eq> Eq for HashSet<T> {
652: impl<T:Hash + Eq> Set<T> for HashSet<T> {
626: impl<K: Eq + Hash, V> Default for HashMap<K, V> {
286: impl<K:Hash + Eq,V> MutableMap<K, V> for HashMap<K, V> {
libstd/to_str.rs:
54: impl<A:ToStr+Hash+Eq, B:ToStr> ToStr for HashMap<A, B> {
75: impl<A:ToStr+Hash+Eq> ToStr for HashSet<A> {
libstd/hash.rs:194:1-194:1 -struct- definition:
struct SipState {
references:-209: fn new(key0: u64, key1: u64) -> SipState {
191: pub fn default_state() -> State {
328: impl Streaming for SipState {
260: impl Writer for SipState {
207: impl SipState {
210: let mut state = SipState {