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