reifydb_runtime/context/rng/
mod.rs1use std::sync::Arc;
5
6use getrandom::fill as getrandom_fill;
7use rand::{Rng as RandRng, RngExt, SeedableRng, rngs::StdRng};
8use reifydb_value::clock::RandomBytes;
9
10use crate::sync::mutex::Mutex;
11
12#[derive(Clone, Default)]
13pub enum Rng {
14 #[default]
15 Os,
16
17 Seeded(SeededRng),
18}
19
20impl RandomBytes for Rng {
21 fn bytes_10(&self) -> [u8; 10] {
22 self.bytes_10()
23 }
24}
25
26impl Rng {
27 pub fn seeded(seed: u64) -> Self {
28 Rng::Seeded(SeededRng::new(seed))
29 }
30
31 pub fn bytes_16(&self) -> [u8; 16] {
32 match self {
33 Rng::Os => {
34 let mut buf = [0u8; 16];
35 getrandom_fill(&mut buf).expect("getrandom failed");
36 buf
37 }
38 Rng::Seeded(seeded) => {
39 let mut buf = [0u8; 16];
40 let mut rng = seeded.inner.lock();
41 rng.fill_bytes(&mut buf);
42 buf
43 }
44 }
45 }
46
47 pub fn bytes_32(&self) -> [u8; 32] {
48 match self {
49 Rng::Os => {
50 let mut buf = [0u8; 32];
51 getrandom_fill(&mut buf).expect("getrandom failed");
52 buf
53 }
54 Rng::Seeded(seeded) => {
55 let mut buf = [0u8; 32];
56 let mut rng = seeded.inner.lock();
57 rng.fill_bytes(&mut buf);
58 buf
59 }
60 }
61 }
62
63 pub fn bytes_10(&self) -> [u8; 10] {
64 match self {
65 Rng::Os => {
66 let mut buf = [0u8; 10];
67 getrandom_fill(&mut buf).expect("getrandom failed");
68 buf
69 }
70 Rng::Seeded(seeded) => {
71 let mut buf = [0u8; 10];
72 let mut rng = seeded.inner.lock();
73 rng.fill_bytes(&mut buf);
74 buf
75 }
76 }
77 }
78
79 pub fn infra_bytes_10(&self) -> [u8; 10] {
80 match self {
81 Rng::Os => {
82 let mut buf = [0u8; 10];
83 getrandom_fill(&mut buf).expect("getrandom failed");
84 buf
85 }
86 Rng::Seeded(seeded) => {
87 let mut buf = [0u8; 10];
88 let mut rng = seeded.infra.lock();
89 rng.fill_bytes(&mut buf);
90 buf
91 }
92 }
93 }
94
95 pub fn infra_bytes_32(&self) -> [u8; 32] {
96 match self {
97 Rng::Os => {
98 let mut buf = [0u8; 32];
99 getrandom_fill(&mut buf).expect("getrandom failed");
100 buf
101 }
102 Rng::Seeded(seeded) => {
103 let mut buf = [0u8; 32];
104 let mut rng = seeded.infra.lock();
105 rng.fill_bytes(&mut buf);
106 buf
107 }
108 }
109 }
110
111 pub fn infra_u64_inclusive(&self, max_inclusive: u64) -> u64 {
112 if max_inclusive == 0 {
113 return 0;
114 }
115 match self {
116 Rng::Os => {
117 let mut buf = [0u8; 8];
118 getrandom_fill(&mut buf).expect("getrandom failed");
119 let raw = u64::from_le_bytes(buf);
120 if max_inclusive == u64::MAX {
121 raw
122 } else {
123 raw % (max_inclusive + 1)
124 }
125 }
126 Rng::Seeded(seeded) => {
127 let mut rng = seeded.infra.lock();
128 rng.random_range(0..=max_inclusive)
129 }
130 }
131 }
132}
133
134#[derive(Clone)]
135pub struct SeededRng {
136 inner: Arc<Mutex<StdRng>>,
137
138 infra: Arc<Mutex<StdRng>>,
139}
140
141impl SeededRng {
142 pub fn new(seed: u64) -> Self {
143 Self {
144 inner: Arc::new(Mutex::new(StdRng::seed_from_u64(seed))),
145 infra: Arc::new(Mutex::new(StdRng::seed_from_u64(seed ^ 0x5A5A5A5A5A5A5A5A))),
146 }
147 }
148}