osom_lib_prng/
stream_prng.rs1use core::ops::RangeBounds;
4
5use osom_lib_reprc::{macros::reprc, traits::ReprC};
6use osom_lib_try_clone::TryClone;
7
8use crate::{
9 prngs::helpers::{
10 generate_f32_in_range, generate_f64_in_range, generate_i32_in_range, generate_i64_in_range,
11 generate_u32_in_range, generate_u64_in_range,
12 },
13 traits::{PRNConcreteBoundedGenerator, PRNConcreteGenerator, PRNGenerator, PRStream, Seedable},
14};
15
16#[derive(Debug, PartialEq, Eq, Clone)]
19#[reprc]
20pub struct StreamPRNG<T: PRStream> {
21 stream: T,
22}
23
24impl<T: PRStream + TryClone> TryClone for StreamPRNG<T> {
25 type Error = <T as TryClone>::Error;
26
27 fn try_clone(&self) -> Result<Self, Self::Error> {
28 let stream = self.stream.try_clone()?;
29 Ok(Self { stream })
30 }
31}
32
33impl<T: PRStream> StreamPRNG<T> {
34 #[inline(always)]
36 pub fn new(stream: T) -> Self {
37 Self { stream }
38 }
39}
40
41#[allow(clippy::cast_possible_truncation)]
42impl<T: PRStream> PRNGenerator for StreamPRNG<T> {
43 unsafe fn fill_raw(&mut self, dst_ptr: *mut u8, dst_len: usize) {
44 unsafe { self.stream.fill_raw(dst_ptr, dst_len) };
45 }
46}
47
48impl<const N: usize, T: PRStream> PRNConcreteGenerator<StreamPRNG<T>> for [u8; N] {
49 #[inline(always)]
50 fn generate(generator: &mut StreamPRNG<T>) -> Self {
51 const {
52 assert!(size_of::<Self>() == N);
53 }
54 if N == 0 {
55 return [0u8; N];
56 }
57 let mut item = core::mem::MaybeUninit::<Self>::uninit();
58 unsafe {
59 generator.fill_raw(item.as_mut_ptr().cast(), N);
60 item.assume_init()
61 }
62 }
63}
64
65impl<T: PRStream> PRNConcreteGenerator<StreamPRNG<T>> for bool {
66 fn generate(generator: &mut StreamPRNG<T>) -> Self {
67 (generator.generate::<u8>() & 1) == 1
68 }
69}
70
71impl<T: PRStream> PRNConcreteGenerator<StreamPRNG<T>> for u8 {
72 fn generate(generator: &mut StreamPRNG<T>) -> Self {
73 u8::from_le_bytes(generator.generate::<[u8; 1]>())
74 }
75}
76
77impl<T: PRStream> PRNConcreteGenerator<StreamPRNG<T>> for i8 {
78 fn generate(generator: &mut StreamPRNG<T>) -> Self {
79 i8::from_le_bytes(generator.generate::<[u8; 1]>())
80 }
81}
82
83impl<T: PRStream> PRNConcreteGenerator<StreamPRNG<T>> for u16 {
84 fn generate(generator: &mut StreamPRNG<T>) -> Self {
85 u16::from_le_bytes(generator.generate::<[u8; 2]>())
86 }
87}
88
89impl<T: PRStream> PRNConcreteGenerator<StreamPRNG<T>> for i16 {
90 fn generate(generator: &mut StreamPRNG<T>) -> Self {
91 i16::from_le_bytes(generator.generate::<[u8; 2]>())
92 }
93}
94
95impl<T: PRStream> PRNConcreteGenerator<StreamPRNG<T>> for u32 {
96 fn generate(generator: &mut StreamPRNG<T>) -> Self {
97 u32::from_le_bytes(generator.generate::<[u8; 4]>())
98 }
99}
100
101impl<T: PRStream> PRNConcreteGenerator<StreamPRNG<T>> for i32 {
102 fn generate(generator: &mut StreamPRNG<T>) -> Self {
103 i32::from_le_bytes(generator.generate::<[u8; 4]>())
104 }
105}
106
107impl<T: PRStream> PRNConcreteGenerator<StreamPRNG<T>> for u64 {
108 fn generate(generator: &mut StreamPRNG<T>) -> Self {
109 u64::from_le_bytes(generator.generate::<[u8; 8]>())
110 }
111}
112
113impl<T: PRStream> PRNConcreteGenerator<StreamPRNG<T>> for i64 {
114 fn generate(generator: &mut StreamPRNG<T>) -> Self {
115 i64::from_le_bytes(generator.generate::<[u8; 8]>())
116 }
117}
118
119impl<T: PRStream> PRNConcreteGenerator<StreamPRNG<T>> for u128 {
120 fn generate(generator: &mut StreamPRNG<T>) -> Self {
121 u128::from_le_bytes(generator.generate::<[u8; 16]>())
122 }
123}
124
125impl<T: PRStream> PRNConcreteGenerator<StreamPRNG<T>> for i128 {
126 fn generate(generator: &mut StreamPRNG<T>) -> Self {
127 i128::from_le_bytes(generator.generate::<[u8; 16]>())
128 }
129}
130
131impl<T: PRStream> PRNConcreteBoundedGenerator<StreamPRNG<T>> for u32 {
132 fn generate<TBounds: RangeBounds<Self>>(generator: &mut StreamPRNG<T>, range: TBounds) -> Self {
133 generate_u32_in_range(generator, range)
134 }
135}
136
137impl<T: PRStream> PRNConcreteBoundedGenerator<StreamPRNG<T>> for u64 {
138 fn generate<TBounds: RangeBounds<Self>>(generator: &mut StreamPRNG<T>, range: TBounds) -> Self {
139 generate_u64_in_range(generator, range)
140 }
141}
142
143impl<T: PRStream> PRNConcreteBoundedGenerator<StreamPRNG<T>> for i32 {
144 fn generate<TBounds: RangeBounds<Self>>(generator: &mut StreamPRNG<T>, range: TBounds) -> Self {
145 generate_i32_in_range(generator, range)
146 }
147}
148
149impl<T: PRStream> PRNConcreteBoundedGenerator<StreamPRNG<T>> for i64 {
150 fn generate<TBounds: RangeBounds<Self>>(generator: &mut StreamPRNG<T>, range: TBounds) -> Self {
151 generate_i64_in_range(generator, range)
152 }
153}
154
155impl<T: PRStream> PRNConcreteBoundedGenerator<StreamPRNG<T>> for f32 {
156 fn generate<TBounds: RangeBounds<Self>>(generator: &mut StreamPRNG<T>, range: TBounds) -> Self {
157 generate_f32_in_range(generator, range)
158 }
159}
160
161impl<T: PRStream> PRNConcreteBoundedGenerator<StreamPRNG<T>> for f64 {
162 fn generate<TBounds: RangeBounds<Self>>(generator: &mut StreamPRNG<T>, range: TBounds) -> Self {
163 generate_f64_in_range(generator, range)
164 }
165}
166
167impl<TSeed: ReprC + Copy, T: PRStream + Seedable<TSeed>> Seedable<TSeed> for StreamPRNG<T> {
168 fn with_seed(seed: TSeed) -> Self {
169 Self::new(T::with_seed(seed))
170 }
171}