2727use clone:: Clone ;
2828use container:: Container ;
2929use default:: Default ;
30+ use int;
3031use io:: { IoResult , Writer } ;
3132use iter:: Iterator ;
3233use result:: Ok ;
3334use slice:: ImmutableVector ;
35+ use uint;
3436
3537use super :: { Hash , Hasher } ;
3638
@@ -43,7 +45,7 @@ pub struct SipState {
4345 v1 : u64 ,
4446 v2 : u64 ,
4547 v3 : u64 ,
46- tail : [ u8 , .. 8 ] , // unprocessed bytes
48+ tail : u64 , // unprocessed bytes le
4749 ntail : uint , // how many bytes in tail are valid
4850}
4951
@@ -60,7 +62,17 @@ macro_rules! u8to64_le (
6062 $buf[ 4 +$i] as u64 << 32 |
6163 $buf[ 5 +$i] as u64 << 40 |
6264 $buf[ 6 +$i] as u64 << 48 |
63- $buf[ 7 +$i] as u64 << 56 )
65+ $buf[ 7 +$i] as u64 << 56 ) ;
66+ ( $buf: expr, $i: expr, $len: expr) =>
67+ ( {
68+ let mut t = 0 ;
69+ let mut out = 0u64 ;
70+ while t < $len {
71+ out |= $buf[ t+$i] as u64 << t* 8 ;
72+ t += 1 ;
73+ }
74+ out
75+ } ) ;
6476)
6577
6678macro_rules! rotl (
@@ -98,7 +110,7 @@ impl SipState {
98110 v1 : 0 ,
99111 v2 : 0 ,
100112 v3 : 0 ,
101- tail : [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ] ,
113+ tail : 0 ,
102114 ntail : 0 ,
103115 } ;
104116 state. reset ( ) ;
@@ -124,15 +136,7 @@ impl SipState {
124136 let mut v2 = self . v2 ;
125137 let mut v3 = self . v3 ;
126138
127- let mut b : u64 = ( self . length as u64 & 0xff ) << 56 ;
128-
129- if self . ntail > 0 { b |= self . tail [ 0 ] as u64 << 0 ; }
130- if self . ntail > 1 { b |= self . tail [ 1 ] as u64 << 8 ; }
131- if self . ntail > 2 { b |= self . tail [ 2 ] as u64 << 16 ; }
132- if self . ntail > 3 { b |= self . tail [ 3 ] as u64 << 24 ; }
133- if self . ntail > 4 { b |= self . tail [ 4 ] as u64 << 32 ; }
134- if self . ntail > 5 { b |= self . tail [ 5 ] as u64 << 40 ; }
135- if self . ntail > 6 { b |= self . tail [ 6 ] as u64 << 48 ; }
139+ let b: u64 = ( ( self . length as u64 & 0xff ) << 56 ) | self . tail ;
136140
137141 v3 ^= b;
138142 compress ! ( v0, v1, v2, v3) ;
@@ -147,8 +151,38 @@ impl SipState {
147151
148152 v0 ^ v1 ^ v2 ^ v3
149153 }
154+
155+ #[ inline]
156+ fn write_le ( & mut self , n : u64 , size : uint ) {
157+ self . tail |= n << 8 * self . ntail ;
158+ self . ntail += size;
159+
160+ if self . ntail >= 8 {
161+ let m = self . tail ;
162+
163+ self . v3 ^= m;
164+ compress ! ( self . v0, self . v1, self . v2, self . v3) ;
165+ compress ! ( self . v0, self . v1, self . v2, self . v3) ;
166+ self . v0 ^= m;
167+
168+ self . ntail -= 8 ;
169+ if self . ntail == 0 {
170+ self . tail = 0 ;
171+ } else {
172+ self . tail = n >> 64 - 8 * self . ntail ;
173+ }
174+ }
175+ }
150176}
151177
178+ macro_rules! make_write_le(
179+ ( $this: expr, $n: expr, $size: expr) => ( {
180+ $this. write_le( $n as u64 , $size) ;
181+ $this. length += $size;
182+ Ok ( ( ) )
183+ } )
184+ )
185+
152186impl Writer for SipState {
153187 #[ inline]
154188 fn write ( & mut self , msg : & [ u8 ] ) -> IoResult < ( ) > {
@@ -159,24 +193,13 @@ impl Writer for SipState {
159193
160194 if self . ntail != 0 {
161195 needed = 8 - self . ntail ;
162-
163196 if length < needed {
164- let mut t = 0 ;
165- while t < length {
166- self . tail [ self . ntail +t] = msg[ t] ;
167- t += 1 ;
168- }
197+ self . tail |= u8to64_le ! ( msg, 0 , length) << 8 * self . ntail ;
169198 self . ntail += length;
170199 return Ok ( ( ) ) ;
171200 }
172201
173- let mut t = 0 ;
174- while t < needed {
175- self . tail [ self . ntail +t] = msg[ t] ;
176- t += 1 ;
177- }
178-
179- let m = u8to64_le ! ( self . tail, 0 ) ;
202+ let m = self . tail | u8to64_le ! ( msg, 0 , needed) << 8 * self . ntail ;
180203
181204 self . v3 ^= m;
182205 compress ! ( self . v0, self . v1, self . v2, self . v3) ;
@@ -203,15 +226,62 @@ impl Writer for SipState {
203226 i += 8 ;
204227 }
205228
206- let mut t = 0 u;
207- while t < left {
208- self . tail [ t] = msg[ i+t] ;
209- t += 1
210- }
229+ self . tail = u8to64_le ! ( msg, i, left) ;
211230 self . ntail = left;
212231
213232 Ok ( ( ) )
214233 }
234+
235+ #[ inline]
236+ fn write_u8 ( & mut self , n : u8 ) -> IoResult < ( ) > {
237+ make_write_le ! ( self , n, 1 )
238+ }
239+
240+ #[ inline]
241+ fn write_le_u16 ( & mut self , n : u16 ) -> IoResult < ( ) > {
242+ make_write_le ! ( self , n, 2 )
243+ }
244+
245+ #[ inline]
246+ fn write_le_u32 ( & mut self , n : u32 ) -> IoResult < ( ) > {
247+ make_write_le ! ( self , n, 4 )
248+ }
249+
250+ #[ inline]
251+ fn write_le_u64 ( & mut self , n : u64 ) -> IoResult < ( ) > {
252+ make_write_le ! ( self , n, 8 )
253+ }
254+
255+ #[ inline]
256+ fn write_le_uint ( & mut self , n : uint ) -> IoResult < ( ) > {
257+ make_write_le ! ( self , n, uint:: BYTES )
258+ }
259+
260+ #[ inline]
261+ fn write_i8 ( & mut self , n : i8 ) -> IoResult < ( ) > {
262+ make_write_le ! ( self , n, 1 )
263+ }
264+
265+ #[ inline]
266+ fn write_le_i16 ( & mut self , n : i16 ) -> IoResult < ( ) > {
267+ make_write_le ! ( self , n, 2 )
268+ }
269+
270+ #[ inline]
271+ fn write_le_i32 ( & mut self , n : i32 ) -> IoResult < ( ) > {
272+ make_write_le ! ( self , n, 4 )
273+ }
274+
275+ #[ inline]
276+ fn write_le_i64 ( & mut self , n : i64 ) -> IoResult < ( ) > {
277+ make_write_le ! ( self , n, 8 )
278+ }
279+
280+ #[ inline]
281+ fn write_le_int ( & mut self , n : int ) -> IoResult < ( ) > {
282+ make_write_le ! ( self , n, int:: BYTES )
283+ }
284+
215285}
216286
217287impl Clone for SipState {
@@ -284,6 +354,8 @@ pub fn hash_with_keys<T: Hash<SipState>>(k0: u64, k1: u64, value: &T) -> u64 {
284354 state. result ( )
285355}
286356
357+
358+
287359#[ cfg( test) ]
288360mod tests {
289361 extern crate test;
@@ -517,28 +589,57 @@ mod tests {
517589 }
518590
519591 #[ bench]
520- fn bench_str ( b : & mut Bencher ) {
592+ fn bench_str_under_8_bytes ( b : & mut Bencher ) {
521593 let s = "foo" ;
522594 b. iter ( || {
523595 assert_eq ! ( hash( & s) , 16262950014981195938 ) ;
524596 } )
525597 }
526598
599+ #[ bench]
600+ fn bench_str_of_8_bytes ( b : & mut Bencher ) {
601+ let s = "foobar78" ;
602+ b. iter ( || {
603+ assert_eq ! ( hash( & s) , 4898293253460910787 ) ;
604+ } )
605+ }
606+
607+ #[ bench]
608+ fn bench_str_over_8_bytes ( b : & mut Bencher ) {
609+ let s = "foobarbaz0" ;
610+ b. iter ( || {
611+ assert_eq ! ( hash( & s) , 10581415515220175264 ) ;
612+ } )
613+ }
614+
615+ #[ bench]
616+ fn bench_long_str ( b : & mut Bencher ) {
617+ let s = "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor \
618+ incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud \
619+ exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute \
620+ irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla \
621+ pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui \
622+ officia deserunt mollit anim id est laborum.";
623+ b. iter ( || {
624+ assert_eq ! ( hash( & s) , 17717065544121360093 ) ;
625+ } )
626+ }
627+
628+ #[ bench]
629+ fn bench_u64 ( b : & mut Bencher ) {
630+ let u = 16262950014981195938u64 ;
631+ b. iter ( || {
632+ assert_eq ! ( hash( & u) , 5254097107239593357 ) ;
633+ } )
634+ }
635+
636+ #[ deriving( Hash ) ]
527637 struct Compound {
528638 x : u8 ,
529- y : u16 ,
639+ y : u64 ,
530640 z : ~str ,
531641 }
532642
533- impl < S : Writer > Hash < S > for Compound {
534- #[ inline]
535- fn hash ( & self , state : & mut S ) {
536- self . x . hash ( state) ;
537- self . y . hash ( state) ;
538- self . z . hash ( state) ;
539- }
540- }
541-
542643 #[ bench]
543644 fn bench_compound_1 ( b : & mut Bencher ) {
544645 let compound = Compound {
@@ -547,7 +648,7 @@ mod tests {
547648 z : ~"foobarbaz",
548649 } ;
549650 b. iter ( || {
550- assert_eq ! ( hash( & compound) , 3581836382593270478 ) ;
651+ assert_eq ! ( hash( & compound) , 15783192367317361799 ) ;
551652 } )
552653 }
553654}
0 commit comments