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}