1use std::{hash, marker, mem};
4
5use dope_core::{driver, driver::schedule::sequence, random::Seed};
6use o3::base::marker::ThreadBound;
7
8mod sip;
9
10pub(crate) use sip::Sip;
11
12type SipHasher13 = Sip<1, 3>;
13type SipHasher24 = Sip<2, 4>;
14
15pub type OwnedHasher = Sip<1, 3>;
17
18pub(crate) fn derive_seed(seed: &Seed, domain: Domain) -> Seed {
19 seed.map(|words| Key::new(words).derive(domain, ()).into_words())
20}
21
22type Invariant<'d> = marker::PhantomData<(fn(&'d ()) -> &'d (), ThreadBound)>;
23
24#[derive(Clone)]
28pub struct HashSeed {
29 state: (Key, ThreadBound),
30}
31
32impl HashSeed {
33 pub fn from_seed(seed: &Seed, domain: Domain) -> Self {
34 Self {
35 state: (
36 Key::new(*seed.as_ref()).derive(domain, ()),
37 ThreadBound::NEW,
38 ),
39 }
40 }
41
42 pub fn hash<T: hash::Hash + ?Sized>(&self, input: &T) -> u64 {
43 let mut state = self.state.0.hasher();
44 input.hash(&mut state);
45 hash::Hasher::finish(&state)
46 }
47
48 pub fn hash_bytes(&self, input: &[u8]) -> u64 {
50 self.state.0.hasher().hash(input)
51 }
52}
53
54impl hash::BuildHasher for HashSeed {
55 type Hasher = OwnedHasher;
56
57 fn build_hasher(&self) -> Self::Hasher {
58 self.state.0.hasher()
59 }
60}
61
62pub struct HashState<'d> {
67 state: (Key, Invariant<'d>),
68}
69
70impl<'d> HashState<'d> {
71 pub(crate) fn for_seed(seed: &Seed, domain: Domain) -> Self {
72 Self {
73 state: (
74 Key::new(*seed.as_ref()).derive(domain, ()),
75 marker::PhantomData,
76 ),
77 }
78 }
79}
80
81impl<'d> hash::BuildHasher for HashState<'d> {
82 type Hasher = Hasher<'d>;
83
84 fn build_hasher(&self) -> Self::Hasher {
85 Hasher::new(self.state.0.hasher(), self.state.1)
86 }
87}
88
89pub struct Hasher<'d> {
91 state: (SipHasher13, Invariant<'d>),
92}
93
94impl<'d> Hasher<'d> {
95 const fn new(inner: SipHasher13, proof: Invariant<'d>) -> Self {
96 Self {
97 state: (inner, proof),
98 }
99 }
100}
101
102impl hash::Hasher for Hasher<'_> {
103 fn finish(&self) -> u64 {
104 self.state.0.finish()
105 }
106
107 fn write(&mut self, bytes: &[u8]) {
108 self.state.0.write(bytes);
109 }
110
111 fn write_u8(&mut self, value: u8) {
112 self.state.0.write_u8(value);
113 }
114
115 fn write_u16(&mut self, value: u16) {
116 self.state.0.write_u16(value);
117 }
118
119 fn write_u32(&mut self, value: u32) {
120 self.state.0.write_u32(value);
121 }
122
123 fn write_u64(&mut self, value: u64) {
124 self.state.0.write_u64(value);
125 }
126
127 fn write_usize(&mut self, value: usize) {
128 self.state.0.write_usize(value);
129 }
130}
131
132pub trait Purpose {
135 const DOMAIN: Domain;
136}
137
138pub trait Entropy<P: Purpose> {
142 fn word<const LANE: u64>(&self, input: u64) -> Word<P, LANE>;
143 fn permute<const LANE: u64>(&self, value: u64) -> Word<P, LANE>;
144
145 fn hash_seed<const LANE: u64>(&self) -> HashSeed;
149}
150
151type RootState<'d, P> = (Key, Invariant<'d>, marker::PhantomData<fn(P) -> P>);
152type ProcessState<P> = (Key, marker::PhantomData<(fn(P) -> P, ThreadBound)>);
153
154pub struct Root<'d, P: Purpose> {
158 state: RootState<'d, P>,
159}
160
161impl<'d, P: Purpose> Root<'d, P> {
162 const fn new(seed: Key) -> Self {
163 Self {
164 state: (seed, marker::PhantomData, marker::PhantomData),
165 }
166 }
167
168 pub fn hash<const LANE: u64, T: hash::Hash + ?Sized>(&self, input: &T) -> Word<P, LANE> {
171 self.state.0.hash::<P, LANE, T>(input)
172 }
173}
174
175pub struct Process<P: Purpose> {
177 state: ProcessState<P>,
178}
179
180impl<P: Purpose> Process<P> {
181 pub fn random() -> Result<Self, dope_core::Errno> {
182 let seed = Key::new(*Seed::acquire()?.as_ref()).derive(P::DOMAIN, ());
183 Ok(Self {
184 state: (seed, marker::PhantomData),
185 })
186 }
187}
188
189impl<P: Purpose> Entropy<P> for Root<'_, P> {
190 fn word<const LANE: u64>(&self, input: u64) -> Word<P, LANE> {
191 self.state.0.hash::<P, LANE, _>(&input)
192 }
193
194 fn permute<const LANE: u64>(&self, value: u64) -> Word<P, LANE> {
195 self.state.0.permute::<P, LANE>(value)
196 }
197
198 fn hash_seed<const LANE: u64>(&self) -> HashSeed {
199 self.state.0.hash_seed::<LANE>()
200 }
201}
202
203impl<P: Purpose> Entropy<P> for Process<P> {
204 fn word<const LANE: u64>(&self, input: u64) -> Word<P, LANE> {
205 self.state.0.hash::<P, LANE, _>(&input)
206 }
207
208 fn permute<const LANE: u64>(&self, value: u64) -> Word<P, LANE> {
209 self.state.0.permute::<P, LANE>(value)
210 }
211
212 fn hash_seed<const LANE: u64>(&self) -> HashSeed {
213 self.state.0.hash_seed::<LANE>()
214 }
215}
216
217impl<'d, P: Purpose> Root<'d, P> {
218 pub fn try_acquire(driver: &driver::Context<'_, 'd>) -> Result<Self, sequence::Exhausted> {
221 let driver = driver.driver_ref();
222 let instance = driver.try_next_id()?;
223 let seed = Key::new(*driver.random_seed().as_ref());
224 Ok(Self::new(seed.derive(P::DOMAIN, instance)))
225 }
226}
227
228const _: () = assert!(mem::size_of::<HashState<'static>>() == 2 * mem::size_of::<u64>());
229const _: () = assert!(mem::size_of::<HashSeed>() == 2 * mem::size_of::<u64>());
230const _: () = assert!(
231 mem::size_of::<OwnedHasher>() == 2 * mem::size_of::<usize>() + 5 * mem::size_of::<u64>()
232);
233const _: () = assert!(mem::size_of::<Hasher<'static>>() == mem::size_of::<SipHasher13>());
234
235#[repr(transparent)]
237#[derive(Clone)]
238struct Key([u64; 2]);
239
240impl Key {
241 const fn new(words: [u64; 2]) -> Self {
242 Self(words)
243 }
244
245 const fn into_words(self) -> [u64; 2] {
246 self.0
247 }
248
249 fn derive(&self, domain: Domain, instance: impl hash::Hash) -> Self {
250 let mut state = self.prefix(domain);
251 instance.hash(&mut state);
252 Self::from_hasher(state)
253 }
254
255 fn from_hasher(state: SipHasher24) -> Self {
256 Self([0, 1].map(|word| {
257 let mut state = state;
258 hash::Hasher::write_u64(&mut state, word);
259 hash::Hasher::finish(&state)
260 }))
261 }
262
263 fn hasher(&self) -> SipHasher13 {
264 SipHasher13::new(self.0[0], self.0[1])
265 }
266
267 fn hash_seed<const LANE: u64>(&self) -> HashSeed {
268 HashSeed {
269 state: (Self::from_hasher(self.lane::<LANE>(2)), ThreadBound::NEW),
270 }
271 }
272
273 fn hash<P, const LANE: u64, T: hash::Hash + ?Sized>(&self, input: &T) -> Word<P, LANE> {
274 let mut state = self.lane::<LANE>(0);
275 input.hash(&mut state);
276 Word::new(hash::Hasher::finish(&state))
277 }
278
279 fn permute<P, const LANE: u64>(&self, value: u64) -> Word<P, LANE> {
280 let state = self.lane::<LANE>(1);
281 let mut left = (value >> 32) as u32;
282 let mut right = value as u32;
283 let mut round = 0;
284 while round < 4 {
285 let input = ((round as u64) << 32) | u64::from(right);
286 let mut hash = state;
287 hash::Hasher::write_u64(&mut hash, input);
288 let next = left ^ hash::Hasher::finish(&hash) as u32;
289 left = right;
290 right = next;
291 round += 1;
292 }
293 Word::new((u64::from(left) << 32) | u64::from(right))
294 }
295
296 fn lane<const LANE: u64>(&self, kind: u8) -> SipHasher24 {
297 let mut state = SipHasher24::new(self.0[0], self.0[1]);
298 hash::Hasher::write_u64(&mut state, LANE);
299 hash::Hasher::write_u8(&mut state, kind);
300 state
301 }
302
303 fn prefix(&self, domain: Domain) -> SipHasher24 {
304 let mut state = SipHasher24::new(self.0[0], self.0[1]);
305 hash::Hasher::write(&mut state, &domain.namespace);
306 hash::Hasher::write_u64(&mut state, domain.instance);
307 state
308 }
309}
310
311#[derive(Clone, Copy, PartialEq, Eq, Hash)]
313#[repr(transparent)]
314pub struct Namespace([u8; 8]);
315
316impl Namespace {
317 pub const fn new(name: [u8; 8]) -> Self {
318 Self(name)
319 }
320
321 pub const fn fixed(self) -> Domain {
322 self.instance(0)
323 }
324
325 pub const fn instance(self, instance: u64) -> Domain {
326 Domain {
327 namespace: self.0,
328 instance,
329 }
330 }
331}
332
333#[derive(Clone, Copy, PartialEq, Eq, Hash)]
335pub struct Domain {
336 namespace: [u8; 8],
337 instance: u64,
338}
339
340#[repr(transparent)]
342pub struct Word<P, const LANE: u64>(u64, marker::PhantomData<fn(P) -> P>);
343
344impl<P, const LANE: u64> Word<P, LANE> {
345 const fn new(value: u64) -> Self {
346 Self(value, marker::PhantomData)
347 }
348
349 pub const fn into_bytes(self) -> [u8; 8] {
351 self.0.to_be_bytes()
352 }
353}
354
355const _: () = {
356 assert!(mem::size_of::<Key>() == 2 * mem::size_of::<u64>());
357 assert!(mem::size_of::<Namespace>() == mem::size_of::<u64>());
358 assert!(mem::size_of::<Domain>() == 2 * mem::size_of::<u64>());
359 assert!(mem::size_of::<Word<(), 0>>() == mem::size_of::<u64>());
360};