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 ] |
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 | |
109 | impl<'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 | |