1 use core::{hint::assert_unchecked, mem}; 2 3 use super::SliceBackport as _; 4 5 #[cfg(feature = "xxhash3_128")] 6 use super::pairs_of_u64_bytes; 7 8 /// The minimum length of a secret. 9 pub const SECRET_MINIMUM_LENGTH: usize = 136; 10 11 #[repr(transparent)] 12 pub struct Secret([u8]); 13 14 impl Secret { 15 #[inline] new(bytes: &[u8]) -> Result<&Self, Error>16 pub fn new(bytes: &[u8]) -> Result<&Self, Error> { 17 // Safety: We check for validity before returning. 18 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 /// # Safety 29 /// 30 /// You must ensure that the secret byte length is >= 31 /// SECRET_MINIMUM_LENGTH. 32 #[inline] new_unchecked(bytes: &[u8]) -> &Self33 pub const unsafe fn new_unchecked(bytes: &[u8]) -> &Self { 34 // Safety: We are `#[repr(transparent)]`. It's up to the 35 // caller to ensure the length 36 unsafe { mem::transmute(bytes) } 37 } 38 39 #[inline] 40 #[cfg(feature = "xxhash3_64")] for_64(&self) -> Secret64BitView<'_>41 pub fn for_64(&self) -> Secret64BitView<'_> { 42 Secret64BitView(self) 43 } 44 45 #[inline] 46 #[cfg(feature = "xxhash3_128")] for_128(&self) -> Secret128BitView<'_>47 pub fn for_128(&self) -> Secret128BitView<'_> { 48 Secret128BitView(self) 49 } 50 51 #[inline] words_for_17_to_128(&self) -> &[[u8; 16]]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 /// # Safety 60 /// 61 /// `i` must be less than the number of stripes in the secret 62 /// ([`Self::n_stripes`][]). 63 #[inline] stripe(&self, i: usize) -> &[u8; 64]64 pub unsafe fn stripe(&self, i: usize) -> &[u8; 64] { 65 self.reassert_preconditions(); 66 67 // Safety: The caller has ensured that `i` is 68 // in-bounds. `&[u8]` and `&[u8; 64]` have the same alignment. 69 unsafe { 70 debug_assert!(i < self.n_stripes()); 71 &*self.0.get_unchecked(i * 8..).as_ptr().cast() 72 } 73 } 74 75 #[inline] last_stripe(&self) -> &[u8; 64]76 pub fn last_stripe(&self) -> &[u8; 64] { 77 self.reassert_preconditions(); 78 79 self.0.last_chunk().unwrap() 80 } 81 82 #[inline] last_stripe_secret_better_name(&self) -> &[u8; 64]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] final_secret(&self) -> &[u8; 64]90 pub fn final_secret(&self) -> &[u8; 64] { 91 self.reassert_preconditions(); 92 93 self.0[11..].first_chunk().unwrap() 94 } 95 96 #[inline] len(&self) -> usize97 pub fn len(&self) -> usize { 98 self.0.len() 99 } 100 101 #[inline] n_stripes(&self) -> usize102 pub fn n_stripes(&self) -> usize { 103 // stripes_per_block 104 (self.len() - 64) / 8 105 } 106 107 #[inline(always)] reassert_preconditions(&self)108 fn reassert_preconditions(&self) { 109 // Safety: The length of the bytes was checked at value 110 // construction time. 111 unsafe { 112 debug_assert!(self.is_valid()); 113 assert_unchecked(self.is_valid()); 114 } 115 } 116 117 #[inline(always)] is_valid(&self) -> bool118 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")] 125 pub struct Secret64BitView<'a>(&'a Secret); 126 127 #[cfg(feature = "xxhash3_64")] 128 impl<'a> Secret64BitView<'a> { 129 #[inline] words_for_0(self) -> [u64; 2]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] words_for_1_to_3(self) -> [u32; 2]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] words_for_4_to_8(self) -> [u64; 2]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] words_for_9_to_16(self) -> [u64; 4]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] words_for_127_to_240_part1(self) -> &'a [[u8; 16]]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] words_for_127_to_240_part2(self) -> &'a [[u8; 16]]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] words_for_127_to_240_part3(self) -> &'a [u8; 16]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 b(self) -> &'a [u8]184 fn b(self) -> &'a [u8] { 185 &(self.0).0 186 } 187 } 188 189 #[derive(Copy, Clone)] 190 #[cfg(feature = "xxhash3_128")] 191 pub struct Secret128BitView<'a>(&'a Secret); 192 193 #[cfg(feature = "xxhash3_128")] 194 impl<'a> Secret128BitView<'a> { 195 #[inline] words_for_0(self) -> [u64; 4]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] words_for_1_to_3(self) -> [u32; 4]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] words_for_4_to_8(self) -> [u64; 2]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] words_for_9_to_16(self) -> [u64; 4]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] words_for_127_to_240_part1(self) -> &'a [[[u8; 16]; 2]]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] words_for_127_to_240_part2(self) -> &'a [[[u8; 16]; 2]]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] words_for_127_to_240_part3(self) -> &'a [[u8; 16]; 2]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] final_secret(self) -> &'a [u8; 64]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 b(self) -> &'a [u8]256 fn b(self) -> &'a [u8] { 257 &(self.0).0 258 } 259 } 260 261 #[derive(Debug)] 262 pub struct Error(()); 263 264 impl core::error::Error for Error {} 265 266 impl core::fmt::Display for Error { fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result267 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 } 274