Skip to main content

reifydb_runtime/context/rng/
mod.rs

1// SPDX-License-Identifier: Apache-2.0
2// Copyright (c) 2026 ReifyDB
3
4use 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}