crypto_common/
generate.rs1use hybrid_array::{Array, ArraySize};
2use rand_core::{CryptoRng, TryCryptoRng};
3
4#[cfg(feature = "getrandom")]
5use crate::RngError;
6
7pub trait Generate: Sized {
9 fn try_from_rng<R: TryCryptoRng + ?Sized>(rng: &mut R) -> Result<Self, R::Error>;
11
12 fn from_rng<R: CryptoRng + ?Sized>(rng: &mut R) -> Self {
14 let Ok(ret) = Self::try_from_rng(rng);
15 ret
16 }
17
18 #[cfg(feature = "getrandom")]
24 fn try_generate() -> Result<Self, RngError> {
25 Self::try_from_rng(&mut sys_rng::SysRng)
26 }
27
28 #[cfg(feature = "getrandom")]
37 fn generate() -> Self {
38 Self::try_generate().expect("RNG failure")
39 }
40}
41
42impl Generate for u32 {
43 #[inline]
44 fn try_from_rng<R: TryCryptoRng + ?Sized>(rng: &mut R) -> Result<Self, R::Error> {
45 rng.try_next_u32()
46 }
47}
48
49impl Generate for u64 {
50 #[inline]
51 fn try_from_rng<R: TryCryptoRng + ?Sized>(rng: &mut R) -> Result<Self, R::Error> {
52 rng.try_next_u64()
53 }
54}
55
56impl<const N: usize> Generate for [u8; N] {
57 #[inline]
58 fn try_from_rng<R: TryCryptoRng + ?Sized>(rng: &mut R) -> Result<Self, R::Error> {
59 let mut ret = [0u8; N];
60 rng.try_fill_bytes(&mut ret)?;
61 Ok(ret)
62 }
63}
64
65impl<U: ArraySize> Generate for Array<u8, U> {
66 #[inline]
67 fn try_from_rng<R: TryCryptoRng + ?Sized>(rng: &mut R) -> Result<Self, R::Error> {
68 let mut ret = Self::default();
69 rng.try_fill_bytes(&mut ret)?;
70 Ok(ret)
71 }
72}
73
74impl<U: ArraySize> Generate for Array<u32, U> {
75 #[inline]
76 fn try_from_rng<R: TryCryptoRng + ?Sized>(rng: &mut R) -> Result<Self, R::Error> {
77 Self::try_from_fn(|_| rng.try_next_u32())
78 }
79}
80
81impl<U: ArraySize> Generate for Array<u64, U> {
82 #[inline]
83 fn try_from_rng<R: TryCryptoRng + ?Sized>(rng: &mut R) -> Result<Self, R::Error> {
84 Self::try_from_fn(|_| rng.try_next_u64())
85 }
86}
87
88#[cfg(feature = "getrandom")]
89pub(crate) mod sys_rng {
90 use getrandom::Error;
91 use rand_core::{TryCryptoRng, TryRngCore};
92
93 #[derive(Clone, Copy, Debug, Default)]
96 pub struct SysRng;
97
98 impl TryRngCore for SysRng {
99 type Error = Error;
100
101 #[inline]
102 fn try_next_u32(&mut self) -> Result<u32, Error> {
103 getrandom::u32()
104 }
105
106 #[inline]
107 fn try_next_u64(&mut self) -> Result<u64, Error> {
108 getrandom::u64()
109 }
110
111 #[inline]
112 fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
113 getrandom::fill(dest)
114 }
115 }
116
117 impl TryCryptoRng for SysRng {}
118}