osom_lib_rand/
traits.rs

1//! Holds traits for random number generators and randomness sources.
2use crate::number::Number;
3
4/// Simple trait for pseudo random number generators. Types implementing
5/// this trait should aim for efficiency above all.
6///
7/// In its essence this is the same as [`RandomnessSource`].
8/// We distinguish those types mostly for type safety. These
9/// have different purposes.
10pub trait PseudoRandomNumberGenerator {
11    type TNumber: Number;
12
13    /// Whether the generator is cryptographically secure.
14    const IS_CRYPTOGRAPHICALLY_SECURE: bool = false;
15
16    /// Creates a new [`PseudoRandomNumberGenerator`] seeded from a [`RandomnessSource`].
17    fn from_randomness_source(source: &mut impl RandomnessSource<TNumber = Self::TNumber>) -> Self;
18
19    /// Returns the next random number.
20    fn next_number(&mut self) -> Self::TNumber;
21
22    /// Fills the given mut slice with random bytes.
23    fn fill_bytes(&mut self, bytes: &mut [u8]) {
24        fill_bytes_from_gens(bytes, || self.next_number());
25    }
26}
27
28/// Simple trait for randomness source.
29///
30/// This looks (and in fact is)
31/// the same as [`PseudoRandomNumberGenerator`], however it is distinguished
32/// by the way it works. It is allowed for implementors of this trait
33/// to be inefficient, but have potentially better randomness (e.g. by
34/// reading from appropriate hardware source).
35///
36/// It is also a good idea to seed [`PseudoRandomNumberGenerator`] objects
37/// with whatever [`RandomnessSource`] returns.
38///
39/// In its essence this is the same as [`PseudoRandomNumberGenerator`].
40/// We distinguish those types mostly for type safety. These
41/// have different purposes.
42pub trait RandomnessSource: Default {
43    type TNumber: Number;
44
45    /// Returns the next random number.
46    fn next_number(&mut self) -> Self::TNumber;
47
48    /// Fills the given mut slice with random bytes.
49    fn fill_bytes(&mut self, bytes: &mut [u8]) {
50        fill_bytes_from_gens(bytes, || self.next_number());
51    }
52}
53
54fn fill_bytes_from_gens<T: Number, F: FnMut() -> T>(bytes: &mut [u8], mut generator: F) {
55    if bytes.is_empty() {
56        return;
57    }
58
59    let size = T::SIZE;
60    let bytes_len = bytes.len();
61    let number_of_chunks = bytes_len / size;
62    let missing_elements = bytes_len % size;
63    let mut ptr = bytes.as_mut_ptr().cast::<T>();
64    for _ in 0..number_of_chunks {
65        unsafe {
66            ptr.write(generator());
67            ptr = ptr.add(1);
68        }
69    }
70
71    if missing_elements > 0 {
72        let mut value_bytes = T::ByteRepr::default();
73        let value_bytes_slice = value_bytes.as_mut();
74        let value_ptr = value_bytes_slice.as_mut_ptr().cast::<T>();
75        unsafe {
76            value_ptr.write(generator());
77        }
78        let index = number_of_chunks * size;
79        let remaining_bytes = &mut bytes[index..(index + missing_elements)];
80        remaining_bytes.copy_from_slice(&value_bytes_slice[..missing_elements]);
81    }
82}