9
9
// except according to those terms.
10
10
11
11
use std:: mem;
12
+ use std:: hash:: Hasher ;
12
13
use rustc_data_structures:: blake2b:: Blake2bHasher ;
13
14
use rustc:: ty:: util:: ArchIndependentHasher ;
14
15
use ich:: Fingerprint ;
16
+ use rustc_serialize:: leb128:: write_unsigned_leb128;
15
17
16
18
#[ derive( Debug ) ]
17
19
pub struct IchHasher {
18
20
state : ArchIndependentHasher < Blake2bHasher > ,
21
+ leb128_helper : Vec < u8 > ,
19
22
bytes_hashed : u64 ,
20
23
}
21
24
@@ -24,6 +27,7 @@ impl IchHasher {
24
27
let hash_size = mem:: size_of :: < Fingerprint > ( ) ;
25
28
IchHasher {
26
29
state : ArchIndependentHasher :: new ( Blake2bHasher :: new ( hash_size, & [ ] ) ) ,
30
+ leb128_helper : vec ! [ ] ,
27
31
bytes_hashed : 0
28
32
}
29
33
}
@@ -37,9 +41,19 @@ impl IchHasher {
37
41
fingerprint. 0 . copy_from_slice ( self . state . into_inner ( ) . finalize ( ) ) ;
38
42
fingerprint
39
43
}
44
+
45
+ #[ inline]
46
+ fn write_uleb128 ( & mut self , value : u64 ) {
47
+ let len = write_unsigned_leb128 ( & mut self . leb128_helper , 0 , value) ;
48
+ self . state . write ( & self . leb128_helper [ 0 ..len] ) ;
49
+ self . bytes_hashed += len as u64 ;
50
+ }
40
51
}
41
52
42
- impl :: std:: hash:: Hasher for IchHasher {
53
+ // For the non-u8 integer cases we leb128 encode them first. Because small
54
+ // integers dominate, this significantly and cheaply reduces the number of
55
+ // bytes hashed, which is good because blake2b is expensive.
56
+ impl Hasher for IchHasher {
43
57
fn finish ( & self ) -> u64 {
44
58
bug ! ( "Use other finish() implementation to get the full 128-bit hash." ) ;
45
59
}
@@ -49,4 +63,26 @@ impl ::std::hash::Hasher for IchHasher {
49
63
self . state . write ( bytes) ;
50
64
self . bytes_hashed += bytes. len ( ) as u64 ;
51
65
}
66
+
67
+ // There is no need to leb128-encode u8 values.
68
+
69
+ #[ inline]
70
+ fn write_u16 ( & mut self , i : u16 ) {
71
+ self . write_uleb128 ( i as u64 ) ;
72
+ }
73
+
74
+ #[ inline]
75
+ fn write_u32 ( & mut self , i : u32 ) {
76
+ self . write_uleb128 ( i as u64 ) ;
77
+ }
78
+
79
+ #[ inline]
80
+ fn write_u64 ( & mut self , i : u64 ) {
81
+ self . write_uleb128 ( i) ;
82
+ }
83
+
84
+ #[ inline]
85
+ fn write_usize ( & mut self , i : usize ) {
86
+ self . write_uleb128 ( i as u64 ) ;
87
+ }
52
88
}
0 commit comments