1use crate::device::Device;
6use crate::error::{check_error, Result};
7use crate::ffi;
8
9#[derive(Debug, Clone)]
11pub struct EntropyStatus {
12 pub level: u32,
14 pub is_healthy: bool,
16 pub total_generated: u64,
18 pub generation_rate: f64,
20}
21
22impl EntropyStatus {
23 pub(crate) fn from_ffi(status: &ffi::quac_entropy_status_t) -> Self {
24 Self {
25 level: status.level,
26 is_healthy: status.is_healthy != 0,
27 total_generated: status.total_generated,
28 generation_rate: status.generation_rate,
29 }
30 }
31}
32
33#[derive(Clone)]
62pub struct Random {
63 device: Device,
64}
65
66impl Random {
67 pub(crate) fn new(device: Device) -> Self {
69 Self { device }
70 }
71
72 pub fn get_entropy_status(&self) -> Result<EntropyStatus> {
74 let mut status = ffi::quac_entropy_status_t::default();
75 let result = unsafe { ffi::quac_get_entropy_status(self.device.handle(), &mut status) };
76 check_error(result)?;
77 Ok(EntropyStatus::from_ffi(&status))
78 }
79
80 pub fn bytes(&self, length: usize) -> Result<Vec<u8>> {
90 let mut buffer = vec![0u8; length];
91 self.fill(&mut buffer)?;
92 Ok(buffer)
93 }
94
95 pub fn fill(&self, buffer: &mut [u8]) -> Result<()> {
101 let result = unsafe {
102 ffi::quac_random_bytes(self.device.handle(), buffer.as_mut_ptr(), buffer.len())
103 };
104 check_error(result)
105 }
106
107 pub fn next_u8(&self) -> Result<u8> {
109 let mut buf = [0u8; 1];
110 self.fill(&mut buf)?;
111 Ok(buf[0])
112 }
113
114 pub fn next_u16(&self) -> Result<u16> {
116 let mut buf = [0u8; 2];
117 self.fill(&mut buf)?;
118 Ok(u16::from_le_bytes(buf))
119 }
120
121 pub fn next_u32(&self) -> Result<u32> {
123 let mut buf = [0u8; 4];
124 self.fill(&mut buf)?;
125 Ok(u32::from_le_bytes(buf))
126 }
127
128 pub fn next_u64(&self) -> Result<u64> {
130 let mut buf = [0u8; 8];
131 self.fill(&mut buf)?;
132 Ok(u64::from_le_bytes(buf))
133 }
134
135 pub fn next_i32(&self) -> Result<i32> {
137 let mut buf = [0u8; 4];
138 self.fill(&mut buf)?;
139 Ok(i32::from_le_bytes(buf))
140 }
141
142 pub fn next_i64(&self) -> Result<i64> {
144 let mut buf = [0u8; 8];
145 self.fill(&mut buf)?;
146 Ok(i64::from_le_bytes(buf))
147 }
148
149 pub fn next_u32_bound(&self, bound: u32) -> Result<u32> {
153 if bound == 0 {
154 return Ok(0);
155 }
156 if bound.is_power_of_two() {
157 return Ok(self.next_u32()? & (bound - 1));
158 }
159
160 let threshold = bound.wrapping_neg() % bound;
161 loop {
162 let r = self.next_u32()?;
163 if r >= threshold {
164 return Ok(r % bound);
165 }
166 }
167 }
168
169 pub fn next_u64_bound(&self, bound: u64) -> Result<u64> {
171 if bound == 0 {
172 return Ok(0);
173 }
174 if bound.is_power_of_two() {
175 return Ok(self.next_u64()? & (bound - 1));
176 }
177
178 let threshold = bound.wrapping_neg() % bound;
179 loop {
180 let r = self.next_u64()?;
181 if r >= threshold {
182 return Ok(r % bound);
183 }
184 }
185 }
186
187 pub fn randint(&self, min: i64, max: i64) -> Result<i64> {
189 if min > max {
190 return Ok(min);
191 }
192 let range = (max - min) as u64 + 1;
193 let r = self.next_u64_bound(range)?;
194 Ok(min + r as i64)
195 }
196
197 pub fn next_f32(&self) -> Result<f32> {
199 let r = self.next_u32()? >> 8;
201 Ok(r as f32 / (1u32 << 24) as f32)
202 }
203
204 pub fn next_f64(&self) -> Result<f64> {
206 let r = self.next_u64()? >> 11;
208 Ok(r as f64 / (1u64 << 53) as f64)
209 }
210
211 pub fn uniform(&self, min: f64, max: f64) -> Result<f64> {
213 let r = self.next_f64()?;
214 Ok(min + (max - min) * r)
215 }
216
217 pub fn next_bool(&self) -> Result<bool> {
219 Ok((self.next_u8()? & 1) != 0)
220 }
221
222 pub fn next_bool_with_probability(&self, p: f64) -> Result<bool> {
224 Ok(self.next_f64()? < p)
225 }
226
227 pub fn uuid(&self) -> Result<String> {
232 let mut bytes = [0u8; 16];
233 self.fill(&mut bytes)?;
234
235 bytes[6] = (bytes[6] & 0x0f) | 0x40;
237 bytes[8] = (bytes[8] & 0x3f) | 0x80;
239
240 Ok(format!(
241 "{:02x}{:02x}{:02x}{:02x}-{:02x}{:02x}-{:02x}{:02x}-{:02x}{:02x}-{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}",
242 bytes[0], bytes[1], bytes[2], bytes[3],
243 bytes[4], bytes[5],
244 bytes[6], bytes[7],
245 bytes[8], bytes[9],
246 bytes[10], bytes[11], bytes[12], bytes[13], bytes[14], bytes[15]
247 ))
248 }
249
250 pub fn choice<'a, T>(&self, items: &'a [T]) -> Result<Option<&'a T>> {
252 if items.is_empty() {
253 return Ok(None);
254 }
255 let idx = self.next_u64_bound(items.len() as u64)? as usize;
256 Ok(Some(&items[idx]))
257 }
258
259 pub fn sample<T: Clone>(&self, items: &[T], n: usize) -> Result<Vec<T>> {
261 if n >= items.len() {
262 return Ok(items.to_vec());
263 }
264
265 let mut pool: Vec<usize> = (0..items.len()).collect();
266 let mut result = Vec::with_capacity(n);
267
268 for _ in 0..n {
269 let idx = self.next_u64_bound(pool.len() as u64)? as usize;
270 result.push(items[pool[idx]].clone());
271 pool.swap_remove(idx);
272 }
273
274 Ok(result)
275 }
276
277 pub fn shuffle<T>(&self, items: &mut [T]) -> Result<()> {
279 for i in (1..items.len()).rev() {
280 let j = self.next_u64_bound((i + 1) as u64)? as usize;
281 items.swap(i, j);
282 }
283 Ok(())
284 }
285
286 pub fn shuffled<T: Clone>(&self, items: &[T]) -> Result<Vec<T>> {
288 let mut result = items.to_vec();
289 self.shuffle(&mut result)?;
290 Ok(result)
291 }
292}
293
294impl std::fmt::Debug for Random {
295 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
296 f.debug_struct("Random").finish()
297 }
298}
299
300#[cfg(test)]
301mod tests {
302 use super::*;
303
304 #[test]
305 fn test_entropy_status() {
306 let status = EntropyStatus {
307 level: 80,
308 is_healthy: true,
309 total_generated: 1000000,
310 generation_rate: 1000.0,
311 };
312 assert!(status.is_healthy);
313 assert_eq!(status.level, 80);
314 }
315}