twox_hash/xxhash3/
secret.rs1use core::{hint::assert_unchecked, mem};
2
3use super::SliceBackport as _;
4
5#[cfg(feature = "xxhash3_128")]
6use super::pairs_of_u64_bytes;
7
8pub const SECRET_MINIMUM_LENGTH: usize = 136;
10
11#[repr(transparent)]
12pub struct Secret([u8]);
13
14impl Secret {
15 #[inline]
16 pub fn new(bytes: &[u8]) -> Result<&Self, Error> {
17 unsafe {
19 let this = Self::new_unchecked(bytes);
20 if this.is_valid() {
21 Ok(this)
22 } else {
23 Err(Error(()))
24 }
25 }
26 }
27
28 #[inline]
33 pub const unsafe fn new_unchecked(bytes: &[u8]) -> &Self {
34 unsafe { mem::transmute(bytes) }
37 }
38
39 #[inline]
40 #[cfg(feature = "xxhash3_64")]
41 pub fn for_64(&self) -> Secret64BitView<'_> {
42 Secret64BitView(self)
43 }
44
45 #[inline]
46 #[cfg(feature = "xxhash3_128")]
47 pub fn for_128(&self) -> Secret128BitView<'_> {
48 Secret128BitView(self)
49 }
50
51 #[inline]
52 pub fn words_for_17_to_128(&self) -> &[[u8; 16]] {
53 self.reassert_preconditions();
54
55 let (words, _) = self.0.bp_as_chunks();
56 words
57 }
58
59 #[inline]
64 pub unsafe fn stripe(&self, i: usize) -> &[u8; 64] {
65 self.reassert_preconditions();
66
67 unsafe {
70 debug_assert!(i < self.n_stripes());
71 &*self.0.get_unchecked(i * 8..).as_ptr().cast()
72 }
73 }
74
75 #[inline]
76 pub fn last_stripe(&self) -> &[u8; 64] {
77 self.reassert_preconditions();
78
79 self.0.last_chunk().unwrap()
80 }
81
82 #[inline]
83 pub fn last_stripe_secret_better_name(&self) -> &[u8; 64] {
84 self.reassert_preconditions();
85
86 self.0[self.0.len() - 71..].first_chunk().unwrap()
87 }
88
89 #[inline]
90 pub fn final_secret(&self) -> &[u8; 64] {
91 self.reassert_preconditions();
92
93 self.0[11..].first_chunk().unwrap()
94 }
95
96 #[inline]
97 pub fn len(&self) -> usize {
98 self.0.len()
99 }
100
101 #[inline]
102 pub fn n_stripes(&self) -> usize {
103 (self.len() - 64) / 8
105 }
106
107 #[inline(always)]
108 fn reassert_preconditions(&self) {
109 unsafe {
112 debug_assert!(self.is_valid());
113 assert_unchecked(self.is_valid());
114 }
115 }
116
117 #[inline(always)]
118 pub fn is_valid(&self) -> bool {
119 self.0.len() >= SECRET_MINIMUM_LENGTH
120 }
121}
122
123#[derive(Copy, Clone)]
124#[cfg(feature = "xxhash3_64")]
125pub struct Secret64BitView<'a>(&'a Secret);
126
127#[cfg(feature = "xxhash3_64")]
128impl<'a> Secret64BitView<'a> {
129 #[inline]
130 pub fn words_for_0(self) -> [u64; 2] {
131 self.0.reassert_preconditions();
132
133 let (q, _) = self.b()[56..].bp_as_chunks();
134 [q[0], q[1]].map(u64::from_le_bytes)
135 }
136
137 #[inline]
138 pub fn words_for_1_to_3(self) -> [u32; 2] {
139 self.0.reassert_preconditions();
140
141 let (q, _) = self.b().bp_as_chunks();
142 [q[0], q[1]].map(u32::from_le_bytes)
143 }
144
145 #[inline]
146 pub fn words_for_4_to_8(self) -> [u64; 2] {
147 self.0.reassert_preconditions();
148
149 let (q, _) = self.b()[8..].bp_as_chunks();
150 [q[0], q[1]].map(u64::from_le_bytes)
151 }
152
153 #[inline]
154 pub fn words_for_9_to_16(self) -> [u64; 4] {
155 self.0.reassert_preconditions();
156
157 let (q, _) = self.b()[24..].bp_as_chunks();
158 [q[0], q[1], q[2], q[3]].map(u64::from_le_bytes)
159 }
160
161 #[inline]
162 pub fn words_for_127_to_240_part1(self) -> &'a [[u8; 16]] {
163 self.0.reassert_preconditions();
164
165 let (ss, _) = self.b().bp_as_chunks();
166 ss
167 }
168
169 #[inline]
170 pub fn words_for_127_to_240_part2(self) -> &'a [[u8; 16]] {
171 self.0.reassert_preconditions();
172
173 let (ss, _) = self.b()[3..].bp_as_chunks();
174 ss
175 }
176
177 #[inline]
178 pub fn words_for_127_to_240_part3(self) -> &'a [u8; 16] {
179 self.0.reassert_preconditions();
180
181 self.b()[119..].first_chunk().unwrap()
182 }
183
184 fn b(self) -> &'a [u8] {
185 &(self.0).0
186 }
187}
188
189#[derive(Copy, Clone)]
190#[cfg(feature = "xxhash3_128")]
191pub struct Secret128BitView<'a>(&'a Secret);
192
193#[cfg(feature = "xxhash3_128")]
194impl<'a> Secret128BitView<'a> {
195 #[inline]
196 pub fn words_for_0(self) -> [u64; 4] {
197 self.0.reassert_preconditions();
198
199 let (q, _) = self.b()[64..].bp_as_chunks();
200 [q[0], q[1], q[2], q[3]].map(u64::from_le_bytes)
201 }
202
203 #[inline]
204 pub fn words_for_1_to_3(self) -> [u32; 4] {
205 self.0.reassert_preconditions();
206
207 let (q, _) = self.b().bp_as_chunks();
208 [q[0], q[1], q[2], q[3]].map(u32::from_le_bytes)
209 }
210
211 #[inline]
212 pub fn words_for_4_to_8(self) -> [u64; 2] {
213 self.0.reassert_preconditions();
214
215 let (q, _) = self.b()[16..].bp_as_chunks();
216 [q[0], q[1]].map(u64::from_le_bytes)
217 }
218
219 #[inline]
220 pub fn words_for_9_to_16(self) -> [u64; 4] {
221 self.0.reassert_preconditions();
222
223 let (q, _) = self.b()[32..].bp_as_chunks();
224 [q[0], q[1], q[2], q[3]].map(u64::from_le_bytes)
225 }
226
227 #[inline]
228 pub fn words_for_127_to_240_part1(self) -> &'a [[[u8; 16]; 2]] {
229 self.0.reassert_preconditions();
230
231 pairs_of_u64_bytes(self.b())
232 }
233
234 #[inline]
235 pub fn words_for_127_to_240_part2(self) -> &'a [[[u8; 16]; 2]] {
236 self.0.reassert_preconditions();
237
238 pairs_of_u64_bytes(&self.b()[3..])
239 }
240
241 #[inline]
242 pub fn words_for_127_to_240_part3(self) -> &'a [[u8; 16]; 2] {
243 self.0.reassert_preconditions();
244
245 pairs_of_u64_bytes(&self.b()[103..]).first().unwrap()
246 }
247
248 #[inline]
249 pub fn final_secret(self) -> &'a [u8; 64] {
250 self.0.reassert_preconditions();
251
252 let b = self.b();
253 b[b.len() - 75..].first_chunk().unwrap()
254 }
255
256 fn b(self) -> &'a [u8] {
257 &(self.0).0
258 }
259}
260
261#[derive(Debug)]
262pub struct Error(());
263
264impl core::error::Error for Error {}
265
266impl core::fmt::Display for Error {
267 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
268 write!(
269 f,
270 "The secret must have at least {SECRET_MINIMUM_LENGTH} bytes"
271 )
272 }
273}