1111use std:: hash:: { Hash , Hasher , BuildHasher } ;
1212use std:: marker:: PhantomData ;
1313use 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 ;
2415
2516/// When hashing something that ends up affecting properties like symbol names. We
2617/// 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 {
4132/// and allows for variable output lengths through its type
4233/// parameter.
4334pub struct StableHasher < W > {
44- state : Blake2bHasher ,
35+ state : SipHasher128 ,
4536 bytes_hashed : u64 ,
4637 width : PhantomData < W > ,
4738}
@@ -59,7 +50,7 @@ pub trait StableHasherResult: Sized {
5950impl < W : StableHasherResult > StableHasher < W > {
6051 pub fn new ( ) -> Self {
6152 StableHasher {
62- state : Blake2bHasher :: new ( mem :: size_of :: < W > ( ) , & [ ] ) ,
53+ state : SipHasher128 :: new_with_keys ( 0 , 0 ) ,
6354 bytes_hashed : 0 ,
6455 width : PhantomData ,
6556 }
@@ -71,65 +62,67 @@ impl<W: StableHasherResult> StableHasher<W> {
7162}
7263
7364impl 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+ ]
7892 }
7993}
8094
8195impl 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 )
8999 }
90100}
91101
92102impl 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
96105 }
97106}
98107
99108impl < W > StableHasher < W > {
100109 #[ inline]
101- pub fn finalize ( & mut self ) -> & [ u8 ] {
102- self . state . finalize ( )
110+ pub fn finalize ( self ) -> ( u64 , u64 ) {
111+ self . state . finish128 ( )
103112 }
104113
105114 #[ inline]
106115 pub fn bytes_hashed ( & self ) -> u64 {
107116 self . bytes_hashed
108117 }
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- }
125118}
126119
127120// For the non-u8 integer cases we leb128 encode them first. Because small
128121// integers dominate, this significantly and cheaply reduces the number of
129122// bytes hashed, which is good because blake2b is expensive.
130123impl < W > Hasher for StableHasher < W > {
131124 fn finish ( & self ) -> u64 {
132- panic ! ( "use StableHasher::finish instead" ) ;
125+ panic ! ( "use StableHasher::finalize instead" ) ;
133126 }
134127
135128 #[ inline]
@@ -146,22 +139,32 @@ impl<W> Hasher for StableHasher<W> {
146139
147140 #[ inline]
148141 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 ;
150144 }
151145
152146 #[ inline]
153147 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 ;
155150 }
156151
157152 #[ inline]
158153 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 ;
160162 }
161163
162164 #[ inline]
163165 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 ;
165168 }
166169
167170 #[ inline]
@@ -172,22 +175,32 @@ impl<W> Hasher for StableHasher<W> {
172175
173176 #[ inline]
174177 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 ;
176180 }
177181
178182 #[ inline]
179183 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 ;
181186 }
182187
183188 #[ inline]
184189 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 ;
186198 }
187199
188200 #[ inline]
189201 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 ;
191204 }
192205}
193206
0 commit comments