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 30 extern crate alloc; 31 32 #[cfg(test)] 33 extern crate std; 34 35 use core::{marker::PhantomData, mem}; 36 37 mod sixty_four; 38 mod thirty_two; 39 pub mod xxh3; 40 41 #[cfg(feature = "std")] 42 mod std_support; 43 #[cfg(feature = "std")] 44 pub use std_support::sixty_four::RandomXxHashBuilder64; 45 #[cfg(feature = "std")] 46 pub use std_support::thirty_two::RandomXxHashBuilder32; 47 #[cfg(feature = "std")] 48 pub use std_support::xxh3::{ 49 RandomHashBuilder128 as RandomXxh3HashBuilder128, 50 RandomHashBuilder64 as RandomXxh3HashBuilder64, 51 }; 52 53 #[cfg(feature = "digest")] 54 mod digest_support; 55 56 #[cfg(feature = "digest_0_9")] 57 mod digest_0_9_support; 58 59 #[cfg(feature = "digest_0_10")] 60 mod digest_0_10_support; 61 62 pub use crate::sixty_four::XxHash64; 63 pub use crate::thirty_two::XxHash32; 64 pub use crate::xxh3::{Hash128 as Xxh3Hash128, Hash64 as Xxh3Hash64}; 65 66 /// A backwards compatibility type alias. Consider directly using 67 /// `XxHash64` instead. 68 pub type XxHash = XxHash64; 69 70 #[cfg(feature = "std")] 71 /// A backwards compatibility type alias. Consider directly using 72 /// `RandomXxHashBuilder64` instead. 73 pub type RandomXxHashBuilder = RandomXxHashBuilder64; 74 75 /// An unaligned buffer with iteration support for `UnalignedItem`. 76 struct 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)] 87 unsafe trait UnalignedItem {} 88 89 unsafe impl UnalignedItem for [u64; 4] {} 90 unsafe impl UnalignedItem for [u32; 4] {} 91 unsafe impl UnalignedItem for u64 {} 92 unsafe impl UnalignedItem for u32 {} 93 94 impl<'a, T: UnalignedItem> UnalignedBuffer<'a, T> { 95 #[inline] new(buf: &'a [u8]) -> Self96 fn new(buf: &'a [u8]) -> Self { 97 Self { 98 buf, 99 phantom: PhantomData, 100 } 101 } 102 103 #[inline] remaining(&self) -> &[u8]104 fn remaining(&self) -> &[u8] { 105 self.buf 106 } 107 } 108 109 impl<'a, T: UnalignedItem> Iterator for UnalignedBuffer<'a, T> { 110 type Item = T; 111 next(&mut self) -> Option<Self::Item>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 } 122