osom_lib_rand/randomness_sources/
os_randomness_source.rs

1use core::marker::PhantomData;
2
3use crate::{number::{Number, NumberType}, traits::RandomnessSource};
4
5#[inline(always)]
6fn next_os_number<ANumber: Number>() -> ANumber {
7    match ANumber::NUMBER_TYPE {
8        NumberType::U32 => {
9            let no = getrandom::u32().expect("Failed to get u32 random number from OS");
10            ANumber::from_u32(no)
11        }
12        NumberType::U64 => {
13            let no = getrandom::u64().expect("Failed to get u64 random number from OS");
14            unsafe { ANumber::from_u64_unchecked(no) }
15        }
16        NumberType::U128 => {
17            let mut array = [0u8; size_of::<u128>()];
18            getrandom::fill(&mut array).expect("Failed to get u128 random number from OS");
19            let no = u128::from_ne_bytes(array);
20            unsafe { ANumber::from_u128_unchecked(no) }
21        }
22    }
23}
24
25/// Randomness source that retrieves randomness from the operating system.
26/// 
27/// At the moment implemented using [`getrandom`] crate.
28#[derive(Debug, Clone, PartialEq, Eq)]
29#[must_use]
30#[repr(transparent)]
31pub struct OsRandomnessSource<ANumber: Number> {
32    _phantom: PhantomData<ANumber>,
33}
34
35impl<ANumber: Number> Default for OsRandomnessSource<ANumber> {
36    fn default() -> Self {
37        Self {
38            _phantom: PhantomData,
39        }
40    }
41}
42
43impl<ANumber: Number> RandomnessSource for OsRandomnessSource<ANumber> {
44    type TNumber = ANumber;
45
46    fn next_number(&mut self) -> Self::TNumber {
47        next_os_number()
48    }
49
50    fn fill_bytes(&mut self, bytes: &mut [u8]) {
51        if bytes.is_empty() {
52            return;
53        }
54
55        getrandom::fill(bytes).expect("Failed to fill bytes from OS");
56    }
57}