1pub mod derive_rng;
2pub mod prf;
3pub mod prg;
4pub mod test_rng;
5
6use num_traits::Zero;
7pub use prg::{new_prg, prg, Prng};
8use rand::{distributions::Standard, prelude::Distribution};
9pub use rand_chacha::rand_core::CryptoRngCore;
10pub use test_rng::{test_rng, TestRng};
11use typenum::Unsigned;
12
13use crate::{
14 constants::{CollisionResistanceBytes, Lambda},
15 errors::PrimitiveError,
16 random::derive_rng::DeriveRng,
17 utils::IntoExactSizeIterator,
18};
19
20pub type Seed = [u8; CollisionResistanceBytes::USIZE];
22
23impl DeriveRng for Seed {}
24
25pub trait Random: Sized {
28 fn random(rng: impl CryptoRngCore) -> Self;
30
31 fn random_n<Container: FromIterator<Self>>(
33 mut rng: impl CryptoRngCore,
34 size: usize,
35 ) -> Container {
36 (0..size).map(|_| Self::random(&mut rng)).collect()
37 }
38}
39
40impl<T> Random for T
42where
43 Standard: Distribution<T>,
44{
45 #[inline]
46 fn random(mut source: impl CryptoRngCore) -> Self {
47 Standard.sample(&mut source)
48 }
49}
50
51pub trait RandomWith<D: Clone>: Sized {
53 fn random_with(rng: impl CryptoRngCore, data: D) -> Self;
55
56 fn random_n_with<Container: FromIterator<Self>>(
58 mut rng: impl CryptoRngCore,
59 size: usize,
60 data: D,
61 ) -> Container {
62 (0..size)
63 .map(|_| Self::random_with(&mut rng, data.clone()))
64 .collect()
65 }
66
67 fn random_n_with_each<Container: FromIterator<Self>>(
69 mut rng: impl CryptoRngCore,
70 all_data: impl IntoExactSizeIterator<Item = D>,
71 ) -> Container {
72 all_data
73 .into_iter()
74 .map(|data| Self::random_with(&mut rng, data))
75 .collect()
76 }
77}
78
79pub trait RandomNonZero: Sized + Zero + Random {
81 #[inline]
96 fn random_non_zero(mut rng: impl CryptoRngCore) -> Result<Self, PrimitiveError> {
97 let n_tries = (Lambda::USIZE).div_ceil(std::mem::size_of::<Self>());
98 for _ in 0..n_tries {
99 let value = Self::random(&mut rng);
100 if !value.is_zero() {
101 return Ok(value);
102 }
103 }
104 Err(PrimitiveError::ZeroValueSampled(
105 std::any::type_name::<Self>().into(),
106 ))
107 }
108
109 fn random_n_non_zero<Container: FromIterator<Self>>(
111 mut rng: impl CryptoRngCore,
112 size: usize,
113 ) -> Result<Container, PrimitiveError> {
114 (0..size).map(|_| Self::random_non_zero(&mut rng)).collect()
115 }
116}