Skip to main content

osom_lib_prng/
traits.rs

1//! Holds definitions of various PRNG traits.
2
3use core::ops::RangeBounds;
4
5use osom_lib_reprc::{macros::reprc, traits::ReprC};
6
7use crate::errors::{DeserializeError, SerializeError};
8
9/// Generates pseudo random instance of current type.
10///
11/// Similar to [`PRNGenerator`] but works with a single type
12/// only.
13pub trait PRNConcreteGenerator<TGenerator: PRNGenerator>: Sized + ReprC {
14    /// Generates a new pseudo random instance of itself.
15    #[must_use]
16    fn generate(generator: &mut TGenerator) -> Self;
17}
18
19/// Represents a trait for generating pseudo-random data
20pub trait PRNConcreteBoundedGenerator<TGenerator: PRNGenerator>: Sized + ReprC {
21    /// Generates a new pseudo random instance of itself in given range.
22    #[must_use]
23    fn generate<TBounds: RangeBounds<Self>>(generator: &mut TGenerator, range: TBounds) -> Self;
24}
25
26/// Generates pseudo random numbers.
27pub trait PRNGenerator: Sized + ReprC + Clone {
28    /// Fills the given raw buffer with randomness.
29    ///
30    /// # Safety
31    ///
32    /// This function assumes that both `dst_ptr` and `dst_len`
33    /// correspond to valid chunk of memory. Otherwise the behaviour
34    /// is undefined.
35    unsafe fn fill_raw(&mut self, dst_ptr: *mut u8, dst_len: usize);
36
37    /// Fills the given buffer with randomness.
38    #[inline(always)]
39    fn fill(&mut self, dst: &mut [u8]) {
40        unsafe {
41            self.fill_raw(dst.as_mut_ptr(), dst.len());
42        }
43    }
44
45    /// Generates pseudo random instance of given type if supported.
46    /// This function should support at least i32, u32, i64 and u64
47    /// types.
48    #[inline(always)]
49    #[must_use]
50    fn generate<T>(&mut self) -> T
51    where
52        T: PRNConcreteGenerator<Self>,
53    {
54        T::generate(self)
55    }
56
57    /// Generates a pseudo random number in given range, if supported.
58    #[must_use]
59    fn generate_in_range<T, TBounds: RangeBounds<T>>(&mut self, range: TBounds) -> T
60    where
61        T: PRNConcreteBoundedGenerator<Self>,
62    {
63        T::generate(self, range)
64    }
65}
66
67/// A marker trait for cryptographically secure PRNGs.
68///
69/// # Safety
70///
71/// It is up to the implementor to ensure this invariant.
72pub unsafe trait CryptographicallySecure: PRNGenerator {}
73
74/// A trait for splittable PRNGs. This means that
75/// given PRNG can split into two generators. This
76/// is different from creating a new PRNG (with a random
77/// seed), because splitting is a deterministic process.
78///
79/// Also this is different from cloning, since clones
80/// generally generate the same sequences of numbers
81/// (since clones have the exact same state).
82/// We want the result of splitting look like
83/// it is independent (even though in reality it is not).
84///
85/// It is especially useful for deterministic, multi-threaded
86/// simulations where each thread needs a PRNG.
87pub trait Splittable: PRNGenerator {
88    /// Create a new PRNG from the current one. In a
89    /// deterministic, yet non-obvious (pseudo random) way.
90    #[must_use]
91    fn split(&mut self) -> Self;
92}
93
94/// Represents deserialization result.
95#[derive(Debug)]
96#[reprc]
97pub struct DeserializationResult<T: ReprC> {
98    /// The real amount of bytes read from the buffer.
99    pub read_bytes: usize,
100
101    /// The actual deserialized value.
102    pub value: T,
103}
104
105/// Represents platform independent (de)serialization trait
106/// of given pseudo random number generator.
107pub trait PRNGSerialize: PRNGenerator {
108    /// Concrete serialization error.
109    type SerializeError: Into<SerializeError> + ReprC;
110
111    /// Concrete deserialization error.
112    type DeserializeError: Into<DeserializeError> + ReprC;
113
114    /// The maximum size of serialized value, in bytes. This should be used by callers
115    /// to determine how big the buffer needs to be for [`PRNGSerialize::serialize`]
116    /// to succeed.
117    ///
118    /// Typically this should be in the order of few kb max
119    /// (e.g. for the 128-bit linear congruential generator that would be the current
120    /// state, i.e. only 16 bytes if we don't count the multiplier and the increment).
121    /// But of course there is no such guarantee in general.
122    const MAX_SERIALIZED_SIZE: usize;
123
124    /// Serializes self into the buffer. Returns the actual amount of bytes that
125    /// were written on success.
126    ///
127    /// # Errors
128    ///
129    /// For errors see concrete [`PRNGSerialize::SerializeError`] type.
130    fn serialize(&self, buffer: &mut [u8]) -> Result<usize, Self::SerializeError>;
131
132    /// Deserializes self from the passed buffer. Returns deserialization info
133    /// on success, i.e. the actual value and the amount of bytes read from the
134    /// buffer.
135    ///
136    /// # Errors
137    ///
138    /// For errors see concrete [`PRNGSerialize::DeserializeError`] type.
139    fn deserialize(buffer: &[u8]) -> Result<DeserializationResult<Self>, Self::DeserializeError>;
140}
141
142/// Represents a pseudo random stream. These are easily convertible
143/// into PRNGs through the [`StreamPRNG`][`crate::stream_prng::StreamPRNG`] wrapper.
144pub trait PRStream: Sized + Clone + ReprC {
145    /// Fills the given raw buffer with randomness.
146    ///
147    /// # Safety
148    ///
149    /// This function assumes that both `dst_ptr` and `dst_len`
150    /// correspond to valid chunk of memory. Otherwise the behaviour
151    /// is undefined.
152    unsafe fn fill_raw(&mut self, dst_ptr: *mut u8, dst_len: usize);
153
154    /// Fills the given block with randomness.
155    #[inline(always)]
156    fn fill_block(&mut self, block: &mut [u8]) {
157        unsafe {
158            self.fill_raw(block.as_mut_ptr(), block.len());
159        }
160    }
161
162    /// Generates the next block of given length.
163    #[inline(always)]
164    #[must_use]
165    fn next_block<const N: usize>(&mut self) -> [u8; N] {
166        let mut block = [0u8; N];
167        self.fill_block(&mut block);
168        block
169    }
170}
171
172/// A trait for seeding PRNGs.
173pub trait Seedable<TSeed: ReprC + Copy> {
174    /// Creates a new instance from a given seed.
175    #[must_use]
176    fn with_seed(seed: TSeed) -> Self;
177}