clock_rand/
traits.rs

1//! Core traits for RNG implementations
2
3use crate::error::Result;
4
5/// Core trait for random number generators
6///
7/// This trait provides the basic interface for generating random values.
8/// It's compatible with the `rand` crate's `RngCore` trait for interoperability.
9pub trait Rng {
10    /// Generate the next `u32` random value
11    fn next_u32(&mut self) -> u32;
12
13    /// Generate the next `u64` random value
14    fn next_u64(&mut self) -> u64;
15
16    /// Fill a byte buffer with random data
17    fn fill_bytes(&mut self, dest: &mut [u8]);
18
19    /// Try to fill a byte buffer with random data (may fail)
20    fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<()> {
21        self.fill_bytes(dest);
22        Ok(())
23    }
24}
25
26/// Marker trait for cryptographically secure random number generators
27///
28/// Types implementing this trait are suitable for cryptographic operations
29/// such as key generation, nonce generation, and signature operations.
30pub trait CryptoRng: Rng {
31    // Marker trait - no additional methods required
32    // The security guarantee is provided by the implementation
33}
34
35/// Trait for deterministic random number generators
36///
37/// RNGs implementing this trait produce reproducible sequences when seeded
38/// with the same seed value.
39pub trait DeterministicRng: Rng {
40    /// Check if the RNG is in a deterministic state
41    fn is_deterministic(&self) -> bool;
42}
43
44/// Trait for RNGs that can be seeded
45pub trait SeedableRng: Rng {
46    /// Seed type for this RNG
47    type Seed: AsRef<[u8]> + Clone;
48
49    /// Create a new RNG from a seed
50    fn from_seed(seed: Self::Seed) -> Self;
51
52    /// Reseed the RNG with a new seed
53    fn reseed(&mut self, seed: Self::Seed) -> Result<()>;
54}
55
56/// Compatibility trait with `rand` crate's `RngCore`
57///
58/// This allows clock-rand RNGs to be used with the `rand` crate ecosystem.
59pub trait RngCore: Rng {
60    /// Generate the next `u32` random value
61    fn next_u32(&mut self) -> u32;
62
63    /// Generate the next `u64` random value
64    fn next_u64(&mut self) -> u64;
65
66    /// Fill a byte buffer with random data
67    fn fill_bytes(&mut self, dest: &mut [u8]);
68
69    /// Try to fill a byte buffer with random data (may fail)
70    #[cfg(feature = "std")]
71    fn try_fill_bytes(&mut self, dest: &mut [u8]) -> core::result::Result<(), std::io::Error>;
72}
73
74/// Helper trait for generating random values of specific types
75pub trait RngExt: Rng {
76    /// Generate a random `u8`
77    #[inline]
78    fn gen_u8(&mut self) -> u8 {
79        (self.next_u32() >> 24) as u8
80    }
81
82    /// Generate a random `u16`
83    #[inline]
84    fn gen_u16(&mut self) -> u16 {
85        (self.next_u32() >> 16) as u16
86    }
87
88    /// Generate a random `u32`
89    #[inline]
90    fn gen_u32(&mut self) -> u32 {
91        self.next_u32()
92    }
93
94    /// Generate a random `u64`
95    #[inline]
96    fn gen_u64(&mut self) -> u64 {
97        self.next_u64()
98    }
99
100    /// Generate a random `f32` in [0, 1)
101    fn gen_f32(&mut self) -> f32 {
102        // Generate 24 random bits for mantissa
103        let bits = (self.next_u32() >> 8) | 0x3f80_0000;
104        f32::from_bits(bits) - 1.0
105    }
106
107    /// Generate a random `f64` in [0, 1)
108    fn gen_f64(&mut self) -> f64 {
109        // Generate 53 random bits for mantissa
110        let bits = (self.next_u64() >> 11) | 0x3ff0_0000_0000_0000;
111        f64::from_bits(bits) - 1.0
112    }
113}
114
115impl<T: Rng> RngExt for T {}
116
117// Blanket implementation for RngCore compatibility
118impl<T: Rng> RngCore for T {
119    fn next_u32(&mut self) -> u32 {
120        Rng::next_u32(self)
121    }
122
123    fn next_u64(&mut self) -> u64 {
124        Rng::next_u64(self)
125    }
126
127    fn fill_bytes(&mut self, dest: &mut [u8]) {
128        Rng::fill_bytes(self, dest)
129    }
130
131    #[cfg(feature = "std")]
132    fn try_fill_bytes(&mut self, dest: &mut [u8]) -> core::result::Result<(), std::io::Error> {
133        Rng::try_fill_bytes(self, dest).map_err(std::io::Error::other)
134    }
135}