osom_lib_entropy_cprng/
cprng_entropy.rs1use core::convert::Infallible;
4
5use osom_lib_entropy::{
6 std::StdEntropyGenerator,
7 traits::{EntropyConcreteGenerator, EntropyGenerator},
8};
9use osom_lib_prng::traits::{CryptographicallySecure, PRNGenerator, Seedable};
10use osom_lib_reprc::macros::reprc;
11use osom_lib_try_clone::TryClone;
12
13#[reprc]
17#[repr(transparent)]
18#[derive(Clone)]
19pub struct CPRNGEntropy<TPrng>
20where
21 TPrng: PRNGenerator + CryptographicallySecure + Seedable<u128>,
22{
23 cprng: TPrng,
24}
25
26impl<TPrng> TryClone for CPRNGEntropy<TPrng>
27where
28 TPrng: PRNGenerator + CryptographicallySecure + Seedable<u128> + TryClone,
29{
30 type Error = <TPrng as TryClone>::Error;
31
32 fn try_clone(&self) -> Result<Self, Self::Error> {
33 let cprng = self.cprng.try_clone()?;
34 Ok(Self { cprng })
35 }
36}
37
38impl<TPrng> CPRNGEntropy<TPrng>
39where
40 TPrng: PRNGenerator + CryptographicallySecure + Seedable<u128>,
41{
42 pub fn new() -> Result<Self, <StdEntropyGenerator as EntropyGenerator>::Error> {
49 let mut entropy = StdEntropyGenerator::new();
50 let seed = entropy.generate::<u128>()?;
51 let cprng = TPrng::with_seed(seed);
52 Ok(Self { cprng })
53 }
54
55 #[allow(clippy::missing_panics_doc)]
57 #[inline(always)]
58 pub fn generate<T: EntropyConcreteGenerator<CPRNGEntropy<TPrng>>>(&mut self) -> T {
59 let result: Result<T, Infallible> = <Self as EntropyGenerator>::generate::<T>(self);
62 result.unwrap()
63 }
64}
65
66impl<TPrng> EntropyGenerator for CPRNGEntropy<TPrng>
67where
68 TPrng: PRNGenerator + CryptographicallySecure + Seedable<u128>,
69{
70 type Error = Infallible;
72
73 unsafe fn fill_raw(&mut self, buffer_ptr: *mut u8, buffer_len: usize) -> Result<(), Infallible> {
74 unsafe {
75 self.cprng.fill_raw(buffer_ptr, buffer_len);
76 }
77 Ok(())
78 }
79}
80
81#[inline]
82fn generate_random_t<T: Copy, TGen: EntropyGenerator>(gene: &mut TGen) -> Result<T, TGen::Error> {
83 let mut item = core::mem::MaybeUninit::<T>::uninit();
84 let item_ptr = item.as_mut_ptr();
85 let slice = unsafe { core::slice::from_raw_parts_mut(item_ptr.cast::<u8>(), size_of::<T>()) };
86 gene.fill(slice)?;
87 Ok(unsafe { item.assume_init() })
88}
89
90impl<const N: usize, TPrng> EntropyConcreteGenerator<CPRNGEntropy<TPrng>> for [u8; N]
91where
92 TPrng: PRNGenerator + CryptographicallySecure + Seedable<u128>,
93{
94 #[inline(always)]
95 fn generate(generator: &mut CPRNGEntropy<TPrng>) -> Result<Self, <CPRNGEntropy<TPrng> as EntropyGenerator>::Error> {
96 if N == 0 {
97 return Ok([0u8; N]);
98 }
99 generate_random_t(generator)
100 }
101}
102
103macro_rules! concrete {
104 ( $t: ty ) => {
105 impl<TPrng> EntropyConcreteGenerator<CPRNGEntropy<TPrng>> for $t
106 where
107 TPrng: PRNGenerator + CryptographicallySecure + Seedable<u128>
108 {
109 #[inline(always)]
110 fn generate(generator: &mut CPRNGEntropy<TPrng>) -> Result<Self, <CPRNGEntropy<TPrng> as EntropyGenerator>::Error>
111 {
112 generate_random_t(generator)
113 }
114 }
115 };
116 ( $t: ty, $($ts:ty),* $(,)?) => {
117 concrete!($t);
118 concrete!($($ts),*);
119 };
120}
121
122concrete!(i16, u16, i32, u32, i64, u64, i128, u128, usize, isize);