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: usize = mem::size_of::<T>();
114 self.buf.get(index:size..).map(|remaining: &[u8]| {
115 // `self.buf` has at least `size` bytes that can be read as `T`.
116 let result: T = unsafe { (self.buf.as_ptr() as *const T).read_unaligned() };
117 self.buf = remaining;
118 result
119 })
120 }
121}
122