88// option. This file may not be copied, modified, or distributed
99// except according to those terms.
1010
11- //! An implementation of SipHash 2-4 .
11+ //! An implementation of SipHash.
1212
1313use prelude:: v1:: * ;
1414
15+ use marker:: PhantomData ;
1516use ptr;
16- use super :: Hasher ;
17+
18+ /// An implementation of SipHash 1-3.
19+ ///
20+ /// See: https://131002.net/siphash/
21+ #[ unstable( feature = "sip_hash_13" , issue = "29754" ) ]
22+ #[ derive( Debug , Clone , Default ) ]
23+ pub struct SipHasher13 {
24+ hasher : Hasher < Sip13Rounds > ,
25+ }
26+
27+ /// An implementation of SipHash 2-4.
28+ ///
29+ /// See: https://131002.net/siphash/
30+ #[ unstable( feature = "sip_hash_13" , issue = "29754" ) ]
31+ #[ derive( Debug , Clone , Default ) ]
32+ pub struct SipHasher24 {
33+ hasher : Hasher < Sip24Rounds > ,
34+ }
1735
1836/// An implementation of SipHash 2-4.
1937///
@@ -30,22 +48,31 @@ use super::Hasher;
3048/// Although the SipHash algorithm is considered to be generally strong,
3149/// it is not intended for cryptographic purposes. As such, all
3250/// cryptographic uses of this implementation are _strongly discouraged_.
33- #[ derive( Debug ) ]
3451#[ stable( feature = "rust1" , since = "1.0.0" ) ]
35- pub struct SipHasher {
52+ #[ derive( Debug , Clone , Default ) ]
53+ pub struct SipHasher ( SipHasher24 ) ;
54+
55+ #[ derive( Debug ) ]
56+ struct Hasher < S : Sip > {
3657 k0 : u64 ,
3758 k1 : u64 ,
3859 length : usize , // how many bytes we've processed
60+ state : State , // hash State
61+ tail : u64 , // unprocessed bytes le
62+ ntail : usize , // how many bytes in tail are valid
63+ _marker : PhantomData < S > ,
64+ }
65+
66+ #[ derive( Debug , Clone , Copy ) ]
67+ struct State {
3968 // v0, v2 and v1, v3 show up in pairs in the algorithm,
4069 // and simd implementations of SipHash will use vectors
4170 // of v02 and v13. By placing them in this order in the struct,
4271 // the compiler can pick up on just a few simd optimizations by itself.
43- v0 : u64 , // hash state
72+ v0 : u64 ,
4473 v2 : u64 ,
4574 v1 : u64 ,
4675 v3 : u64 ,
47- tail : u64 , // unprocessed bytes le
48- ntail : usize , // how many bytes in tail are valid
4976}
5077
5178// sadly, these macro definitions can't appear later,
@@ -93,6 +120,9 @@ macro_rules! rotl {
93120}
94121
95122macro_rules! compress {
123+ ( $state: expr) => ( {
124+ compress!( $state. v0, $state. v1, $state. v2, $state. v3)
125+ } ) ;
96126 ( $v0: expr, $v1: expr, $v2: expr, $v3: expr) =>
97127 ( {
98128 $v0 = $v0. wrapping_add( $v1) ; $v1 = rotl!( $v1, 13 ) ; $v1 ^= $v0;
@@ -101,7 +131,7 @@ macro_rules! compress {
101131 $v0 = $v0. wrapping_add( $v3) ; $v3 = rotl!( $v3, 21 ) ; $v3 ^= $v0;
102132 $v2 = $v2. wrapping_add( $v1) ; $v1 = rotl!( $v1, 17 ) ; $v1 ^= $v2;
103133 $v2 = rotl!( $v2, 32 ) ;
104- } )
134+ } ) ;
105135}
106136
107137impl SipHasher {
@@ -116,16 +146,63 @@ impl SipHasher {
116146 #[ inline]
117147 #[ stable( feature = "rust1" , since = "1.0.0" ) ]
118148 pub fn new_with_keys ( key0 : u64 , key1 : u64 ) -> SipHasher {
119- let mut state = SipHasher {
149+ SipHasher ( SipHasher24 :: new_with_keys ( key0, key1) )
150+ }
151+ }
152+
153+
154+ impl SipHasher13 {
155+ /// Creates a new `SipHasher13` with the two initial keys set to 0.
156+ #[ inline]
157+ #[ unstable( feature = "sip_hash_13" , issue = "29754" ) ]
158+ pub fn new ( ) -> SipHasher13 {
159+ SipHasher13 :: new_with_keys ( 0 , 0 )
160+ }
161+
162+ /// Creates a `SipHasher13` that is keyed off the provided keys.
163+ #[ inline]
164+ #[ unstable( feature = "sip_hash_13" , issue = "29754" ) ]
165+ pub fn new_with_keys ( key0 : u64 , key1 : u64 ) -> SipHasher13 {
166+ SipHasher13 {
167+ hasher : Hasher :: new_with_keys ( key0, key1)
168+ }
169+ }
170+ }
171+
172+ impl SipHasher24 {
173+ /// Creates a new `SipHasher24` with the two initial keys set to 0.
174+ #[ inline]
175+ #[ unstable( feature = "sip_hash_13" , issue = "29754" ) ]
176+ pub fn new ( ) -> SipHasher24 {
177+ SipHasher24 :: new_with_keys ( 0 , 0 )
178+ }
179+
180+ /// Creates a `SipHasher24` that is keyed off the provided keys.
181+ #[ inline]
182+ #[ unstable( feature = "sip_hash_13" , issue = "29754" ) ]
183+ pub fn new_with_keys ( key0 : u64 , key1 : u64 ) -> SipHasher24 {
184+ SipHasher24 {
185+ hasher : Hasher :: new_with_keys ( key0, key1)
186+ }
187+ }
188+ }
189+
190+ impl < S : Sip > Hasher < S > {
191+ #[ inline]
192+ fn new_with_keys ( key0 : u64 , key1 : u64 ) -> Hasher < S > {
193+ let mut state = Hasher {
120194 k0 : key0,
121195 k1 : key1,
122196 length : 0 ,
123- v0 : 0 ,
124- v1 : 0 ,
125- v2 : 0 ,
126- v3 : 0 ,
197+ state : State {
198+ v0 : 0 ,
199+ v1 : 0 ,
200+ v2 : 0 ,
201+ v3 : 0 ,
202+ } ,
127203 tail : 0 ,
128204 ntail : 0 ,
205+ _marker : PhantomData ,
129206 } ;
130207 state. reset ( ) ;
131208 state
@@ -134,16 +211,54 @@ impl SipHasher {
134211 #[ inline]
135212 fn reset ( & mut self ) {
136213 self . length = 0 ;
137- self . v0 = self . k0 ^ 0x736f6d6570736575 ;
138- self . v1 = self . k1 ^ 0x646f72616e646f6d ;
139- self . v2 = self . k0 ^ 0x6c7967656e657261 ;
140- self . v3 = self . k1 ^ 0x7465646279746573 ;
214+ self . state . v0 = self . k0 ^ 0x736f6d6570736575 ;
215+ self . state . v1 = self . k1 ^ 0x646f72616e646f6d ;
216+ self . state . v2 = self . k0 ^ 0x6c7967656e657261 ;
217+ self . state . v3 = self . k1 ^ 0x7465646279746573 ;
141218 self . ntail = 0 ;
142219 }
143220}
144221
145222#[ stable( feature = "rust1" , since = "1.0.0" ) ]
146- impl Hasher for SipHasher {
223+ impl super :: Hasher for SipHasher {
224+ #[ inline]
225+ fn write ( & mut self , msg : & [ u8 ] ) {
226+ self . 0 . write ( msg)
227+ }
228+
229+ #[ inline]
230+ fn finish ( & self ) -> u64 {
231+ self . 0 . finish ( )
232+ }
233+ }
234+
235+ #[ unstable( feature = "sip_hash_13" , issue = "29754" ) ]
236+ impl super :: Hasher for SipHasher13 {
237+ #[ inline]
238+ fn write ( & mut self , msg : & [ u8 ] ) {
239+ self . hasher . write ( msg)
240+ }
241+
242+ #[ inline]
243+ fn finish ( & self ) -> u64 {
244+ self . hasher . finish ( )
245+ }
246+ }
247+
248+ #[ unstable( feature = "sip_hash_13" , issue = "29754" ) ]
249+ impl super :: Hasher for SipHasher24 {
250+ #[ inline]
251+ fn write ( & mut self , msg : & [ u8 ] ) {
252+ self . hasher . write ( msg)
253+ }
254+
255+ #[ inline]
256+ fn finish ( & self ) -> u64 {
257+ self . hasher . finish ( )
258+ }
259+ }
260+
261+ impl < S : Sip > super :: Hasher for Hasher < S > {
147262 #[ inline]
148263 fn write ( & mut self , msg : & [ u8 ] ) {
149264 let length = msg. len ( ) ;
@@ -161,10 +276,9 @@ impl Hasher for SipHasher {
161276
162277 let m = self . tail | u8to64_le ! ( msg, 0 , needed) << 8 * self . ntail ;
163278
164- self . v3 ^= m;
165- compress ! ( self . v0, self . v1, self . v2, self . v3) ;
166- compress ! ( self . v0, self . v1, self . v2, self . v3) ;
167- self . v0 ^= m;
279+ self . state . v3 ^= m;
280+ S :: c_rounds ( & mut self . state ) ;
281+ self . state . v0 ^= m;
168282
169283 self . ntail = 0 ;
170284 }
@@ -177,10 +291,9 @@ impl Hasher for SipHasher {
177291 while i < len - left {
178292 let mi = unsafe { load_u64_le ( msg, i) } ;
179293
180- self . v3 ^= mi;
181- compress ! ( self . v0, self . v1, self . v2, self . v3) ;
182- compress ! ( self . v0, self . v1, self . v2, self . v3) ;
183- self . v0 ^= mi;
294+ self . state . v3 ^= mi;
295+ S :: c_rounds ( & mut self . state ) ;
296+ self . state . v0 ^= mi;
184297
185298 i += 8 ;
186299 }
@@ -191,49 +304,81 @@ impl Hasher for SipHasher {
191304
192305 #[ inline]
193306 fn finish ( & self ) -> u64 {
194- let mut v0 = self . v0 ;
195- let mut v1 = self . v1 ;
196- let mut v2 = self . v2 ;
197- let mut v3 = self . v3 ;
307+ let mut state = self . state ;
198308
199309 let b: u64 = ( ( self . length as u64 & 0xff ) << 56 ) | self . tail ;
200310
201- v3 ^= b;
202- compress ! ( v0, v1, v2, v3) ;
203- compress ! ( v0, v1, v2, v3) ;
204- v0 ^= b;
311+ state. v3 ^= b;
312+ S :: c_rounds ( & mut state) ;
313+ state. v0 ^= b;
205314
206- v2 ^= 0xff ;
207- compress ! ( v0, v1, v2, v3) ;
208- compress ! ( v0, v1, v2, v3) ;
209- compress ! ( v0, v1, v2, v3) ;
210- compress ! ( v0, v1, v2, v3) ;
315+ state. v2 ^= 0xff ;
316+ S :: d_rounds ( & mut state) ;
211317
212- v0 ^ v1 ^ v2 ^ v3
318+ state . v0 ^ state . v1 ^ state . v2 ^ state . v3
213319 }
214320}
215321
216- #[ stable( feature = "rust1" , since = "1.0.0" ) ]
217- impl Clone for SipHasher {
322+ impl < S : Sip > Clone for Hasher < S > {
218323 #[ inline]
219- fn clone ( & self ) -> SipHasher {
220- SipHasher {
324+ fn clone ( & self ) -> Hasher < S > {
325+ Hasher {
221326 k0 : self . k0 ,
222327 k1 : self . k1 ,
223328 length : self . length ,
224- v0 : self . v0 ,
225- v1 : self . v1 ,
226- v2 : self . v2 ,
227- v3 : self . v3 ,
329+ state : self . state ,
228330 tail : self . tail ,
229331 ntail : self . ntail ,
332+ _marker : self . _marker ,
230333 }
231334 }
232335}
233336
234- #[ stable( feature = "rust1" , since = "1.0.0" ) ]
235- impl Default for SipHasher {
236- fn default ( ) -> SipHasher {
237- SipHasher :: new ( )
337+ impl < S : Sip > Default for Hasher < S > {
338+ #[ inline]
339+ fn default ( ) -> Hasher < S > {
340+ Hasher :: new_with_keys ( 0 , 0 )
341+ }
342+ }
343+
344+ #[ doc( hidden) ]
345+ trait Sip {
346+ fn c_rounds ( & mut State ) ;
347+ fn d_rounds ( & mut State ) ;
348+ }
349+
350+ #[ derive( Debug , Clone , Default ) ]
351+ struct Sip13Rounds ;
352+
353+ impl Sip for Sip13Rounds {
354+ #[ inline]
355+ fn c_rounds ( state : & mut State ) {
356+ compress ! ( state) ;
357+ }
358+
359+ #[ inline]
360+ fn d_rounds ( state : & mut State ) {
361+ compress ! ( state) ;
362+ compress ! ( state) ;
363+ compress ! ( state) ;
364+ }
365+ }
366+
367+ #[ derive( Debug , Clone , Default ) ]
368+ struct Sip24Rounds ;
369+
370+ impl Sip for Sip24Rounds {
371+ #[ inline]
372+ fn c_rounds ( state : & mut State ) {
373+ compress ! ( state) ;
374+ compress ! ( state) ;
375+ }
376+
377+ #[ inline]
378+ fn d_rounds ( state : & mut State ) {
379+ compress ! ( state) ;
380+ compress ! ( state) ;
381+ compress ! ( state) ;
382+ compress ! ( state) ;
238383 }
239384}
0 commit comments