@@ -12,6 +12,8 @@ use std::collections::{HashMap, HashSet};
12
12
use std:: default:: Default ;
13
13
use std:: hash:: { Hasher , Hash , BuildHasherDefault } ;
14
14
use std:: ops:: BitXor ;
15
+ use std:: mem:: size_of;
16
+ use byteorder:: { ByteOrder , NativeEndian } ;
15
17
16
18
pub type FxHashMap < K , V > = HashMap < K , V , BuildHasherDefault < FxHasher > > ;
17
19
pub type FxHashSet < V > = HashSet < V , BuildHasherDefault < FxHasher > > ;
@@ -37,6 +39,7 @@ pub fn FxHashSet<V: Hash + Eq>() -> FxHashSet<V> {
37
39
/// out-performs an FNV-based hash within rustc itself -- the collision rate is
38
40
/// similar or slightly worse than FNV, but the speed of the hash function
39
41
/// itself is much higher because it works on up to 8 bytes at a time.
42
+ #[ derive( Copy , Clone ) ]
40
43
pub struct FxHasher {
41
44
hash : usize
42
45
}
@@ -62,11 +65,30 @@ impl FxHasher {
62
65
63
66
impl Hasher for FxHasher {
64
67
#[ inline]
65
- fn write ( & mut self , bytes : & [ u8 ] ) {
66
- for byte in bytes {
67
- let i = * byte;
68
- self . add_to_hash ( i as usize ) ;
68
+ fn write ( & mut self , mut bytes : & [ u8 ] ) {
69
+ #[ cfg( target_pointer_width = "32" ) ]
70
+ let read_usize = |bytes| NativeEndian :: read_u32 ( bytes) ;
71
+ #[ cfg( target_pointer_width = "64" ) ]
72
+ let read_usize = |bytes| NativeEndian :: read_u64 ( bytes) ;
73
+
74
+ let mut hash = * self ;
75
+ assert ! ( size_of:: <usize >( ) <= 8 ) ;
76
+ while bytes. len ( ) >= size_of :: < usize > ( ) {
77
+ hash. add_to_hash ( read_usize ( bytes) as usize ) ;
78
+ bytes = & bytes[ size_of :: < usize > ( ) ..] ;
69
79
}
80
+ if ( size_of :: < usize > ( ) > 4 ) && ( bytes. len ( ) >= 4 ) {
81
+ hash. add_to_hash ( NativeEndian :: read_u32 ( bytes) as usize ) ;
82
+ bytes = & bytes[ 4 ..] ;
83
+ }
84
+ if ( size_of :: < usize > ( ) > 2 ) && bytes. len ( ) >= 2 {
85
+ hash. add_to_hash ( NativeEndian :: read_u16 ( bytes) as usize ) ;
86
+ bytes = & bytes[ 2 ..] ;
87
+ }
88
+ if ( size_of :: < usize > ( ) > 1 ) && bytes. len ( ) >= 1 {
89
+ hash. add_to_hash ( bytes[ 0 ] as usize ) ;
90
+ }
91
+ * self = hash;
70
92
}
71
93
72
94
#[ inline]
0 commit comments