1
1
//! Stable hasher adapted for cross-platform independent hash.
2
2
3
- use crate :: sip128:: SipHasher128 ;
4
-
5
3
use std:: fmt;
6
4
use std:: hash:: Hasher ;
7
5
8
6
#[ cfg( test) ]
9
7
mod tests;
10
8
9
+ /// Extended the [`Hasher`] trait for use with [`StableHasher`].
10
+ ///
11
+ /// It permits returning an arbitrary type as the [`Self::Hash`] type
12
+ /// contrary to the [`Hasher`] trait which can only return `u64`. This
13
+ /// is useful when the hasher uses a different representation.
14
+ ///
15
+ /// # Example
16
+ ///
17
+ /// ```
18
+ /// use std::hash::Hasher;
19
+ /// use rustc_stable_hash::ExtendedHasher;
20
+ ///
21
+ /// struct DumbHasher(u128);
22
+ ///
23
+ /// impl Hasher for DumbHasher {
24
+ /// fn write(&mut self, a: &[u8]) {
25
+ /// # self.0 = a.iter().fold(0u128, |acc, a| acc + (*a as u128)) + self.0;
26
+ /// // ...
27
+ /// }
28
+ ///
29
+ /// fn finish(&self) -> u64 {
30
+ /// self.0 as u64 // really dumb
31
+ /// }
32
+ /// }
33
+ ///
34
+ /// impl ExtendedHasher for DumbHasher {
35
+ /// type Hash = u128;
36
+ ///
37
+ /// fn short_write<const LEN: usize>(&mut self, bytes: [u8; LEN]) {
38
+ /// self.write(&bytes)
39
+ /// }
40
+ ///
41
+ /// fn finish(self) -> Self::Hash {
42
+ /// self.0
43
+ /// }
44
+ /// }
45
+ /// ```
46
+ pub trait ExtendedHasher : Hasher {
47
+ /// Type returned by the hasher.
48
+ type Hash ;
49
+
50
+ /// Optimized version of [`Hasher::write`] but for small write.
51
+ fn short_write < const LEN : usize > ( & mut self , bytes : [ u8 ; LEN ] ) ;
52
+
53
+ /// Finalization method of the hasher to return the [`Hash`].
54
+ fn finish ( self ) -> Self :: Hash ;
55
+ }
56
+
11
57
/// A Stable Hasher adapted for cross-platform independent hash.
12
58
///
13
59
/// When hashing something that ends up affecting properties like symbol names,
@@ -21,24 +67,26 @@ mod tests;
21
67
/// # Example
22
68
///
23
69
/// ```
24
- /// use rustc_stable_hash::{StableHasher, StableHasherResult};
70
+ /// use rustc_stable_hash::{StableHasher, StableHasherResult, StableSipHasher128 };
25
71
/// use std::hash::Hasher;
26
72
///
27
73
/// struct Hash128([u64; 2]);
28
74
/// impl StableHasherResult for Hash128 {
75
+ /// type Hash = [u64; 2];
76
+ ///
29
77
/// fn finish(hash: [u64; 2]) -> Hash128 {
30
78
/// Hash128(hash)
31
79
/// }
32
80
/// }
33
81
///
34
- /// let mut hasher = StableHasher ::new();
82
+ /// let mut hasher = StableSipHasher128 ::new();
35
83
/// hasher.write_usize(0xFA);
36
84
///
37
85
/// let hash: Hash128 = hasher.finish();
38
86
/// ```
39
87
#[ must_use]
40
- pub struct StableHasher {
41
- state : SipHasher128 ,
88
+ pub struct StableHasher < H : ExtendedHasher > {
89
+ state : H ,
42
90
}
43
91
44
92
/// Trait for retrieving the result of the stable hashing operation.
@@ -51,6 +99,8 @@ pub struct StableHasher {
51
99
/// struct Hash128(u128);
52
100
///
53
101
/// impl StableHasherResult for Hash128 {
102
+ /// type Hash = [u64; 2];
103
+ ///
54
104
/// fn finish(hash: [u64; 2]) -> Hash128 {
55
105
/// let upper: u128 = hash[0] as u128;
56
106
/// let lower: u128 = hash[1] as u128;
@@ -60,23 +110,36 @@ pub struct StableHasher {
60
110
/// }
61
111
/// ```
62
112
pub trait StableHasherResult : Sized {
113
+ type Hash ;
114
+
63
115
/// Retrieving the finalized state of the [`StableHasher`] and construct
64
116
/// an [`Self`] containing the hash.
65
- fn finish ( hasher : [ u64 ; 2 ] ) -> Self ;
117
+ fn finish ( hash : Self :: Hash ) -> Self ;
66
118
}
67
119
68
- impl StableHasher {
120
+ impl < H : ExtendedHasher + Default > StableHasher < H > {
69
121
/// Creates a new [`StableHasher`].
70
122
///
71
123
/// To be used with the [`Hasher`] implementation and [`StableHasher::finish`].
124
+ // TODO: Should this exist as is? or maybe it should take an `ExtendedHasher` as input?
72
125
#[ inline]
73
126
#[ must_use]
74
127
pub fn new ( ) -> Self {
128
+ Default :: default ( )
129
+ }
130
+ }
131
+
132
+ impl < H : ExtendedHasher + Default > Default for StableHasher < H > {
133
+ #[ inline]
134
+ #[ must_use]
135
+ fn default ( ) -> Self {
75
136
StableHasher {
76
- state : SipHasher128 :: new_with_keys ( 0 , 0 ) ,
137
+ state : Default :: default ( ) ,
77
138
}
78
139
}
140
+ }
79
141
142
+ impl < H : ExtendedHasher > StableHasher < H > {
80
143
/// Returns the typed-hash value for the values written.
81
144
///
82
145
/// The resulting typed-hash value is constructed from an
@@ -85,23 +148,23 @@ impl StableHasher {
85
148
/// To be used in-place of [`Hasher::finish`].
86
149
#[ inline]
87
150
#[ must_use]
88
- pub fn finish < W : StableHasherResult > ( self ) -> W {
89
- W :: finish ( self . state . finish128 ( ) )
151
+ pub fn finish < W : StableHasherResult < Hash = H :: Hash > > ( self ) -> W {
152
+ W :: finish ( self . state . finish ( ) )
90
153
}
91
154
}
92
155
93
- impl fmt:: Debug for StableHasher {
156
+ impl < H : ExtendedHasher + fmt:: Debug > fmt :: Debug for StableHasher < H > {
94
157
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
95
158
write ! ( f, "{:?}" , self . state)
96
159
}
97
160
}
98
161
99
- impl Hasher for StableHasher {
162
+ impl < H : ExtendedHasher > Hasher for StableHasher < H > {
100
163
/// Returns a combined hash.
101
164
///
102
165
/// For greater precision use instead [`StableHasher::finish`].
103
166
fn finish ( & self ) -> u64 {
104
- self . state . finish ( )
167
+ Hasher :: finish ( & self . state )
105
168
}
106
169
107
170
#[ inline]
@@ -192,7 +255,7 @@ impl Hasher for StableHasher {
192
255
// Cold path
193
256
#[ cold]
194
257
#[ inline( never) ]
195
- fn hash_value ( state : & mut SipHasher128 , value : u64 ) {
258
+ fn hash_value < H : ExtendedHasher > ( state : & mut H , value : u64 ) {
196
259
state. write_u8 ( 0xFF ) ;
197
260
state. short_write ( value. to_le_bytes ( ) ) ;
198
261
}
0 commit comments