Coverage Report

Created: 2026-05-16 07:11

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
}