27
27
use clone:: Clone ;
28
28
use container:: Container ;
29
29
use default:: Default ;
30
+ use int;
30
31
use io:: { IoResult , Writer } ;
31
32
use iter:: Iterator ;
32
33
use result:: Ok ;
33
34
use slice:: ImmutableVector ;
35
+ use uint;
34
36
35
37
use super :: { Hash , Hasher } ;
36
38
@@ -43,7 +45,7 @@ pub struct SipState {
43
45
v1 : u64 ,
44
46
v2 : u64 ,
45
47
v3 : u64 ,
46
- tail : [ u8 , .. 8 ] , // unprocessed bytes
48
+ tail : u64 , // unprocessed bytes le
47
49
ntail : uint , // how many bytes in tail are valid
48
50
}
49
51
@@ -60,7 +62,17 @@ macro_rules! u8to64_le (
60
62
$buf[ 4 +$i] as u64 << 32 |
61
63
$buf[ 5 +$i] as u64 << 40 |
62
64
$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
+ } ) ;
64
76
)
65
77
66
78
macro_rules! rotl (
@@ -98,7 +110,7 @@ impl SipState {
98
110
v1 : 0 ,
99
111
v2 : 0 ,
100
112
v3 : 0 ,
101
- tail : [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ] ,
113
+ tail : 0 ,
102
114
ntail : 0 ,
103
115
} ;
104
116
state. reset ( ) ;
@@ -124,15 +136,7 @@ impl SipState {
124
136
let mut v2 = self . v2 ;
125
137
let mut v3 = self . v3 ;
126
138
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 ;
136
140
137
141
v3 ^= b;
138
142
compress ! ( v0, v1, v2, v3) ;
@@ -147,8 +151,38 @@ impl SipState {
147
151
148
152
v0 ^ v1 ^ v2 ^ v3
149
153
}
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
+ }
150
176
}
151
177
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
+
152
186
impl Writer for SipState {
153
187
#[ inline]
154
188
fn write ( & mut self , msg : & [ u8 ] ) -> IoResult < ( ) > {
@@ -159,24 +193,13 @@ impl Writer for SipState {
159
193
160
194
if self . ntail != 0 {
161
195
needed = 8 - self . ntail ;
162
-
163
196
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 ;
169
198
self . ntail += length;
170
199
return Ok ( ( ) ) ;
171
200
}
172
201
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 ;
180
203
181
204
self . v3 ^= m;
182
205
compress ! ( self . v0, self . v1, self . v2, self . v3) ;
@@ -203,15 +226,62 @@ impl Writer for SipState {
203
226
i += 8 ;
204
227
}
205
228
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) ;
211
230
self . ntail = left;
212
231
213
232
Ok ( ( ) )
214
233
}
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
+
215
285
}
216
286
217
287
impl Clone for SipState {
@@ -284,6 +354,8 @@ pub fn hash_with_keys<T: Hash<SipState>>(k0: u64, k1: u64, value: &T) -> u64 {
284
354
state. result ( )
285
355
}
286
356
357
+
358
+
287
359
#[ cfg( test) ]
288
360
mod tests {
289
361
extern crate test;
@@ -517,28 +589,57 @@ mod tests {
517
589
}
518
590
519
591
#[ bench]
520
- fn bench_str ( b : & mut Bencher ) {
592
+ fn bench_str_under_8_bytes ( b : & mut Bencher ) {
521
593
let s = "foo" ;
522
594
b. iter ( || {
523
595
assert_eq ! ( hash( & s) , 16262950014981195938 ) ;
524
596
} )
525
597
}
526
598
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 ) ]
527
637
struct Compound {
528
638
x : u8 ,
529
- y : u16 ,
639
+ y : u64 ,
530
640
z : ~str ,
531
641
}
532
642
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
-
542
643
#[ bench]
543
644
fn bench_compound_1 ( b : & mut Bencher ) {
544
645
let compound = Compound {
@@ -547,7 +648,7 @@ mod tests {
547
648
z : ~"foobarbaz",
548
649
} ;
549
650
b. iter ( || {
550
- assert_eq ! ( hash( & compound) , 3581836382593270478 ) ;
651
+ assert_eq ! ( hash( & compound) , 15783192367317361799 ) ;
551
652
} )
552
653
}
553
654
}
0 commit comments