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