99// except according to those terms.
1010
1111use std:: mem;
12+ use std:: hash:: Hasher ;
1213use rustc_data_structures:: blake2b:: Blake2bHasher ;
1314use rustc:: ty:: util:: ArchIndependentHasher ;
1415use ich:: Fingerprint ;
16+ use rustc_serialize:: leb128:: write_unsigned_leb128;
1517
1618#[ derive( Debug ) ]
1719pub struct IchHasher {
1820 state : ArchIndependentHasher < Blake2bHasher > ,
21+ leb128_helper : Vec < u8 > ,
1922 bytes_hashed : u64 ,
2023}
2124
@@ -24,6 +27,7 @@ impl IchHasher {
2427 let hash_size = mem:: size_of :: < Fingerprint > ( ) ;
2528 IchHasher {
2629 state : ArchIndependentHasher :: new ( Blake2bHasher :: new ( hash_size, & [ ] ) ) ,
30+ leb128_helper : vec ! [ ] ,
2731 bytes_hashed : 0
2832 }
2933 }
@@ -37,9 +41,19 @@ impl IchHasher {
3741 fingerprint. 0 . copy_from_slice ( self . state . into_inner ( ) . finalize ( ) ) ;
3842 fingerprint
3943 }
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+ }
4051}
4152
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 {
4357 fn finish ( & self ) -> u64 {
4458 bug ! ( "Use other finish() implementation to get the full 128-bit hash." ) ;
4559 }
@@ -49,4 +63,26 @@ impl ::std::hash::Hasher for IchHasher {
4963 self . state . write ( bytes) ;
5064 self . bytes_hashed += bytes. len ( ) as u64 ;
5165 }
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+ }
5288}
0 commit comments