11
11
use std:: hash:: { Hash , Hasher , BuildHasher } ;
12
12
use std:: marker:: PhantomData ;
13
13
use std:: mem;
14
- use blake2b:: Blake2bHasher ;
15
- use rustc_serialize:: leb128;
16
-
17
- fn write_unsigned_leb128_to_buf ( buf : & mut [ u8 ; 16 ] , value : u64 ) -> usize {
18
- leb128:: write_unsigned_leb128_to ( value as u128 , |i, v| buf[ i] = v)
19
- }
20
-
21
- fn write_signed_leb128_to_buf ( buf : & mut [ u8 ; 16 ] , value : i64 ) -> usize {
22
- leb128:: write_signed_leb128_to ( value as i128 , |i, v| buf[ i] = v)
23
- }
14
+ use sip128:: SipHasher128 ;
24
15
25
16
/// When hashing something that ends up affecting properties like symbol names. We
26
17
/// want these symbol names to be calculated independent of other factors like
@@ -41,7 +32,7 @@ fn write_signed_leb128_to_buf(buf: &mut [u8; 16], value: i64) -> usize {
41
32
/// and allows for variable output lengths through its type
42
33
/// parameter.
43
34
pub struct StableHasher < W > {
44
- state : Blake2bHasher ,
35
+ state : SipHasher128 ,
45
36
bytes_hashed : u64 ,
46
37
width : PhantomData < W > ,
47
38
}
@@ -59,7 +50,7 @@ pub trait StableHasherResult: Sized {
59
50
impl < W : StableHasherResult > StableHasher < W > {
60
51
pub fn new ( ) -> Self {
61
52
StableHasher {
62
- state : Blake2bHasher :: new ( mem :: size_of :: < W > ( ) , & [ ] ) ,
53
+ state : SipHasher128 :: new_with_keys ( 0 , 0 ) ,
63
54
bytes_hashed : 0 ,
64
55
width : PhantomData ,
65
56
}
@@ -71,65 +62,67 @@ impl<W: StableHasherResult> StableHasher<W> {
71
62
}
72
63
73
64
impl StableHasherResult for [ u8 ; 20 ] {
74
- fn finish ( mut hasher : StableHasher < Self > ) -> Self {
75
- let mut result: [ u8 ; 20 ] = [ 0 ; 20 ] ;
76
- result. copy_from_slice ( hasher. state . finalize ( ) ) ;
77
- result
65
+ fn finish ( hasher : StableHasher < Self > ) -> Self {
66
+ let ( _0, _1) = hasher. finalize ( ) ;
67
+
68
+ [
69
+ ( _0 >> 0 ) as u8 ,
70
+ ( _0 >> 8 ) as u8 ,
71
+ ( _0 >> 16 ) as u8 ,
72
+ ( _0 >> 24 ) as u8 ,
73
+ ( _0 >> 32 ) as u8 ,
74
+ ( _0 >> 40 ) as u8 ,
75
+ ( _0 >> 48 ) as u8 ,
76
+ ( _0 >> 56 ) as u8 ,
77
+
78
+ 17 ,
79
+ 33 ,
80
+ 47 ,
81
+ 3 ,
82
+
83
+ ( _1 >> 0 ) as u8 ,
84
+ ( _1 >> 8 ) as u8 ,
85
+ ( _1 >> 16 ) as u8 ,
86
+ ( _1 >> 24 ) as u8 ,
87
+ ( _1 >> 32 ) as u8 ,
88
+ ( _1 >> 40 ) as u8 ,
89
+ ( _1 >> 48 ) as u8 ,
90
+ ( _1 >> 56 ) as u8 ,
91
+ ]
78
92
}
79
93
}
80
94
81
95
impl StableHasherResult for u128 {
82
- fn finish ( mut hasher : StableHasher < Self > ) -> Self {
83
- let hash_bytes: & [ u8 ] = hasher. finalize ( ) ;
84
- assert ! ( hash_bytes. len( ) >= mem:: size_of:: <u128 >( ) ) ;
85
-
86
- unsafe {
87
- :: std:: ptr:: read_unaligned ( hash_bytes. as_ptr ( ) as * const u128 )
88
- }
96
+ fn finish ( hasher : StableHasher < Self > ) -> Self {
97
+ let ( _0, _1) = hasher. finalize ( ) ;
98
+ ( _0 as u128 ) | ( ( _1 as u128 ) << 64 )
89
99
}
90
100
}
91
101
92
102
impl StableHasherResult for u64 {
93
- fn finish ( mut hasher : StableHasher < Self > ) -> Self {
94
- hasher. state . finalize ( ) ;
95
- hasher. state . finish ( )
103
+ fn finish ( hasher : StableHasher < Self > ) -> Self {
104
+ hasher. finalize ( ) . 0
96
105
}
97
106
}
98
107
99
108
impl < W > StableHasher < W > {
100
109
#[ inline]
101
- pub fn finalize ( & mut self ) -> & [ u8 ] {
102
- self . state . finalize ( )
110
+ pub fn finalize ( self ) -> ( u64 , u64 ) {
111
+ self . state . finish128 ( )
103
112
}
104
113
105
114
#[ inline]
106
115
pub fn bytes_hashed ( & self ) -> u64 {
107
116
self . bytes_hashed
108
117
}
109
-
110
- #[ inline]
111
- fn write_uleb128 ( & mut self , value : u64 ) {
112
- let mut buf = [ 0 ; 16 ] ;
113
- let len = write_unsigned_leb128_to_buf ( & mut buf, value) ;
114
- self . state . write ( & buf[ ..len] ) ;
115
- self . bytes_hashed += len as u64 ;
116
- }
117
-
118
- #[ inline]
119
- fn write_ileb128 ( & mut self , value : i64 ) {
120
- let mut buf = [ 0 ; 16 ] ;
121
- let len = write_signed_leb128_to_buf ( & mut buf, value) ;
122
- self . state . write ( & buf[ ..len] ) ;
123
- self . bytes_hashed += len as u64 ;
124
- }
125
118
}
126
119
127
120
// For the non-u8 integer cases we leb128 encode them first. Because small
128
121
// integers dominate, this significantly and cheaply reduces the number of
129
122
// bytes hashed, which is good because blake2b is expensive.
130
123
impl < W > Hasher for StableHasher < W > {
131
124
fn finish ( & self ) -> u64 {
132
- panic ! ( "use StableHasher::finish instead" ) ;
125
+ panic ! ( "use StableHasher::finalize instead" ) ;
133
126
}
134
127
135
128
#[ inline]
@@ -146,22 +139,32 @@ impl<W> Hasher for StableHasher<W> {
146
139
147
140
#[ inline]
148
141
fn write_u16 ( & mut self , i : u16 ) {
149
- self . write_uleb128 ( i as u64 ) ;
142
+ self . state . write_u16 ( i. to_le ( ) ) ;
143
+ self . bytes_hashed += 2 ;
150
144
}
151
145
152
146
#[ inline]
153
147
fn write_u32 ( & mut self , i : u32 ) {
154
- self . write_uleb128 ( i as u64 ) ;
148
+ self . state . write_u32 ( i. to_le ( ) ) ;
149
+ self . bytes_hashed += 4 ;
155
150
}
156
151
157
152
#[ inline]
158
153
fn write_u64 ( & mut self , i : u64 ) {
159
- self . write_uleb128 ( i) ;
154
+ self . state . write_u64 ( i. to_le ( ) ) ;
155
+ self . bytes_hashed += 8 ;
156
+ }
157
+
158
+ #[ inline]
159
+ fn write_u128 ( & mut self , i : u128 ) {
160
+ self . state . write_u128 ( i. to_le ( ) ) ;
161
+ self . bytes_hashed += 16 ;
160
162
}
161
163
162
164
#[ inline]
163
165
fn write_usize ( & mut self , i : usize ) {
164
- self . write_uleb128 ( i as u64 ) ;
166
+ self . state . write_usize ( i. to_le ( ) ) ;
167
+ self . bytes_hashed += :: std:: mem:: size_of :: < usize > ( ) as u64 ;
165
168
}
166
169
167
170
#[ inline]
@@ -172,22 +175,32 @@ impl<W> Hasher for StableHasher<W> {
172
175
173
176
#[ inline]
174
177
fn write_i16 ( & mut self , i : i16 ) {
175
- self . write_ileb128 ( i as i64 ) ;
178
+ self . state . write_i16 ( i. to_le ( ) ) ;
179
+ self . bytes_hashed += 2 ;
176
180
}
177
181
178
182
#[ inline]
179
183
fn write_i32 ( & mut self , i : i32 ) {
180
- self . write_ileb128 ( i as i64 ) ;
184
+ self . state . write_i32 ( i. to_le ( ) ) ;
185
+ self . bytes_hashed += 4 ;
181
186
}
182
187
183
188
#[ inline]
184
189
fn write_i64 ( & mut self , i : i64 ) {
185
- self . write_ileb128 ( i) ;
190
+ self . state . write_i64 ( i. to_le ( ) ) ;
191
+ self . bytes_hashed += 8 ;
192
+ }
193
+
194
+ #[ inline]
195
+ fn write_i128 ( & mut self , i : i128 ) {
196
+ self . state . write_i128 ( i. to_le ( ) ) ;
197
+ self . bytes_hashed += 16 ;
186
198
}
187
199
188
200
#[ inline]
189
201
fn write_isize ( & mut self , i : isize ) {
190
- self . write_ileb128 ( i as i64 ) ;
202
+ self . state . write_isize ( i. to_le ( ) ) ;
203
+ self . bytes_hashed += :: std:: mem:: size_of :: < isize > ( ) as u64 ;
191
204
}
192
205
}
193
206
0 commit comments