File
Blob: firmware/vendor/str0m/src/_internal_test_exports/rng.rs
| 1 | pub struct Rng<'a>(&'a [u8], usize); |
| 2 | |
| 3 | macro_rules! rng_primary { |
| 4 | ($unit:tt, $above:tt) => { |
| 5 | pub fn $unit(&mut self, max: $unit) -> Option<$unit> { |
| 6 | const X: usize = std::mem::size_of::<$unit>(); |
| 7 | let bytes = self.array::<X>()?; |
| 8 | let u = $unit::from_be_bytes(bytes); |
| 9 | Some(if max == $unit::MAX { |
| 10 | u |
| 11 | } else { |
| 12 | ((u as $above * max as $above) / $unit::MAX as $above) as $unit |
| 13 | }) |
| 14 | } |
| 15 | }; |
| 16 | } |
| 17 | |
| 18 | impl<'a> Rng<'a> { |
| 19 | pub fn new(data: &'a [u8]) -> Self { |
| 20 | Self(data, 0) |
| 21 | } |
| 22 | |
| 23 | pub fn slice(&mut self, n: usize) -> Option<&[u8]> { |
| 24 | let start = self.1; |
| 25 | let end = self.1 + n; |
| 26 | |
| 27 | if end > self.0.len() { |
| 28 | // First that hits limit ends anymore data. |
| 29 | self.1 = self.0.len(); |
| 30 | return None; |
| 31 | } |
| 32 | |
| 33 | self.1 = end; |
| 34 | |
| 35 | Some(&self.0[start..end]) |
| 36 | } |
| 37 | |
| 38 | pub fn array<const N: usize>(&mut self) -> Option<[u8; N]> { |
| 39 | let slice = self.slice(N)?; |
| 40 | |
| 41 | let mut arr = [0_u8; N]; |
| 42 | arr.copy_from_slice(slice); |
| 43 | |
| 44 | Some(arr) |
| 45 | } |
| 46 | |
| 47 | pub fn bool(&mut self) -> Option<bool> { |
| 48 | Some(self.array::<1>()?[0] < 128) |
| 49 | } |
| 50 | |
| 51 | rng_primary!(u8, u16); |
| 52 | rng_primary!(u32, u64); |
| 53 | rng_primary!(u64, u128); |
| 54 | rng_primary!(usize, u128); |
| 55 | } |