1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
use std::cell::UnsafeCell;
use std::mem::MaybeUninit;
use std::rc::Rc;
use std::thread_local;
use rand::rngs::SmallRng;
use rand::{RngCore, SeedableRng};
thread_local!(
static THREAD_RNG_KEY: Rc<UnsafeCell<SmallRng>> = {
Rc::new(UnsafeCell::new(SmallRng::from_rng(&mut rand::thread_rng()).unwrap()))
}
);
pub fn fast_thread_rng() -> SmallThreadRng {
let rng = THREAD_RNG_KEY.with(|t| t.clone());
SmallThreadRng { rng }
}
pub fn gen_fast_bytes<const N: usize>() -> [u8; N] {
THREAD_RNG_KEY.with(|t| {
unsafe {
let rng = &mut *t.get();
let mut id = MaybeUninit::<[u8; N]>::uninit();
rng.fill_bytes(&mut *id.as_mut_ptr() as &mut [u8; N]);
id.assume_init()
}
})
}
pub struct SmallThreadRng {
rng: Rc<UnsafeCell<SmallRng>>,
}
impl RngCore for SmallThreadRng {
#[inline(always)]
fn next_u32(&mut self) -> u32 {
let rng = unsafe { &mut *self.rng.get() };
rng.next_u32()
}
#[inline(always)]
fn next_u64(&mut self) -> u64 {
let rng = unsafe { &mut *self.rng.get() };
rng.next_u64()
}
fn fill_bytes(&mut self, dest: &mut [u8]) {
let rng = unsafe { &mut *self.rng.get() };
rng.fill_bytes(dest)
}
fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), rand::Error> {
let rng = unsafe { &mut *self.rng.get() };
rng.try_fill_bytes(dest)
}
}