1use core::cmp;
14use core::hash;
15use core::marker::PhantomData;
16use core::mem;
17use core::ptr;
18use core::slice;
19
20#[derive(Debug, Clone, Copy, Default)]
24pub struct SipHasher13 {
25 hasher: Hasher<Sip13Rounds>,
26}
27
28#[derive(Debug, Clone, Copy, Default)]
32pub struct SipHasher24 {
33 hasher: Hasher<Sip24Rounds>,
34}
35
36#[derive(Debug, Clone, Copy, Default)]
49pub struct SipHasher(SipHasher24);
50
51#[derive(Debug, Clone, Copy)]
52struct Hasher<S: Sip> {
53 k0: u64,
54 k1: u64,
55 length: usize, state: State, tail: u64, ntail: usize, _marker: PhantomData<S>,
60}
61
62#[derive(Debug, Clone, Copy)]
63struct State {
64 v0: u64,
69 v2: u64,
70 v1: u64,
71 v3: u64,
72}
73
74macro_rules! compress {
75 ($state:expr) => {{
76 compress!($state.v0, $state.v1, $state.v2, $state.v3)
77 }};
78 ($v0:expr, $v1:expr, $v2:expr, $v3:expr) => {{
79 $v0 = $v0.wrapping_add($v1);
80 $v1 = $v1.rotate_left(13);
81 $v1 ^= $v0;
82 $v0 = $v0.rotate_left(32);
83 $v2 = $v2.wrapping_add($v3);
84 $v3 = $v3.rotate_left(16);
85 $v3 ^= $v2;
86 $v0 = $v0.wrapping_add($v3);
87 $v3 = $v3.rotate_left(21);
88 $v3 ^= $v0;
89 $v2 = $v2.wrapping_add($v1);
90 $v1 = $v1.rotate_left(17);
91 $v1 ^= $v2;
92 $v2 = $v2.rotate_left(32);
93 }};
94}
95
96macro_rules! load_int_le {
102 ($buf:expr, $i:expr, $int_ty:ident) => {{
103 debug_assert!($i + mem::size_of::<$int_ty>() <= $buf.len());
104 let mut data = 0 as $int_ty;
105 ptr::copy_nonoverlapping(
106 $buf.get_unchecked($i),
107 &mut data as *mut _ as *mut u8,
108 mem::size_of::<$int_ty>(),
109 );
110 data.to_le()
111 }};
112}
113
114#[inline]
118unsafe fn u8to64_le(buf: &[u8], start: usize, len: usize) -> u64 {
119 debug_assert!(len < 8);
120 let mut i = 0; let mut out = 0;
122 if i + 3 < len {
123 out = load_int_le!(buf, start + i, u32) as u64;
124 i += 4;
125 }
126 if i + 1 < len {
127 out |= (load_int_le!(buf, start + i, u16) as u64) << (i * 8);
128 i += 2
129 }
130 if i < len {
131 out |= (*buf.get_unchecked(start + i) as u64) << (i * 8);
132 i += 1;
133 }
134 debug_assert_eq!(i, len);
135 out
136}
137
138impl SipHasher {
139 #[inline]
141 pub fn new() -> SipHasher {
142 SipHasher::new_with_keys(0, 0)
143 }
144
145 #[inline]
147 pub fn new_with_keys(key0: u64, key1: u64) -> SipHasher {
148 SipHasher(SipHasher24::new_with_keys(key0, key1))
149 }
150
151 pub fn keys(&self) -> (u64, u64) {
153 (self.0.hasher.k0, self.0.hasher.k1)
154 }
155}
156
157impl SipHasher13 {
158 #[inline]
160 pub fn new() -> SipHasher13 {
161 SipHasher13::new_with_keys(0, 0)
162 }
163
164 #[inline]
166 pub fn new_with_keys(key0: u64, key1: u64) -> SipHasher13 {
167 SipHasher13 {
168 hasher: Hasher::new_with_keys(key0, key1),
169 }
170 }
171
172 pub fn keys(&self) -> (u64, u64) {
174 (self.hasher.k0, self.hasher.k1)
175 }
176}
177
178impl SipHasher24 {
179 #[inline]
181 pub fn new() -> SipHasher24 {
182 SipHasher24::new_with_keys(0, 0)
183 }
184
185 #[inline]
187 pub fn new_with_keys(key0: u64, key1: u64) -> SipHasher24 {
188 SipHasher24 {
189 hasher: Hasher::new_with_keys(key0, key1),
190 }
191 }
192
193 pub fn keys(&self) -> (u64, u64) {
195 (self.hasher.k0, self.hasher.k1)
196 }
197}
198
199impl<S: Sip> Hasher<S> {
200 #[inline]
201 fn new_with_keys(key0: u64, key1: u64) -> Hasher<S> {
202 let mut state = Hasher {
203 k0: key0,
204 k1: key1,
205 length: 0,
206 state: State {
207 v0: 0,
208 v1: 0,
209 v2: 0,
210 v3: 0,
211 },
212 tail: 0,
213 ntail: 0,
214 _marker: PhantomData,
215 };
216 state.reset();
217 state
218 }
219
220 #[inline]
221 fn reset(&mut self) {
222 self.length = 0;
223 self.state.v0 = self.k0 ^ 0x736f6d6570736575;
224 self.state.v1 = self.k1 ^ 0x646f72616e646f6d;
225 self.state.v2 = self.k0 ^ 0x6c7967656e657261;
226 self.state.v3 = self.k1 ^ 0x7465646279746573;
227 self.ntail = 0;
228 }
229
230 #[inline(always)]
236 fn short_write(&mut self, msg: &[u8]) {
237 debug_assert!(msg.len() <= 8);
238 let length = msg.len();
239 self.length += length;
240
241 let needed = 8 - self.ntail;
242 let fill = cmp::min(length, needed);
243 if fill == 8 {
244 self.tail = unsafe { load_int_le!(msg, 0, u64) };
245 } else {
246 self.tail |= unsafe { u8to64_le(msg, 0, fill) } << (8 * self.ntail);
247 if length < needed {
248 self.ntail += length;
249 return;
250 }
251 }
252 self.state.v3 ^= self.tail;
253 S::c_rounds(&mut self.state);
254 self.state.v0 ^= self.tail;
255
256 self.ntail = length - needed;
258 self.tail = unsafe { u8to64_le(msg, needed, self.ntail) };
259 }
260}
261
262impl hash::Hasher for SipHasher {
263 #[inline]
264 fn write(&mut self, msg: &[u8]) {
265 self.0.write(msg)
266 }
267
268 #[inline]
269 fn finish(&self) -> u64 {
270 self.0.finish()
271 }
272}
273
274impl hash::Hasher for SipHasher13 {
275 #[inline]
276 fn write(&mut self, msg: &[u8]) {
277 self.hasher.write(msg)
278 }
279
280 #[inline]
281 fn finish(&self) -> u64 {
282 self.hasher.finish()
283 }
284}
285
286impl hash::Hasher for SipHasher24 {
287 #[inline]
288 fn write(&mut self, msg: &[u8]) {
289 self.hasher.write(msg)
290 }
291
292 #[inline]
293 fn finish(&self) -> u64 {
294 self.hasher.finish()
295 }
296}
297
298impl<S: Sip> hash::Hasher for Hasher<S> {
299 #[inline]
301 fn write_usize(&mut self, i: usize) {
302 let bytes = unsafe {
303 slice::from_raw_parts(&i as *const usize as *const u8, mem::size_of::<usize>())
304 };
305 self.short_write(bytes);
306 }
307
308 #[inline]
310 fn write_u8(&mut self, i: u8) {
311 self.short_write(&[i]);
312 }
313
314 #[inline]
315 fn write(&mut self, msg: &[u8]) {
316 let length = msg.len();
317 self.length += length;
318
319 let mut needed = 0;
320
321 if self.ntail != 0 {
322 needed = 8 - self.ntail;
323 self.tail |= unsafe { u8to64_le(msg, 0, cmp::min(length, needed)) } << (8 * self.ntail);
324 if length < needed {
325 self.ntail += length;
326 return;
327 } else {
328 self.state.v3 ^= self.tail;
329 S::c_rounds(&mut self.state);
330 self.state.v0 ^= self.tail;
331 self.ntail = 0;
332 }
333 }
334
335 let len = length - needed;
337 let left = len & 0x7;
338
339 let mut i = needed;
340 while i < len - left {
341 let mi = unsafe { load_int_le!(msg, i, u64) };
342
343 self.state.v3 ^= mi;
344 S::c_rounds(&mut self.state);
345 self.state.v0 ^= mi;
346
347 i += 8;
348 }
349
350 self.tail = unsafe { u8to64_le(msg, i, left) };
351 self.ntail = left;
352 }
353
354 #[inline]
355 fn finish(&self) -> u64 {
356 let mut state = self.state;
357
358 let b: u64 = ((self.length as u64 & 0xff) << 56) | self.tail;
359
360 state.v3 ^= b;
361 S::c_rounds(&mut state);
362 state.v0 ^= b;
363
364 state.v2 ^= 0xff;
365 S::d_rounds(&mut state);
366
367 state.v0 ^ state.v1 ^ state.v2 ^ state.v3
368 }
369}
370
371impl<S: Sip> Default for Hasher<S> {
372 #[inline]
374 fn default() -> Hasher<S> {
375 Hasher::new_with_keys(0, 0)
376 }
377}
378
379#[doc(hidden)]
380trait Sip {
381 fn c_rounds(_: &mut State);
382 fn d_rounds(_: &mut State);
383}
384
385#[derive(Debug, Clone, Copy, Default)]
386struct Sip13Rounds;
387
388impl Sip for Sip13Rounds {
389 #[inline]
390 fn c_rounds(state: &mut State) {
391 compress!(state);
392 }
393
394 #[inline]
395 fn d_rounds(state: &mut State) {
396 compress!(state);
397 compress!(state);
398 compress!(state);
399 }
400}
401
402#[derive(Debug, Clone, Copy, Default)]
403struct Sip24Rounds;
404
405impl Sip for Sip24Rounds {
406 #[inline]
407 fn c_rounds(state: &mut State) {
408 compress!(state);
409 compress!(state);
410 }
411
412 #[inline]
413 fn d_rounds(state: &mut State) {
414 compress!(state);
415 compress!(state);
416 compress!(state);
417 compress!(state);
418 }
419}