bolero_generator/driver/
rng.rs

1use super::*;
2
3#[cfg(feature = "alloc")]
4pub(crate) use buffer_alloc::Buffer;
5#[cfg(not(feature = "alloc"))]
6pub(crate) use buffer_no_alloc::Buffer;
7
8#[derive(Debug)]
9pub struct Rng<R: TryRngCore> {
10    rng: R,
11    depth: usize,
12    max_depth: usize,
13    consumed_len: usize,
14    max_len: usize,
15    #[allow(dead_code)] // this isn't used in no_std mode
16    buffer: Buffer,
17}
18
19impl<R: TryRngCore> Rng<R> {
20    pub fn new(rng: R, options: &Options) -> Self {
21        Self {
22            rng,
23            depth: 0,
24            max_depth: options.max_depth_or_default(),
25            consumed_len: 0,
26            max_len: options.max_len_or_default(),
27            buffer: Default::default(),
28        }
29    }
30
31    #[inline]
32    fn fill_bytes(&mut self, bytes: &mut [u8]) -> Option<()> {
33        let len = bytes.len().min(self.remaining_len());
34        let (to_rng, to_fill) = bytes.split_at_mut(len);
35        fill_bytes(&mut self.rng, to_rng)?;
36        to_fill.fill(0);
37        Some(())
38    }
39
40    #[inline]
41    fn has_remaining(&self) -> bool {
42        self.consumed_len < self.max_len
43    }
44
45    #[inline]
46    fn remaining_len(&self) -> usize {
47        self.max_len.saturating_sub(self.consumed_len)
48    }
49
50    #[inline]
51    fn fill_buffer(&mut self, len: usize) -> Option<&[u8]> {
52        self.buffer.fill(len, &mut self.rng)?;
53        Some(self.buffer.slice_mut(len))
54    }
55}
56
57impl<R: TryRngCore> AsRef<R> for Rng<R> {
58    #[inline]
59    fn as_ref(&self) -> &R {
60        &self.rng
61    }
62}
63
64#[inline]
65fn fill_bytes<R: TryRngCore>(rng: &mut R, bytes: &mut [u8]) -> Option<()> {
66    if TryRngCore::try_fill_bytes(rng, bytes).is_err() {
67        // if the rng fails to fill the remaining bytes, then we just start returning 0s
68        for byte in bytes.iter_mut() {
69            *byte = 0;
70        }
71    }
72
73    Some(())
74}
75
76macro_rules! impl_sample {
77    ($sample:ident, $ty:ty, $inner:ident) => {
78        #[inline(always)]
79        fn $sample(&mut self) -> Option<$ty> {
80            if self.has_remaining() {
81                self.consumed_len += core::mem::size_of::<$ty>();
82                Some(self.rng.$inner().unwrap_or_default() as $ty)
83            } else {
84                Some(0)
85            }
86        }
87    };
88}
89
90impl<R: TryRngCore> FillBytes for Rng<R> {
91    // prefer sampling the larger values since it's faster to pull from the RNG
92    const SHOULD_SHRINK: bool = false;
93
94    #[inline]
95    fn peek_bytes(&mut self, _offset: usize, bytes: &mut [u8]) -> Option<()> {
96        self.fill_bytes(bytes)
97    }
98
99    #[inline(always)]
100    fn consume_bytes(&mut self, consumed: usize) {
101        self.consumed_len += consumed;
102    }
103
104    #[inline(always)]
105    fn sample_bool(&mut self) -> Option<bool> {
106        if self.has_remaining() {
107            self.consumed_len += 1;
108            let value = self.rng.try_next_u32().unwrap_or_default();
109            Some(value < (u32::MAX / 2))
110        } else {
111            Some(false)
112        }
113    }
114
115    impl_sample!(sample_u8, u8, try_next_u32);
116    impl_sample!(sample_i8, i8, try_next_u32);
117    impl_sample!(sample_u16, u16, try_next_u32);
118    impl_sample!(sample_i16, i16, try_next_u32);
119    impl_sample!(sample_u32, u32, try_next_u32);
120    impl_sample!(sample_i32, i32, try_next_u32);
121    impl_sample!(sample_u64, u64, try_next_u64);
122    impl_sample!(sample_i64, i64, try_next_u64);
123    impl_sample!(sample_usize, usize, try_next_u64);
124    impl_sample!(sample_isize, isize, try_next_u64);
125}
126
127impl<R: TryRngCore> Driver for Rng<R> {
128    gen_from_bytes!();
129
130    #[inline]
131    fn depth(&self) -> usize {
132        self.depth
133    }
134
135    #[inline]
136    fn set_depth(&mut self, depth: usize) {
137        self.depth = depth;
138    }
139
140    #[inline]
141    fn max_depth(&self) -> usize {
142        self.max_depth
143    }
144
145    #[inline]
146    fn gen_from_bytes<Hint, Gen, T>(&mut self, hint: Hint, mut produce: Gen) -> Option<T>
147    where
148        Hint: FnOnce() -> (usize, Option<usize>),
149        Gen: FnMut(&[u8]) -> Option<(usize, T)>,
150    {
151        let (min, max) = hint();
152
153        let max = max
154            .unwrap_or(usize::MAX)
155            // make sure max is at least min
156            .clamp(min, self.remaining_len())
157            .min(Buffer::MAX_CAPACITY);
158
159        let len = self.gen_usize(Bound::Included(&min), Bound::Included(&max))?;
160        let bytes = self.fill_buffer(len)?;
161        let (consumed, value) = produce(bytes)?;
162        self.consume_bytes(consumed);
163        self.buffer.clear();
164        Some(value)
165    }
166}
167
168#[cfg(feature = "alloc")]
169mod buffer_alloc {
170    use super::*;
171
172    #[derive(Clone, Debug, Default)]
173    pub struct Buffer {
174        bytes: alloc::vec::Vec<u8>,
175    }
176
177    impl Buffer {
178        pub const MAX_CAPACITY: usize = isize::MAX as _;
179
180        #[inline]
181        pub fn fill<R: TryRngCore>(&mut self, len: usize, rng: &mut R) -> Option<()> {
182            let data = &mut self.bytes;
183
184            let initial_len = data.len();
185
186            // we don't need any more bytes, just return what we have
187            if initial_len >= len {
188                return Some(());
189            }
190
191            // extend the random bytes
192            data.try_reserve(len).ok()?;
193            data.resize(len, 0);
194            fill_bytes(rng, &mut data[initial_len..])?;
195
196            Some(())
197        }
198
199        #[inline]
200        pub fn slice_mut(&mut self, len: usize) -> &mut [u8] {
201            &mut self.bytes[..len]
202        }
203
204        #[inline]
205        pub fn clear(&mut self) {
206            self.bytes.clear();
207        }
208    }
209}
210
211#[cfg_attr(feature = "alloc", allow(dead_code))]
212mod buffer_no_alloc {
213    use super::*;
214
215    #[derive(Clone, Debug)]
216    pub struct Buffer {
217        bytes: [u8; Self::MAX_CAPACITY],
218        len: usize,
219    }
220
221    impl Default for Buffer {
222        fn default() -> Self {
223            Self {
224                bytes: [0; Self::MAX_CAPACITY],
225                len: Default::default(),
226            }
227        }
228    }
229
230    impl Buffer {
231        pub const MAX_CAPACITY: usize = 256;
232
233        #[inline]
234        pub fn fill<R: TryRngCore>(&mut self, len: usize, rng: &mut R) -> Option<()> {
235            if cfg!(test) {
236                assert!(len <= Self::MAX_CAPACITY);
237            }
238
239            let initial_len = self.len;
240
241            // we don't need any more bytes, just return what we have
242            if initial_len >= len {
243                return Some(());
244            }
245
246            // extend the random bytes
247            fill_bytes(rng, &mut self.bytes[initial_len..])?;
248            self.len = len;
249
250            Some(())
251        }
252
253        #[inline]
254        pub fn slice_mut(&mut self, len: usize) -> &mut [u8] {
255            &mut self.bytes[..len]
256        }
257
258        #[inline]
259        pub fn clear(&mut self) {
260            self.len = 0;
261        }
262    }
263}