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