twox_hash/
lib.rs

1//! A Rust implementation of the [XXHash] algorithm.
2//!
3//! [XXHash]: https://github.com/Cyan4973/xxHash
4//!
5//! ### With a fixed seed
6//!
7//! ```rust
8//! use std::hash::BuildHasherDefault;
9//! use std::collections::HashMap;
10//! use twox_hash::XxHash64;
11//!
12//! let mut hash: HashMap<_, _, BuildHasherDefault<XxHash64>> = Default::default();
13//! hash.insert(42, "the answer");
14//! assert_eq!(hash.get(&42), Some(&"the answer"));
15//! ```
16//!
17//! ### With a random seed
18//!
19//! ```rust
20//! use std::collections::HashMap;
21//! use twox_hash::RandomXxHashBuilder64;
22//!
23//! let mut hash: HashMap<_, _, RandomXxHashBuilder64> = Default::default();
24//! hash.insert(42, "the answer");
25//! assert_eq!(hash.get(&42), Some(&"the answer"));
26//! ```
27
28#![no_std]
29
30extern crate alloc;
31
32#[cfg(test)]
33extern crate std;
34
35use core::{marker::PhantomData, mem};
36
37mod sixty_four;
38mod thirty_two;
39pub mod xxh3;
40
41#[cfg(feature = "std")]
42mod std_support;
43#[cfg(feature = "std")]
44pub use std_support::sixty_four::RandomXxHashBuilder64;
45#[cfg(feature = "std")]
46pub use std_support::thirty_two::RandomXxHashBuilder32;
47#[cfg(feature = "std")]
48pub use std_support::xxh3::{
49    RandomHashBuilder128 as RandomXxh3HashBuilder128,
50    RandomHashBuilder64 as RandomXxh3HashBuilder64,
51};
52
53#[cfg(feature = "digest")]
54mod digest_support;
55
56#[cfg(feature = "digest_0_9")]
57mod digest_0_9_support;
58
59#[cfg(feature = "digest_0_10")]
60mod digest_0_10_support;
61
62pub use crate::sixty_four::XxHash64;
63pub use crate::thirty_two::XxHash32;
64pub use crate::xxh3::{Hash128 as Xxh3Hash128, Hash64 as Xxh3Hash64};
65
66/// A backwards compatibility type alias. Consider directly using
67/// `XxHash64` instead.
68pub type XxHash = XxHash64;
69
70#[cfg(feature = "std")]
71/// A backwards compatibility type alias. Consider directly using
72/// `RandomXxHashBuilder64` instead.
73pub type RandomXxHashBuilder = RandomXxHashBuilder64;
74
75/// An unaligned buffer with iteration support for `UnalignedItem`.
76struct UnalignedBuffer<'a, T> {
77    buf: &'a [u8],
78    phantom: PhantomData<T>,
79}
80
81/// Types implementing this trait must be transmutable from a `*const
82/// u8` to `*const Self` at any possible alignment.
83///
84/// The intent is to use this with only primitive integer types (and
85/// tightly-packed arrays of those integers).
86#[allow(clippy::missing_safety_doc)]
87unsafe trait UnalignedItem {}
88
89unsafe impl UnalignedItem for [u64; 4] {}
90unsafe impl UnalignedItem for [u32; 4] {}
91unsafe impl UnalignedItem for u64 {}
92unsafe impl UnalignedItem for u32 {}
93
94impl<'a, T: UnalignedItem> UnalignedBuffer<'a, T> {
95    #[inline]
96    fn new(buf: &'a [u8]) -> Self {
97        Self {
98            buf,
99            phantom: PhantomData,
100        }
101    }
102
103    #[inline]
104    fn remaining(&self) -> &[u8] {
105        self.buf
106    }
107}
108
109impl<'a, T: UnalignedItem> Iterator for UnalignedBuffer<'a, T> {
110    type Item = T;
111
112    fn next(&mut self) -> Option<Self::Item> {
113        let size = mem::size_of::<T>();
114        self.buf.get(size..).map(|remaining| {
115            // `self.buf` has at least `size` bytes that can be read as `T`.
116            let result = unsafe { (self.buf.as_ptr() as *const T).read_unaligned() };
117            self.buf = remaining;
118            result
119        })
120    }
121}