/rust/registry/src/index.crates.io-1949cf8c6b5b557f/siphasher-1.0.3/src/sip.rs
Line | Count | Source |
1 | | // Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT |
2 | | // file at the top-level directory of this distribution and at |
3 | | // http://rust-lang.org/COPYRIGHT. |
4 | | // |
5 | | // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or |
6 | | // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license |
7 | | // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your |
8 | | // option. This file may not be copied, modified, or distributed |
9 | | // except according to those terms. |
10 | | |
11 | | //! An implementation of SipHash. |
12 | | |
13 | | use core::cmp; |
14 | | use core::hash; |
15 | | use core::hash::Hasher as _; |
16 | | use core::marker::PhantomData; |
17 | | use core::mem; |
18 | | |
19 | | use crate::common::{compress, load_int_le, u8to64_le}; |
20 | | |
21 | | /// An implementation of SipHash 1-3. |
22 | | /// |
23 | | /// See: <https://www.aumasson.jp/siphash/siphash.pdf> |
24 | | #[derive(Debug, Clone, Copy, Default)] |
25 | | #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] |
26 | | pub struct SipHasher13 { |
27 | | hasher: Hasher<Sip13Rounds>, |
28 | | } |
29 | | |
30 | | /// An implementation of SipHash 2-4. |
31 | | /// |
32 | | /// See: <https://www.aumasson.jp/siphash/siphash.pdf> |
33 | | #[derive(Debug, Clone, Copy, Default)] |
34 | | #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] |
35 | | pub struct SipHasher24 { |
36 | | hasher: Hasher<Sip24Rounds>, |
37 | | } |
38 | | |
39 | | /// An implementation of SipHash 2-4. |
40 | | /// |
41 | | /// See: <https://www.aumasson.jp/siphash/siphash.pdf> |
42 | | /// |
43 | | /// SipHash is a general-purpose hashing function: it runs at a good |
44 | | /// speed (competitive with Spooky and City) and permits strong _keyed_ |
45 | | /// hashing. This lets you key your hashtables from a strong RNG, such as |
46 | | /// [`rand::os::OsRng`](https://doc.rust-lang.org/rand/rand/os/struct.OsRng.html). |
47 | | /// |
48 | | /// Although the SipHash algorithm is considered to be generally strong, |
49 | | /// it is not intended for cryptographic purposes. As such, all |
50 | | /// cryptographic uses of this implementation are _strongly discouraged_. |
51 | | #[derive(Debug, Clone, Copy, Default)] |
52 | | #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] |
53 | | pub struct SipHasher(SipHasher24); |
54 | | |
55 | | #[derive(Debug, Clone, Copy)] |
56 | | #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] |
57 | | struct Hasher<S: Sip> { |
58 | | k0: u64, |
59 | | k1: u64, |
60 | | length: usize, // how many bytes we've processed |
61 | | state: State, // hash State |
62 | | tail: u64, // unprocessed bytes le |
63 | | ntail: usize, // how many bytes in tail are valid |
64 | | _marker: PhantomData<S>, |
65 | | } |
66 | | |
67 | | #[derive(Debug, Clone, Copy)] |
68 | | #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] |
69 | | struct State { |
70 | | // v0, v2 and v1, v3 show up in pairs in the algorithm, |
71 | | // and simd implementations of SipHash will use vectors |
72 | | // of v02 and v13. By placing them in this order in the struct, |
73 | | // the compiler can pick up on just a few simd optimizations by itself. |
74 | | v0: u64, |
75 | | v2: u64, |
76 | | v1: u64, |
77 | | v3: u64, |
78 | | } |
79 | | |
80 | | impl SipHasher { |
81 | | /// Creates a new `SipHasher` with the two initial keys set to 0. |
82 | | #[inline] |
83 | 0 | pub fn new() -> SipHasher { |
84 | 0 | SipHasher::new_with_keys(0, 0) |
85 | 0 | } |
86 | | |
87 | | /// Creates a `SipHasher` that is keyed off the provided keys. |
88 | | #[inline] |
89 | 0 | pub fn new_with_keys(key0: u64, key1: u64) -> SipHasher { |
90 | 0 | SipHasher(SipHasher24::new_with_keys(key0, key1)) |
91 | 0 | } |
92 | | |
93 | | /// Creates a `SipHasher` from a 16 byte key. |
94 | 0 | pub fn new_with_key(key: &[u8; 16]) -> SipHasher { |
95 | 0 | let mut b0 = [0u8; 8]; |
96 | 0 | let mut b1 = [0u8; 8]; |
97 | 0 | b0.copy_from_slice(&key[0..8]); |
98 | 0 | b1.copy_from_slice(&key[8..16]); |
99 | 0 | let key0 = u64::from_le_bytes(b0); |
100 | 0 | let key1 = u64::from_le_bytes(b1); |
101 | 0 | Self::new_with_keys(key0, key1) |
102 | 0 | } |
103 | | |
104 | | /// Get the keys used by this hasher |
105 | 0 | pub fn keys(&self) -> (u64, u64) { |
106 | 0 | (self.0.hasher.k0, self.0.hasher.k1) |
107 | 0 | } |
108 | | |
109 | | /// Get the key used by this hasher as a 16 byte vector |
110 | 0 | pub fn key(&self) -> [u8; 16] { |
111 | 0 | let mut bytes = [0u8; 16]; |
112 | 0 | bytes[0..8].copy_from_slice(&self.0.hasher.k0.to_le_bytes()); |
113 | 0 | bytes[8..16].copy_from_slice(&self.0.hasher.k1.to_le_bytes()); |
114 | 0 | bytes |
115 | 0 | } |
116 | | |
117 | | /// Hash a byte array - This is the easiest and safest way to use SipHash. |
118 | | #[inline] |
119 | 0 | pub fn hash(&self, bytes: &[u8]) -> u64 { |
120 | 0 | self.0.hasher.hash(bytes) |
121 | 0 | } |
122 | | } |
123 | | |
124 | | impl SipHasher13 { |
125 | | /// Creates a new `SipHasher13` with the two initial keys set to 0. |
126 | | #[inline] |
127 | 0 | pub fn new() -> SipHasher13 { |
128 | 0 | SipHasher13::new_with_keys(0, 0) |
129 | 0 | } |
130 | | |
131 | | /// Creates a `SipHasher13` that is keyed off the provided keys. |
132 | | #[inline] |
133 | 0 | pub fn new_with_keys(key0: u64, key1: u64) -> SipHasher13 { |
134 | 0 | SipHasher13 { |
135 | 0 | hasher: Hasher::new_with_keys(key0, key1), |
136 | 0 | } |
137 | 0 | } |
138 | | |
139 | | /// Creates a `SipHasher13` from a 16 byte key. |
140 | 0 | pub fn new_with_key(key: &[u8; 16]) -> SipHasher13 { |
141 | 0 | let mut b0 = [0u8; 8]; |
142 | 0 | let mut b1 = [0u8; 8]; |
143 | 0 | b0.copy_from_slice(&key[0..8]); |
144 | 0 | b1.copy_from_slice(&key[8..16]); |
145 | 0 | let key0 = u64::from_le_bytes(b0); |
146 | 0 | let key1 = u64::from_le_bytes(b1); |
147 | 0 | Self::new_with_keys(key0, key1) |
148 | 0 | } |
149 | | |
150 | | /// Get the keys used by this hasher |
151 | 0 | pub fn keys(&self) -> (u64, u64) { |
152 | 0 | (self.hasher.k0, self.hasher.k1) |
153 | 0 | } |
154 | | |
155 | | /// Get the key used by this hasher as a 16 byte vector |
156 | 0 | pub fn key(&self) -> [u8; 16] { |
157 | 0 | let mut bytes = [0u8; 16]; |
158 | 0 | bytes[0..8].copy_from_slice(&self.hasher.k0.to_le_bytes()); |
159 | 0 | bytes[8..16].copy_from_slice(&self.hasher.k1.to_le_bytes()); |
160 | 0 | bytes |
161 | 0 | } |
162 | | |
163 | | /// Hash a byte array - This is the easiest and safest way to use SipHash. |
164 | | #[inline] |
165 | 0 | pub fn hash(&self, bytes: &[u8]) -> u64 { |
166 | 0 | self.hasher.hash(bytes) |
167 | 0 | } |
168 | | } |
169 | | |
170 | | impl SipHasher24 { |
171 | | /// Creates a new `SipHasher24` with the two initial keys set to 0. |
172 | | #[inline] |
173 | 0 | pub fn new() -> SipHasher24 { |
174 | 0 | SipHasher24::new_with_keys(0, 0) |
175 | 0 | } |
176 | | |
177 | | /// Creates a `SipHasher24` that is keyed off the provided keys. |
178 | | #[inline] |
179 | 0 | pub fn new_with_keys(key0: u64, key1: u64) -> SipHasher24 { |
180 | 0 | SipHasher24 { |
181 | 0 | hasher: Hasher::new_with_keys(key0, key1), |
182 | 0 | } |
183 | 0 | } |
184 | | |
185 | | /// Creates a `SipHasher24` from a 16 byte key. |
186 | 0 | pub fn new_with_key(key: &[u8; 16]) -> SipHasher24 { |
187 | 0 | let mut b0 = [0u8; 8]; |
188 | 0 | let mut b1 = [0u8; 8]; |
189 | 0 | b0.copy_from_slice(&key[0..8]); |
190 | 0 | b1.copy_from_slice(&key[8..16]); |
191 | 0 | let key0 = u64::from_le_bytes(b0); |
192 | 0 | let key1 = u64::from_le_bytes(b1); |
193 | 0 | Self::new_with_keys(key0, key1) |
194 | 0 | } |
195 | | |
196 | | /// Get the keys used by this hasher |
197 | 0 | pub fn keys(&self) -> (u64, u64) { |
198 | 0 | (self.hasher.k0, self.hasher.k1) |
199 | 0 | } |
200 | | |
201 | | /// Get the key used by this hasher as a 16 byte vector |
202 | 0 | pub fn key(&self) -> [u8; 16] { |
203 | 0 | let mut bytes = [0u8; 16]; |
204 | 0 | bytes[0..8].copy_from_slice(&self.hasher.k0.to_le_bytes()); |
205 | 0 | bytes[8..16].copy_from_slice(&self.hasher.k1.to_le_bytes()); |
206 | 0 | bytes |
207 | 0 | } |
208 | | |
209 | | /// Hash a byte array - This is the easiest and safest way to use SipHash. |
210 | | #[inline] |
211 | 0 | pub fn hash(&self, bytes: &[u8]) -> u64 { |
212 | 0 | self.hasher.hash(bytes) |
213 | 0 | } |
214 | | } |
215 | | |
216 | | impl<S: Sip> Hasher<S> { |
217 | | #[inline] |
218 | 0 | fn new_with_keys(key0: u64, key1: u64) -> Hasher<S> { |
219 | 0 | let mut state = Hasher { |
220 | 0 | k0: key0, |
221 | 0 | k1: key1, |
222 | 0 | length: 0, |
223 | 0 | state: State { |
224 | 0 | v0: 0, |
225 | 0 | v1: 0, |
226 | 0 | v2: 0, |
227 | 0 | v3: 0, |
228 | 0 | }, |
229 | 0 | tail: 0, |
230 | 0 | ntail: 0, |
231 | 0 | _marker: PhantomData, |
232 | 0 | }; |
233 | 0 | state.reset(); |
234 | 0 | state |
235 | 0 | } Unexecuted instantiation: <siphasher::sip::Hasher<siphasher::sip::Sip13Rounds>>::new_with_keys Unexecuted instantiation: <siphasher::sip::Hasher<siphasher::sip::Sip24Rounds>>::new_with_keys |
236 | | |
237 | | #[inline] |
238 | 0 | fn reset(&mut self) { |
239 | 0 | self.length = 0; |
240 | 0 | self.state.v0 = self.k0 ^ 0x736f6d6570736575; |
241 | 0 | self.state.v1 = self.k1 ^ 0x646f72616e646f6d; |
242 | 0 | self.state.v2 = self.k0 ^ 0x6c7967656e657261; |
243 | 0 | self.state.v3 = self.k1 ^ 0x7465646279746573; |
244 | 0 | self.ntail = 0; |
245 | 0 | } Unexecuted instantiation: <siphasher::sip::Hasher<siphasher::sip::Sip13Rounds>>::reset Unexecuted instantiation: <siphasher::sip::Hasher<siphasher::sip::Sip24Rounds>>::reset |
246 | | |
247 | | // A specialized write function for values with size <= 8. |
248 | | // |
249 | | // The hashing of multi-byte integers depends on endianness. E.g.: |
250 | | // - little-endian: `write_u32(0xDDCCBBAA)` == `write([0xAA, 0xBB, 0xCC, 0xDD])` |
251 | | // - big-endian: `write_u32(0xDDCCBBAA)` == `write([0xDD, 0xCC, 0xBB, 0xAA])` |
252 | | // |
253 | | // This function does the right thing for little-endian hardware. On |
254 | | // big-endian hardware `x` must be byte-swapped first to give the right |
255 | | // behaviour. After any byte-swapping, the input must be zero-extended to |
256 | | // 64-bits. The caller is responsible for the byte-swapping and |
257 | | // zero-extension. |
258 | | #[inline] |
259 | 0 | fn short_write<T>(&mut self, _x: T, x: u64) { |
260 | 0 | let size = mem::size_of::<T>(); |
261 | 0 | self.length += size; |
262 | | |
263 | | // The original number must be zero-extended, not sign-extended. |
264 | 0 | debug_assert!(if size < 8 { x >> (8 * size) == 0 } else { true }); |
265 | | |
266 | | // The number of bytes needed to fill `self.tail`. |
267 | 0 | let needed = 8 - self.ntail; |
268 | | |
269 | 0 | self.tail |= x << (8 * self.ntail); |
270 | 0 | if size < needed { |
271 | 0 | self.ntail += size; |
272 | 0 | return; |
273 | 0 | } |
274 | | |
275 | | // `self.tail` is full, process it. |
276 | 0 | self.state.v3 ^= self.tail; |
277 | 0 | S::c_rounds(&mut self.state); |
278 | 0 | self.state.v0 ^= self.tail; |
279 | | |
280 | 0 | self.ntail = size - needed; |
281 | 0 | self.tail = if needed < 8 { x >> (8 * needed) } else { 0 }; |
282 | 0 | } |
283 | | |
284 | | #[inline] |
285 | 0 | fn hash(&self, msg: &[u8]) -> u64 { |
286 | 0 | if self.ntail != 0 { |
287 | 0 | let mut hasher: Hasher<S> = Hasher { |
288 | 0 | k0: self.k0, |
289 | 0 | k1: self.k1, |
290 | 0 | length: self.length, |
291 | 0 | state: self.state, |
292 | 0 | tail: self.tail, |
293 | 0 | ntail: self.ntail, |
294 | 0 | _marker: PhantomData, |
295 | 0 | }; |
296 | 0 | hasher.write(msg); |
297 | 0 | return hasher.finish(); |
298 | 0 | } |
299 | | |
300 | 0 | let length = self.length + msg.len(); |
301 | 0 | let len = msg.len(); |
302 | 0 | let left = len & 0x7; |
303 | 0 | let mut state = self.state; |
304 | 0 | let mut i = 0; |
305 | | |
306 | 0 | while i < len - left { |
307 | 0 | let mi = unsafe { load_int_le!(msg, i, u64) }; |
308 | | |
309 | 0 | state.v3 ^= mi; |
310 | 0 | S::c_rounds(&mut state); |
311 | 0 | state.v0 ^= mi; |
312 | | |
313 | 0 | i += 8; |
314 | | } |
315 | | |
316 | 0 | let tail = unsafe { u8to64_le(msg, i, left) }; |
317 | 0 | Self::finish_with_state(state, length, tail) |
318 | 0 | } |
319 | | |
320 | | #[inline] |
321 | 0 | fn finish_with_state(mut state: State, length: usize, tail: u64) -> u64 { |
322 | 0 | let b: u64 = ((length as u64 & 0xff) << 56) | tail; |
323 | | |
324 | 0 | state.v3 ^= b; |
325 | 0 | S::c_rounds(&mut state); |
326 | 0 | state.v0 ^= b; |
327 | | |
328 | 0 | state.v2 ^= 0xff; |
329 | 0 | S::d_rounds(&mut state); |
330 | | |
331 | 0 | state.v0 ^ state.v1 ^ state.v2 ^ state.v3 |
332 | 0 | } |
333 | | } |
334 | | |
335 | | impl hash::Hasher for SipHasher { |
336 | | #[inline] |
337 | 0 | fn write(&mut self, msg: &[u8]) { |
338 | 0 | self.0.write(msg) |
339 | 0 | } |
340 | | |
341 | | #[inline] |
342 | 0 | fn finish(&self) -> u64 { |
343 | 0 | self.0.finish() |
344 | 0 | } |
345 | | |
346 | | #[inline] |
347 | 0 | fn write_usize(&mut self, i: usize) { |
348 | 0 | self.0.write_usize(i); |
349 | 0 | } |
350 | | |
351 | | #[inline] |
352 | 0 | fn write_u8(&mut self, i: u8) { |
353 | 0 | self.0.write_u8(i); |
354 | 0 | } |
355 | | |
356 | | #[inline] |
357 | 0 | fn write_u16(&mut self, i: u16) { |
358 | 0 | self.0.write_u16(i); |
359 | 0 | } |
360 | | |
361 | | #[inline] |
362 | 0 | fn write_u32(&mut self, i: u32) { |
363 | 0 | self.0.write_u32(i); |
364 | 0 | } |
365 | | |
366 | | #[inline] |
367 | 0 | fn write_u64(&mut self, i: u64) { |
368 | 0 | self.0.write_u64(i); |
369 | 0 | } |
370 | | } |
371 | | |
372 | | impl hash::Hasher for SipHasher13 { |
373 | | #[inline] |
374 | 0 | fn write(&mut self, msg: &[u8]) { |
375 | 0 | self.hasher.write(msg) |
376 | 0 | } |
377 | | |
378 | | #[inline] |
379 | 0 | fn finish(&self) -> u64 { |
380 | 0 | self.hasher.finish() |
381 | 0 | } |
382 | | |
383 | | #[inline] |
384 | 0 | fn write_usize(&mut self, i: usize) { |
385 | 0 | self.hasher.write_usize(i); |
386 | 0 | } |
387 | | |
388 | | #[inline] |
389 | 0 | fn write_u8(&mut self, i: u8) { |
390 | 0 | self.hasher.write_u8(i); |
391 | 0 | } |
392 | | |
393 | | #[inline] |
394 | 0 | fn write_u16(&mut self, i: u16) { |
395 | 0 | self.hasher.write_u16(i); |
396 | 0 | } |
397 | | |
398 | | #[inline] |
399 | 0 | fn write_u32(&mut self, i: u32) { |
400 | 0 | self.hasher.write_u32(i); |
401 | 0 | } |
402 | | |
403 | | #[inline] |
404 | 0 | fn write_u64(&mut self, i: u64) { |
405 | 0 | self.hasher.write_u64(i); |
406 | 0 | } |
407 | | } |
408 | | |
409 | | impl hash::Hasher for SipHasher24 { |
410 | | #[inline] |
411 | 0 | fn write(&mut self, msg: &[u8]) { |
412 | 0 | self.hasher.write(msg) |
413 | 0 | } |
414 | | |
415 | | #[inline] |
416 | 0 | fn finish(&self) -> u64 { |
417 | 0 | self.hasher.finish() |
418 | 0 | } |
419 | | |
420 | | #[inline] |
421 | 0 | fn write_usize(&mut self, i: usize) { |
422 | 0 | self.hasher.write_usize(i); |
423 | 0 | } |
424 | | |
425 | | #[inline] |
426 | 0 | fn write_u8(&mut self, i: u8) { |
427 | 0 | self.hasher.write_u8(i); |
428 | 0 | } |
429 | | |
430 | | #[inline] |
431 | 0 | fn write_u16(&mut self, i: u16) { |
432 | 0 | self.hasher.write_u16(i); |
433 | 0 | } |
434 | | |
435 | | #[inline] |
436 | 0 | fn write_u32(&mut self, i: u32) { |
437 | 0 | self.hasher.write_u32(i); |
438 | 0 | } |
439 | | |
440 | | #[inline] |
441 | 0 | fn write_u64(&mut self, i: u64) { |
442 | 0 | self.hasher.write_u64(i); |
443 | 0 | } |
444 | | } |
445 | | |
446 | | impl<S: Sip> hash::Hasher for Hasher<S> { |
447 | | #[inline] |
448 | 0 | fn write_usize(&mut self, i: usize) { |
449 | 0 | self.short_write(i, i.to_le() as u64); |
450 | 0 | } |
451 | | |
452 | | #[inline] |
453 | 0 | fn write_u8(&mut self, i: u8) { |
454 | 0 | self.short_write(i, i as u64); |
455 | 0 | } |
456 | | |
457 | | #[inline] |
458 | 0 | fn write_u16(&mut self, i: u16) { |
459 | 0 | self.short_write(i, i.to_le() as u64); |
460 | 0 | } |
461 | | |
462 | | #[inline] |
463 | 0 | fn write_u32(&mut self, i: u32) { |
464 | 0 | self.short_write(i, i.to_le() as u64); |
465 | 0 | } |
466 | | |
467 | | #[inline] |
468 | 0 | fn write_u64(&mut self, i: u64) { |
469 | 0 | self.short_write(i, i.to_le()); |
470 | 0 | } |
471 | | |
472 | | #[inline] |
473 | 0 | fn write(&mut self, msg: &[u8]) { |
474 | 0 | let length = msg.len(); |
475 | 0 | self.length += length; |
476 | | |
477 | 0 | let mut needed = 0; |
478 | | |
479 | 0 | if self.ntail != 0 { |
480 | 0 | needed = 8 - self.ntail; |
481 | 0 | self.tail |= unsafe { u8to64_le(msg, 0, cmp::min(length, needed)) } << (8 * self.ntail); |
482 | 0 | if length < needed { |
483 | 0 | self.ntail += length; |
484 | 0 | return; |
485 | 0 | } else { |
486 | 0 | self.state.v3 ^= self.tail; |
487 | 0 | S::c_rounds(&mut self.state); |
488 | 0 | self.state.v0 ^= self.tail; |
489 | 0 | self.ntail = 0; |
490 | 0 | } |
491 | 0 | } |
492 | | |
493 | | // Buffered tail is now flushed, process new input. |
494 | 0 | let len = length - needed; |
495 | 0 | let left = len & 0x7; |
496 | | |
497 | 0 | let mut i = needed; |
498 | 0 | while i < len - left { |
499 | 0 | let mi = unsafe { load_int_le!(msg, i, u64) }; |
500 | | |
501 | 0 | self.state.v3 ^= mi; |
502 | 0 | S::c_rounds(&mut self.state); |
503 | 0 | self.state.v0 ^= mi; |
504 | | |
505 | 0 | i += 8; |
506 | | } |
507 | | |
508 | 0 | self.tail = unsafe { u8to64_le(msg, i, left) }; |
509 | 0 | self.ntail = left; |
510 | 0 | } |
511 | | |
512 | | #[inline] |
513 | 0 | fn finish(&self) -> u64 { |
514 | 0 | Self::finish_with_state(self.state, self.length, self.tail) |
515 | 0 | } |
516 | | } |
517 | | |
518 | | impl<S: Sip> Default for Hasher<S> { |
519 | | /// Creates a `Hasher<S>` with the two initial keys set to 0. |
520 | | #[inline] |
521 | 0 | fn default() -> Hasher<S> { |
522 | 0 | Hasher::new_with_keys(0, 0) |
523 | 0 | } |
524 | | } |
525 | | |
526 | | #[doc(hidden)] |
527 | | trait Sip { |
528 | | fn c_rounds(_: &mut State); |
529 | | fn d_rounds(_: &mut State); |
530 | | } |
531 | | |
532 | | #[derive(Debug, Clone, Copy, Default)] |
533 | | struct Sip13Rounds; |
534 | | |
535 | | impl Sip for Sip13Rounds { |
536 | | #[inline] |
537 | 0 | fn c_rounds(state: &mut State) { |
538 | 0 | compress!(state); |
539 | 0 | } |
540 | | |
541 | | #[inline] |
542 | 0 | fn d_rounds(state: &mut State) { |
543 | 0 | compress!(state); |
544 | 0 | compress!(state); |
545 | 0 | compress!(state); |
546 | 0 | } |
547 | | } |
548 | | |
549 | | #[derive(Debug, Clone, Copy, Default)] |
550 | | struct Sip24Rounds; |
551 | | |
552 | | impl Sip for Sip24Rounds { |
553 | | #[inline] |
554 | 0 | fn c_rounds(state: &mut State) { |
555 | 0 | compress!(state); |
556 | 0 | compress!(state); |
557 | 0 | } |
558 | | |
559 | | #[inline] |
560 | 0 | fn d_rounds(state: &mut State) { |
561 | 0 | compress!(state); |
562 | 0 | compress!(state); |
563 | 0 | compress!(state); |
564 | 0 | compress!(state); |
565 | 0 | } |
566 | | } |