osom_lib_prng/
traits.rs

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