Skip to main content

reifydb_runtime/context/rng/
mod.rs

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