]>
Commit | Line | Data |
---|---|---|
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 | |
cc61c64b XL |
19 | //! use std::collections::hash_map::DefaultHasher; |
20 | //! use std::hash::{Hash, Hasher}; | |
1a4d82fc JJ |
21 | //! |
22 | //! #[derive(Hash)] | |
23 | //! struct Person { | |
c34b1796 | 24 | //! id: u32, |
1a4d82fc JJ |
25 | //! name: String, |
26 | //! phone: u64, | |
27 | //! } | |
28 | //! | |
cc61c64b XL |
29 | //! let person1 = Person { |
30 | //! id: 5, | |
31 | //! name: "Janet".to_string(), | |
32 | //! phone: 555_666_7777, | |
33 | //! }; | |
34 | //! let person2 = Person { | |
35 | //! id: 5, | |
36 | //! name: "Bob".to_string(), | |
37 | //! phone: 555_666_7777, | |
38 | //! }; | |
1a4d82fc | 39 | //! |
cc61c64b | 40 | //! assert!(calculate_hash(&person1) != calculate_hash(&person2)); |
e9174d1e | 41 | //! |
cc61c64b XL |
42 | //! fn calculate_hash<T: Hash>(t: &T) -> u64 { |
43 | //! let mut s = DefaultHasher::new(); | |
e9174d1e SL |
44 | //! t.hash(&mut s); |
45 | //! s.finish() | |
46 | //! } | |
1a4d82fc JJ |
47 | //! ``` |
48 | //! | |
49 | //! If you need more control over how a value is hashed, you need to implement | |
c30ab7b3 SL |
50 | //! the [`Hash`] trait: |
51 | //! | |
52 | //! [`Hash`]: trait.Hash.html | |
1a4d82fc JJ |
53 | //! |
54 | //! ```rust | |
cc61c64b XL |
55 | //! use std::collections::hash_map::DefaultHasher; |
56 | //! use std::hash::{Hash, Hasher}; | |
1a4d82fc JJ |
57 | //! |
58 | //! struct Person { | |
c34b1796 | 59 | //! id: u32, |
cc61c64b | 60 | //! # #[allow(dead_code)] |
1a4d82fc JJ |
61 | //! name: String, |
62 | //! phone: u64, | |
63 | //! } | |
64 | //! | |
85aaf69f SL |
65 | //! impl Hash for Person { |
66 | //! fn hash<H: Hasher>(&self, state: &mut H) { | |
1a4d82fc JJ |
67 | //! self.id.hash(state); |
68 | //! self.phone.hash(state); | |
69 | //! } | |
70 | //! } | |
71 | //! | |
cc61c64b XL |
72 | //! let person1 = Person { |
73 | //! id: 5, | |
74 | //! name: "Janet".to_string(), | |
75 | //! phone: 555_666_7777, | |
76 | //! }; | |
77 | //! let person2 = Person { | |
78 | //! id: 5, | |
79 | //! name: "Bob".to_string(), | |
80 | //! phone: 555_666_7777, | |
81 | //! }; | |
1a4d82fc | 82 | //! |
cc61c64b | 83 | //! assert_eq!(calculate_hash(&person1), calculate_hash(&person2)); |
e9174d1e | 84 | //! |
cc61c64b XL |
85 | //! fn calculate_hash<T: Hash>(t: &T) -> u64 { |
86 | //! let mut s = DefaultHasher::new(); | |
e9174d1e SL |
87 | //! t.hash(&mut s); |
88 | //! s.finish() | |
89 | //! } | |
1a4d82fc JJ |
90 | //! ``` |
91 | ||
85aaf69f SL |
92 | #![stable(feature = "rust1", since = "1.0.0")] |
93 | ||
54a0048b | 94 | use fmt; |
9cc50fc6 | 95 | use marker; |
85aaf69f | 96 | use mem; |
1a4d82fc | 97 | |
92a42be0 | 98 | #[stable(feature = "rust1", since = "1.0.0")] |
9e0c209e | 99 | #[allow(deprecated)] |
1a4d82fc JJ |
100 | pub use self::sip::SipHasher; |
101 | ||
041b39d2 | 102 | #[unstable(feature = "sip_hash_13", issue = "34767")] |
9e0c209e | 103 | #[allow(deprecated)] |
3157f602 XL |
104 | pub use self::sip::{SipHasher13, SipHasher24}; |
105 | ||
1a4d82fc JJ |
106 | mod sip; |
107 | ||
108 | /// A hashable type. | |
109 | /// | |
cc61c64b XL |
110 | /// Types implementing `Hash` are able to be [`hash`]ed with an instance of |
111 | /// [`Hasher`]. | |
c34b1796 | 112 | /// |
cc61c64b | 113 | /// ## Implementing `Hash` |
c34b1796 | 114 | /// |
cc61c64b XL |
115 | /// You can derive `Hash` with `#[derive(Hash)]` if all fields implement `Hash`. |
116 | /// The resulting hash will be the combination of the values from calling | |
117 | /// [`hash`] on each field. | |
92a42be0 | 118 | /// |
cc61c64b XL |
119 | /// ``` |
120 | /// #[derive(Hash)] | |
121 | /// struct Rustacean { | |
122 | /// name: String, | |
123 | /// country: String, | |
124 | /// } | |
125 | /// ``` | |
3157f602 | 126 | /// |
cc61c64b XL |
127 | /// If you need more control over how a value is hashed, you can of course |
128 | /// implement the `Hash` trait yourself: | |
3157f602 XL |
129 | /// |
130 | /// ``` | |
131 | /// use std::hash::{Hash, Hasher}; | |
132 | /// | |
133 | /// struct Person { | |
134 | /// id: u32, | |
135 | /// name: String, | |
136 | /// phone: u64, | |
137 | /// } | |
138 | /// | |
139 | /// impl Hash for Person { | |
140 | /// fn hash<H: Hasher>(&self, state: &mut H) { | |
141 | /// self.id.hash(state); | |
142 | /// self.phone.hash(state); | |
143 | /// } | |
144 | /// } | |
145 | /// ``` | |
c30ab7b3 | 146 | /// |
cc61c64b XL |
147 | /// ## `Hash` and `Eq` |
148 | /// | |
149 | /// When implementing both `Hash` and [`Eq`], it is important that the following | |
150 | /// property holds: | |
151 | /// | |
152 | /// ```text | |
153 | /// k1 == k2 -> hash(k1) == hash(k2) | |
154 | /// ``` | |
155 | /// | |
156 | /// In other words, if two keys are equal, their hashes must also be equal. | |
157 | /// [`HashMap`] and [`HashSet`] both rely on this behavior. | |
158 | /// | |
159 | /// Thankfully, you won't need to worry about upholding this property when | |
160 | /// deriving both [`Eq`] and `Hash` with `#[derive(PartialEq, Eq, Hash)]`. | |
161 | /// | |
c30ab7b3 | 162 | /// [`Eq`]: ../../std/cmp/trait.Eq.html |
cc61c64b | 163 | /// [`Hasher`]: trait.Hasher.html |
c30ab7b3 SL |
164 | /// [`HashMap`]: ../../std/collections/struct.HashMap.html |
165 | /// [`HashSet`]: ../../std/collections/struct.HashSet.html | |
cc61c64b | 166 | /// [`hash`]: #tymethod.hash |
85aaf69f SL |
167 | #[stable(feature = "rust1", since = "1.0.0")] |
168 | pub trait Hash { | |
cc61c64b XL |
169 | /// Feeds this value into the given [`Hasher`]. |
170 | /// | |
171 | /// # Examples | |
172 | /// | |
173 | /// ``` | |
174 | /// use std::collections::hash_map::DefaultHasher; | |
175 | /// use std::hash::{Hash, Hasher}; | |
176 | /// | |
177 | /// let mut hasher = DefaultHasher::new(); | |
178 | /// 7920.hash(&mut hasher); | |
179 | /// println!("Hash is {:x}!", hasher.finish()); | |
180 | /// ``` | |
181 | /// | |
182 | /// [`Hasher`]: trait.Hasher.html | |
85aaf69f SL |
183 | #[stable(feature = "rust1", since = "1.0.0")] |
184 | fn hash<H: Hasher>(&self, state: &mut H); | |
185 | ||
cc61c64b XL |
186 | /// Feeds a slice of this type into the given [`Hasher`]. |
187 | /// | |
188 | /// # Examples | |
189 | /// | |
190 | /// ``` | |
191 | /// use std::collections::hash_map::DefaultHasher; | |
192 | /// use std::hash::{Hash, Hasher}; | |
193 | /// | |
194 | /// let mut hasher = DefaultHasher::new(); | |
195 | /// let numbers = [6, 28, 496, 8128]; | |
196 | /// Hash::hash_slice(&numbers, &mut hasher); | |
197 | /// println!("Hash is {:x}!", hasher.finish()); | |
198 | /// ``` | |
199 | /// | |
200 | /// [`Hasher`]: trait.Hasher.html | |
c1a9b12d | 201 | #[stable(feature = "hash_slice", since = "1.3.0")] |
b039eaaf SL |
202 | fn hash_slice<H: Hasher>(data: &[Self], state: &mut H) |
203 | where Self: Sized | |
204 | { | |
85aaf69f SL |
205 | for piece in data { |
206 | piece.hash(state); | |
207 | } | |
208 | } | |
1a4d82fc JJ |
209 | } |
210 | ||
cc61c64b XL |
211 | /// A trait for hashing an arbitrary stream of bytes. |
212 | /// | |
213 | /// Instances of `Hasher` usually represent state that is changed while hashing | |
214 | /// data. | |
215 | /// | |
216 | /// `Hasher` provides a fairly basic interface for retrieving the generated hash | |
217 | /// (with [`finish`]), and writing integers as well as slices of bytes into an | |
218 | /// instance (with [`write`] and [`write_u8`] etc.). Most of the time, `Hasher` | |
219 | /// instances are used in conjunction with the [`Hash`] trait. | |
220 | /// | |
221 | /// # Examples | |
222 | /// | |
223 | /// ``` | |
224 | /// use std::collections::hash_map::DefaultHasher; | |
225 | /// use std::hash::Hasher; | |
226 | /// | |
227 | /// let mut hasher = DefaultHasher::new(); | |
228 | /// | |
229 | /// hasher.write_u32(1989); | |
230 | /// hasher.write_u8(11); | |
231 | /// hasher.write_u8(9); | |
232 | /// hasher.write(b"Huh?"); | |
233 | /// | |
234 | /// println!("Hash is {:x}!", hasher.finish()); | |
235 | /// ``` | |
236 | /// | |
237 | /// [`Hash`]: trait.Hash.html | |
238 | /// [`finish`]: #tymethod.finish | |
239 | /// [`write`]: #tymethod.write | |
240 | /// [`write_u8`]: #method.write_u8 | |
85aaf69f | 241 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc | 242 | pub trait Hasher { |
3b2f2976 XL |
243 | /// Returns the hash value for the values written so far. |
244 | /// | |
245 | /// Despite its name, the method does not reset the hasher’s internal | |
246 | /// state. Additional [`write`]s will continue from the current value. | |
247 | /// If you need to start a fresh hash value, you will have to create | |
248 | /// a new hasher. | |
cc61c64b XL |
249 | /// |
250 | /// # Examples | |
251 | /// | |
252 | /// ``` | |
253 | /// use std::collections::hash_map::DefaultHasher; | |
254 | /// use std::hash::Hasher; | |
255 | /// | |
256 | /// let mut hasher = DefaultHasher::new(); | |
257 | /// hasher.write(b"Cool!"); | |
258 | /// | |
259 | /// println!("Hash is {:x}!", hasher.finish()); | |
260 | /// ``` | |
3b2f2976 | 261 | /// |
abe05a73 | 262 | /// [`write`]: #tymethod.write |
c34b1796 | 263 | #[stable(feature = "rust1", since = "1.0.0")] |
85aaf69f SL |
264 | fn finish(&self) -> u64; |
265 | ||
c30ab7b3 | 266 | /// Writes some data into this `Hasher`. |
cc61c64b XL |
267 | /// |
268 | /// # Examples | |
269 | /// | |
270 | /// ``` | |
271 | /// use std::collections::hash_map::DefaultHasher; | |
272 | /// use std::hash::Hasher; | |
273 | /// | |
274 | /// let mut hasher = DefaultHasher::new(); | |
275 | /// let data = [0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef]; | |
276 | /// | |
277 | /// hasher.write(&data); | |
278 | /// | |
279 | /// println!("Hash is {:x}!", hasher.finish()); | |
280 | /// ``` | |
85aaf69f SL |
281 | #[stable(feature = "rust1", since = "1.0.0")] |
282 | fn write(&mut self, bytes: &[u8]); | |
283 | ||
cc61c64b | 284 | /// Writes a single `u8` into this hasher. |
85aaf69f | 285 | #[inline] |
c1a9b12d | 286 | #[stable(feature = "hasher_write", since = "1.3.0")] |
b039eaaf SL |
287 | fn write_u8(&mut self, i: u8) { |
288 | self.write(&[i]) | |
289 | } | |
c30ab7b3 | 290 | /// Writes a single `u16` into this hasher. |
85aaf69f | 291 | #[inline] |
c1a9b12d | 292 | #[stable(feature = "hasher_write", since = "1.3.0")] |
85aaf69f SL |
293 | fn write_u16(&mut self, i: u16) { |
294 | self.write(&unsafe { mem::transmute::<_, [u8; 2]>(i) }) | |
295 | } | |
c30ab7b3 | 296 | /// Writes a single `u32` into this hasher. |
85aaf69f | 297 | #[inline] |
c1a9b12d | 298 | #[stable(feature = "hasher_write", since = "1.3.0")] |
85aaf69f SL |
299 | fn write_u32(&mut self, i: u32) { |
300 | self.write(&unsafe { mem::transmute::<_, [u8; 4]>(i) }) | |
301 | } | |
c30ab7b3 | 302 | /// Writes a single `u64` into this hasher. |
85aaf69f | 303 | #[inline] |
c1a9b12d | 304 | #[stable(feature = "hasher_write", since = "1.3.0")] |
85aaf69f SL |
305 | fn write_u64(&mut self, i: u64) { |
306 | self.write(&unsafe { mem::transmute::<_, [u8; 8]>(i) }) | |
307 | } | |
32a655c1 SL |
308 | /// Writes a single `u128` into this hasher. |
309 | #[inline] | |
310 | #[unstable(feature = "i128", issue = "35118")] | |
311 | fn write_u128(&mut self, i: u128) { | |
312 | self.write(&unsafe { mem::transmute::<_, [u8; 16]>(i) }) | |
313 | } | |
c30ab7b3 | 314 | /// Writes a single `usize` into this hasher. |
85aaf69f | 315 | #[inline] |
c1a9b12d | 316 | #[stable(feature = "hasher_write", since = "1.3.0")] |
85aaf69f | 317 | fn write_usize(&mut self, i: usize) { |
e9174d1e | 318 | let bytes = unsafe { |
b039eaaf | 319 | ::slice::from_raw_parts(&i as *const usize as *const u8, mem::size_of::<usize>()) |
e9174d1e SL |
320 | }; |
321 | self.write(bytes); | |
85aaf69f SL |
322 | } |
323 | ||
c30ab7b3 | 324 | /// Writes a single `i8` into this hasher. |
85aaf69f | 325 | #[inline] |
c1a9b12d | 326 | #[stable(feature = "hasher_write", since = "1.3.0")] |
b039eaaf SL |
327 | fn write_i8(&mut self, i: i8) { |
328 | self.write_u8(i as u8) | |
329 | } | |
c30ab7b3 | 330 | /// Writes a single `i16` into this hasher. |
85aaf69f | 331 | #[inline] |
c1a9b12d | 332 | #[stable(feature = "hasher_write", since = "1.3.0")] |
b039eaaf SL |
333 | fn write_i16(&mut self, i: i16) { |
334 | self.write_u16(i as u16) | |
335 | } | |
c30ab7b3 | 336 | /// Writes a single `i32` into this hasher. |
85aaf69f | 337 | #[inline] |
c1a9b12d | 338 | #[stable(feature = "hasher_write", since = "1.3.0")] |
b039eaaf SL |
339 | fn write_i32(&mut self, i: i32) { |
340 | self.write_u32(i as u32) | |
341 | } | |
c30ab7b3 | 342 | /// Writes a single `i64` into this hasher. |
85aaf69f | 343 | #[inline] |
c1a9b12d | 344 | #[stable(feature = "hasher_write", since = "1.3.0")] |
b039eaaf SL |
345 | fn write_i64(&mut self, i: i64) { |
346 | self.write_u64(i as u64) | |
347 | } | |
32a655c1 SL |
348 | /// Writes a single `i128` into this hasher. |
349 | #[inline] | |
350 | #[unstable(feature = "i128", issue = "35118")] | |
351 | fn write_i128(&mut self, i: i128) { | |
352 | self.write_u128(i as u128) | |
353 | } | |
c30ab7b3 | 354 | /// Writes a single `isize` into this hasher. |
85aaf69f | 355 | #[inline] |
c1a9b12d | 356 | #[stable(feature = "hasher_write", since = "1.3.0")] |
b039eaaf SL |
357 | fn write_isize(&mut self, i: isize) { |
358 | self.write_usize(i as usize) | |
359 | } | |
1a4d82fc JJ |
360 | } |
361 | ||
ea8adc8c XL |
362 | #[stable(feature = "indirect_hasher_impl", since = "1.22.0")] |
363 | impl<'a, H: Hasher + ?Sized> Hasher for &'a mut H { | |
364 | fn finish(&self) -> u64 { | |
365 | (**self).finish() | |
366 | } | |
367 | fn write(&mut self, bytes: &[u8]) { | |
368 | (**self).write(bytes) | |
369 | } | |
370 | fn write_u8(&mut self, i: u8) { | |
371 | (**self).write_u8(i) | |
372 | } | |
373 | fn write_u16(&mut self, i: u16) { | |
374 | (**self).write_u16(i) | |
375 | } | |
376 | fn write_u32(&mut self, i: u32) { | |
377 | (**self).write_u32(i) | |
378 | } | |
379 | fn write_u64(&mut self, i: u64) { | |
380 | (**self).write_u64(i) | |
381 | } | |
382 | fn write_u128(&mut self, i: u128) { | |
383 | (**self).write_u128(i) | |
384 | } | |
385 | fn write_usize(&mut self, i: usize) { | |
386 | (**self).write_usize(i) | |
387 | } | |
388 | fn write_i8(&mut self, i: i8) { | |
389 | (**self).write_i8(i) | |
390 | } | |
391 | fn write_i16(&mut self, i: i16) { | |
392 | (**self).write_i16(i) | |
393 | } | |
394 | fn write_i32(&mut self, i: i32) { | |
395 | (**self).write_i32(i) | |
396 | } | |
397 | fn write_i64(&mut self, i: i64) { | |
398 | (**self).write_i64(i) | |
399 | } | |
400 | fn write_i128(&mut self, i: i128) { | |
401 | (**self).write_i128(i) | |
402 | } | |
403 | fn write_isize(&mut self, i: isize) { | |
404 | (**self).write_isize(i) | |
405 | } | |
406 | } | |
407 | ||
cc61c64b XL |
408 | /// A trait for creating instances of [`Hasher`]. |
409 | /// | |
410 | /// A `BuildHasher` is typically used (e.g. by [`HashMap`]) to create | |
411 | /// [`Hasher`]s for each key such that they are hashed independently of one | |
412 | /// another, since [`Hasher`]s contain state. | |
413 | /// | |
414 | /// For each instance of `BuildHasher`, the [`Hasher`]s created by | |
415 | /// [`build_hasher`] should be identical. That is, if the same stream of bytes | |
416 | /// is fed into each hasher, the same output will also be generated. | |
417 | /// | |
418 | /// # Examples | |
419 | /// | |
420 | /// ``` | |
421 | /// use std::collections::hash_map::RandomState; | |
422 | /// use std::hash::{BuildHasher, Hasher}; | |
423 | /// | |
424 | /// let s = RandomState::new(); | |
425 | /// let mut hasher_1 = s.build_hasher(); | |
426 | /// let mut hasher_2 = s.build_hasher(); | |
9cc50fc6 | 427 | /// |
cc61c64b XL |
428 | /// hasher_1.write_u32(8128); |
429 | /// hasher_2.write_u32(8128); | |
430 | /// | |
431 | /// assert_eq!(hasher_1.finish(), hasher_2.finish()); | |
432 | /// ``` | |
433 | /// | |
434 | /// [`build_hasher`]: #tymethod.build_hasher | |
435 | /// [`Hasher`]: trait.Hasher.html | |
436 | /// [`HashMap`]: ../../std/collections/struct.HashMap.html | |
9cc50fc6 SL |
437 | #[stable(since = "1.7.0", feature = "build_hasher")] |
438 | pub trait BuildHasher { | |
439 | /// Type of the hasher that will be created. | |
440 | #[stable(since = "1.7.0", feature = "build_hasher")] | |
441 | type Hasher: Hasher; | |
442 | ||
443 | /// Creates a new hasher. | |
5bcae85e | 444 | /// |
cc61c64b XL |
445 | /// Each call to `build_hasher` on the same instance should produce identical |
446 | /// [`Hasher`]s. | |
447 | /// | |
5bcae85e SL |
448 | /// # Examples |
449 | /// | |
450 | /// ``` | |
451 | /// use std::collections::hash_map::RandomState; | |
452 | /// use std::hash::BuildHasher; | |
453 | /// | |
454 | /// let s = RandomState::new(); | |
455 | /// let new_s = s.build_hasher(); | |
456 | /// ``` | |
cc61c64b XL |
457 | /// |
458 | /// [`Hasher`]: trait.Hasher.html | |
9cc50fc6 SL |
459 | #[stable(since = "1.7.0", feature = "build_hasher")] |
460 | fn build_hasher(&self) -> Self::Hasher; | |
461 | } | |
462 | ||
cc61c64b XL |
463 | /// Used to create a default [`BuildHasher`] instance for types that implement |
464 | /// [`Hasher`] and [`Default`]. | |
9cc50fc6 | 465 | /// |
cc61c64b XL |
466 | /// `BuildHasherDefault<H>` can be used when a type `H` implements [`Hasher`] and |
467 | /// [`Default`], and you need a corresponding [`BuildHasher`] instance, but none is | |
468 | /// defined. | |
469 | /// | |
470 | /// Any `BuildHasherDefault` is [zero-sized]. It can be created with | |
471 | /// [`default`][method.Default]. When using `BuildHasherDefault` with [`HashMap`] or | |
472 | /// [`HashSet`], this doesn't need to be done, since they implement appropriate | |
473 | /// [`Default`] instances themselves. | |
476ff2be SL |
474 | /// |
475 | /// # Examples | |
476 | /// | |
477 | /// Using `BuildHasherDefault` to specify a custom [`BuildHasher`] for | |
478 | /// [`HashMap`]: | |
479 | /// | |
480 | /// ``` | |
481 | /// use std::collections::HashMap; | |
482 | /// use std::hash::{BuildHasherDefault, Hasher}; | |
483 | /// | |
484 | /// #[derive(Default)] | |
485 | /// struct MyHasher; | |
486 | /// | |
487 | /// impl Hasher for MyHasher { | |
488 | /// fn write(&mut self, bytes: &[u8]) { | |
489 | /// // Your hashing algorithm goes here! | |
490 | /// unimplemented!() | |
491 | /// } | |
492 | /// | |
493 | /// fn finish(&self) -> u64 { | |
494 | /// // Your hashing algorithm goes here! | |
495 | /// unimplemented!() | |
496 | /// } | |
497 | /// } | |
498 | /// | |
499 | /// type MyBuildHasher = BuildHasherDefault<MyHasher>; | |
500 | /// | |
501 | /// let hash_map = HashMap::<u32, u32, MyBuildHasher>::default(); | |
502 | /// ``` | |
503 | /// | |
504 | /// [`BuildHasher`]: trait.BuildHasher.html | |
505 | /// [`Default`]: ../default/trait.Default.html | |
cc61c64b | 506 | /// [method.default]: #method.default |
476ff2be | 507 | /// [`Hasher`]: trait.Hasher.html |
32a655c1 | 508 | /// [`HashMap`]: ../../std/collections/struct.HashMap.html |
cc61c64b XL |
509 | /// [`HashSet`]: ../../std/collections/struct.HashSet.html |
510 | /// [zero-sized]: https://doc.rust-lang.org/nomicon/exotic-sizes.html#zero-sized-types-zsts | |
9cc50fc6 SL |
511 | #[stable(since = "1.7.0", feature = "build_hasher")] |
512 | pub struct BuildHasherDefault<H>(marker::PhantomData<H>); | |
513 | ||
54a0048b SL |
514 | #[stable(since = "1.9.0", feature = "core_impl_debug")] |
515 | impl<H> fmt::Debug for BuildHasherDefault<H> { | |
516 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
517 | f.pad("BuildHasherDefault") | |
518 | } | |
519 | } | |
520 | ||
9cc50fc6 SL |
521 | #[stable(since = "1.7.0", feature = "build_hasher")] |
522 | impl<H: Default + Hasher> BuildHasher for BuildHasherDefault<H> { | |
523 | type Hasher = H; | |
524 | ||
525 | fn build_hasher(&self) -> H { | |
526 | H::default() | |
527 | } | |
528 | } | |
529 | ||
530 | #[stable(since = "1.7.0", feature = "build_hasher")] | |
531 | impl<H> Clone for BuildHasherDefault<H> { | |
532 | fn clone(&self) -> BuildHasherDefault<H> { | |
533 | BuildHasherDefault(marker::PhantomData) | |
534 | } | |
535 | } | |
536 | ||
537 | #[stable(since = "1.7.0", feature = "build_hasher")] | |
538 | impl<H> Default for BuildHasherDefault<H> { | |
539 | fn default() -> BuildHasherDefault<H> { | |
540 | BuildHasherDefault(marker::PhantomData) | |
541 | } | |
542 | } | |
543 | ||
1a4d82fc JJ |
544 | ////////////////////////////////////////////////////////////////////////////// |
545 | ||
1a4d82fc | 546 | mod impls { |
9cc50fc6 | 547 | use mem; |
85aaf69f SL |
548 | use slice; |
549 | use super::*; | |
1a4d82fc | 550 | |
85aaf69f SL |
551 | macro_rules! impl_write { |
552 | ($(($ty:ident, $meth:ident),)*) => {$( | |
553 | #[stable(feature = "rust1", since = "1.0.0")] | |
554 | impl Hash for $ty { | |
555 | fn hash<H: Hasher>(&self, state: &mut H) { | |
556 | state.$meth(*self) | |
557 | } | |
558 | ||
559 | fn hash_slice<H: Hasher>(data: &[$ty], state: &mut H) { | |
9cc50fc6 | 560 | let newlen = data.len() * mem::size_of::<$ty>(); |
85aaf69f SL |
561 | let ptr = data.as_ptr() as *const u8; |
562 | state.write(unsafe { slice::from_raw_parts(ptr, newlen) }) | |
1a4d82fc JJ |
563 | } |
564 | } | |
85aaf69f | 565 | )*} |
1a4d82fc JJ |
566 | } |
567 | ||
85aaf69f SL |
568 | impl_write! { |
569 | (u8, write_u8), | |
570 | (u16, write_u16), | |
571 | (u32, write_u32), | |
572 | (u64, write_u64), | |
573 | (usize, write_usize), | |
574 | (i8, write_i8), | |
575 | (i16, write_i16), | |
576 | (i32, write_i32), | |
577 | (i64, write_i64), | |
578 | (isize, write_isize), | |
32a655c1 SL |
579 | (u128, write_u128), |
580 | (i128, write_i128), | |
581 | } | |
1a4d82fc | 582 | |
85aaf69f SL |
583 | #[stable(feature = "rust1", since = "1.0.0")] |
584 | impl Hash for bool { | |
585 | fn hash<H: Hasher>(&self, state: &mut H) { | |
586 | state.write_u8(*self as u8) | |
1a4d82fc JJ |
587 | } |
588 | } | |
589 | ||
85aaf69f SL |
590 | #[stable(feature = "rust1", since = "1.0.0")] |
591 | impl Hash for char { | |
592 | fn hash<H: Hasher>(&self, state: &mut H) { | |
593 | state.write_u32(*self as u32) | |
1a4d82fc JJ |
594 | } |
595 | } | |
596 | ||
85aaf69f SL |
597 | #[stable(feature = "rust1", since = "1.0.0")] |
598 | impl Hash for str { | |
599 | fn hash<H: Hasher>(&self, state: &mut H) { | |
1a4d82fc | 600 | state.write(self.as_bytes()); |
85aaf69f | 601 | state.write_u8(0xff) |
1a4d82fc JJ |
602 | } |
603 | } | |
604 | ||
605 | macro_rules! impl_hash_tuple { | |
606 | () => ( | |
85aaf69f SL |
607 | #[stable(feature = "rust1", since = "1.0.0")] |
608 | impl Hash for () { | |
609 | fn hash<H: Hasher>(&self, _state: &mut H) {} | |
1a4d82fc JJ |
610 | } |
611 | ); | |
612 | ||
613 | ( $($name:ident)+) => ( | |
85aaf69f | 614 | #[stable(feature = "rust1", since = "1.0.0")] |
041b39d2 | 615 | impl<$($name: Hash),*> Hash for ($($name,)*) where last_type!($($name,)+): ?Sized { |
1a4d82fc | 616 | #[allow(non_snake_case)] |
85aaf69f SL |
617 | fn hash<S: Hasher>(&self, state: &mut S) { |
618 | let ($(ref $name,)*) = *self; | |
619 | $($name.hash(state);)* | |
1a4d82fc JJ |
620 | } |
621 | } | |
622 | ); | |
623 | } | |
624 | ||
041b39d2 XL |
625 | macro_rules! last_type { |
626 | ($a:ident,) => { $a }; | |
627 | ($a:ident, $($rest_a:ident,)+) => { last_type!($($rest_a,)+) }; | |
628 | } | |
629 | ||
1a4d82fc JJ |
630 | impl_hash_tuple! {} |
631 | impl_hash_tuple! { A } | |
632 | impl_hash_tuple! { A B } | |
633 | impl_hash_tuple! { A B C } | |
634 | impl_hash_tuple! { A B C D } | |
635 | impl_hash_tuple! { A B C D E } | |
636 | impl_hash_tuple! { A B C D E F } | |
637 | impl_hash_tuple! { A B C D E F G } | |
638 | impl_hash_tuple! { A B C D E F G H } | |
639 | impl_hash_tuple! { A B C D E F G H I } | |
640 | impl_hash_tuple! { A B C D E F G H I J } | |
641 | impl_hash_tuple! { A B C D E F G H I J K } | |
642 | impl_hash_tuple! { A B C D E F G H I J K L } | |
643 | ||
85aaf69f SL |
644 | #[stable(feature = "rust1", since = "1.0.0")] |
645 | impl<T: Hash> Hash for [T] { | |
646 | fn hash<H: Hasher>(&self, state: &mut H) { | |
1a4d82fc | 647 | self.len().hash(state); |
85aaf69f | 648 | Hash::hash_slice(self, state) |
1a4d82fc JJ |
649 | } |
650 | } | |
651 | ||
652 | ||
85aaf69f SL |
653 | #[stable(feature = "rust1", since = "1.0.0")] |
654 | impl<'a, T: ?Sized + Hash> Hash for &'a T { | |
655 | fn hash<H: Hasher>(&self, state: &mut H) { | |
1a4d82fc JJ |
656 | (**self).hash(state); |
657 | } | |
658 | } | |
659 | ||
85aaf69f SL |
660 | #[stable(feature = "rust1", since = "1.0.0")] |
661 | impl<'a, T: ?Sized + Hash> Hash for &'a mut T { | |
662 | fn hash<H: Hasher>(&self, state: &mut H) { | |
1a4d82fc JJ |
663 | (**self).hash(state); |
664 | } | |
665 | } | |
666 | ||
85aaf69f | 667 | #[stable(feature = "rust1", since = "1.0.0")] |
abe05a73 | 668 | impl<T: ?Sized> Hash for *const T { |
85aaf69f | 669 | fn hash<H: Hasher>(&self, state: &mut H) { |
abe05a73 XL |
670 | if mem::size_of::<Self>() == mem::size_of::<usize>() { |
671 | // Thin pointer | |
672 | state.write_usize(*self as *const () as usize); | |
673 | } else { | |
674 | // Fat pointer | |
675 | let (a, b) = unsafe { | |
676 | *(self as *const Self as *const (usize, usize)) | |
677 | }; | |
678 | state.write_usize(a); | |
679 | state.write_usize(b); | |
680 | } | |
1a4d82fc JJ |
681 | } |
682 | } | |
683 | ||
85aaf69f | 684 | #[stable(feature = "rust1", since = "1.0.0")] |
abe05a73 | 685 | impl<T: ?Sized> Hash for *mut T { |
85aaf69f | 686 | fn hash<H: Hasher>(&self, state: &mut H) { |
abe05a73 XL |
687 | if mem::size_of::<Self>() == mem::size_of::<usize>() { |
688 | // Thin pointer | |
689 | state.write_usize(*self as *const () as usize); | |
690 | } else { | |
691 | // Fat pointer | |
692 | let (a, b) = unsafe { | |
693 | *(self as *const Self as *const (usize, usize)) | |
694 | }; | |
695 | state.write_usize(a); | |
696 | state.write_usize(b); | |
697 | } | |
1a4d82fc JJ |
698 | } |
699 | } | |
700 | } |