diff options
| author | Bob McWhirter <[email protected]> | 2021-09-01 09:39:33 -0400 |
|---|---|---|
| committer | Bob McWhirter <[email protected]> | 2021-09-01 09:39:33 -0400 |
| commit | 37ceae908b39fcf1ef3b38680cef240ed6b1e867 (patch) | |
| tree | ec7fe229b9ebc2892dc7c57732ab01f8f611ae4b /embassy-traits/src | |
| parent | fd7a76c59e8a190781aea476d199bda826dd5031 (diff) | |
Rename Random impl to Rng.
Create Random struct providing next_x(range) for all T:Rng.
Diffstat (limited to 'embassy-traits/src')
| -rw-r--r-- | embassy-traits/src/rng.rs | 61 |
1 files changed, 55 insertions, 6 deletions
diff --git a/embassy-traits/src/rng.rs b/embassy-traits/src/rng.rs index 181faa515..3cc4b2a0b 100644 --- a/embassy-traits/src/rng.rs +++ b/embassy-traits/src/rng.rs | |||
| @@ -17,11 +17,60 @@ pub trait Rng { | |||
| 17 | fn fill_bytes<'a>(&'a mut self, dest: &'a mut [u8]) -> Self::RngFuture<'a>; | 17 | fn fill_bytes<'a>(&'a mut self, dest: &'a mut [u8]) -> Self::RngFuture<'a>; |
| 18 | } | 18 | } |
| 19 | 19 | ||
| 20 | pub trait Random: Rng { | 20 | pub struct Random<T: Rng> { |
| 21 | #[rustfmt::skip] | 21 | rng: T, |
| 22 | type NextFuture<'a>: Future<Output = Result<u32, <Self as Rng>::Error>> + 'a | 22 | } |
| 23 | where | 23 | |
| 24 | Self: 'a; | 24 | impl<T: Rng> Random<T> { |
| 25 | pub fn new(rng: T) -> Self { | ||
| 26 | Self { rng } | ||
| 27 | } | ||
| 28 | |||
| 29 | pub async fn next_u8<'a>(&'a mut self, range: u8) -> Result<u8, T::Error> { | ||
| 30 | // Lemire's method | ||
| 31 | let t = (-(range as i8) % (range as i8)) as u8; | ||
| 32 | loop { | ||
| 33 | let mut buf = [0; 1]; | ||
| 34 | self.rng.fill_bytes(&mut buf).await?; | ||
| 35 | let x = u8::from_le_bytes(buf); | ||
| 36 | let m = x as u16 * range as u16; | ||
| 37 | let l = m as u8; | ||
| 38 | if l < t { | ||
| 39 | continue; | ||
| 40 | } | ||
| 41 | return Ok((m >> 8) as u8); | ||
| 42 | } | ||
| 43 | } | ||
| 44 | |||
| 45 | pub async fn next_u16<'a>(&'a mut self, range: u16) -> Result<u16, T::Error> { | ||
| 46 | // Lemire's method | ||
| 47 | let t = (-(range as i16) % (range as i16)) as u16; | ||
| 48 | loop { | ||
| 49 | let mut buf = [0; 2]; | ||
| 50 | self.rng.fill_bytes(&mut buf).await?; | ||
| 51 | let x = u16::from_le_bytes(buf); | ||
| 52 | let m = x as u32 * range as u32; | ||
| 53 | let l = m as u16; | ||
| 54 | if l < t { | ||
| 55 | continue; | ||
| 56 | } | ||
| 57 | return Ok((m >> 16) as u16); | ||
| 58 | } | ||
| 59 | } | ||
| 25 | 60 | ||
| 26 | fn next<'a>(&'a mut self, range: u32) -> Self::NextFuture<'a>; | 61 | pub async fn next_u32<'a>(&'a mut self, range: u32) -> Result<u32, T::Error> { |
| 62 | // Lemire's method | ||
| 63 | let t = (-(range as i32) % (range as i32)) as u32; | ||
| 64 | loop { | ||
| 65 | let mut buf = [0; 4]; | ||
| 66 | self.rng.fill_bytes(&mut buf).await?; | ||
| 67 | let x = u32::from_le_bytes(buf); | ||
| 68 | let m = x as u64 * range as u64; | ||
| 69 | let l = m as u32; | ||
| 70 | if l < t { | ||
| 71 | continue; | ||
| 72 | } | ||
| 73 | return Ok((m >> 32) as u32); | ||
| 74 | } | ||
| 75 | } | ||
| 27 | } | 76 | } |
