Skip to content

Commit d3ff76d

Browse files
bors[bot]olback
andauthored
Merge #284
284: Impl rand_core::RngCore & support all integers in Rng r=richardeoin a=olback Co-authored-by: Edwin Svensson <git@olback.net>
2 parents 01e7381 + c6a0d31 commit d3ff76d

File tree

5 files changed

+118
-8
lines changed

5 files changed

+118
-8
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ jobs:
2323
- stm32h7b0
2424
- stm32h735
2525
env: # Peripheral Feature flags
26-
FLAGS: rt,xspi,sdmmc,fmc,usb_hs,rtc,ethernet,ltdc,crc
26+
FLAGS: rt,xspi,sdmmc,sdmmc-fatfs,fmc,usb_hs,rtc,ethernet,ltdc,crc,rand
2727

2828
steps:
2929
- uses: actions/checkout@v2

.github/workflows/nightly.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ jobs:
1919
- log-semihost
2020
- log-rtt
2121
env: # Peripheral Feature flags
22-
FLAGS: rt,xspi,sdmmc,fmc,usb_hs,rtc,ethernet,ltdc,crc
22+
FLAGS: rt,xspi,sdmmc,sdmmc-fatfs,fmc,usb_hs,rtc,ethernet,ltdc,crc,rand
2323

2424
steps:
2525
- uses: actions/checkout@v2

Cargo.toml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,11 @@ version = "0.4"
5151
default-features = false
5252
optional = true
5353

54+
[dependencies.rand_core]
55+
version = "0.6"
56+
default-features = false
57+
optional = true
58+
5459
[dev-dependencies]
5560
cortex-m-rt = ">=0.6.15,<0.8"
5661
cortex-m-rtic = { version = "0.5.8", default-features = false, features = ["cortex-m-7"] }
@@ -93,6 +98,7 @@ sdmmc-fatfs = ["embedded-sdmmc", "sdmmc"]
9398
ethernet = ["smoltcp"]
9499
rtc = ["chrono"]
95100
crc = []
101+
rand = ["rand_core"]
96102
rt = ["stm32h7/rt"]
97103
usb_hs = ["synopsys-usb-otg", "synopsys-usb-otg/hs"]
98104
stm32h742 = ["stm32h7/stm32h743", "device-selected", "rm0433"]

src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
//! External Memory
3232
//!
3333
//! * [Flexible Memory Controller (FMC)](crate::fmc) Feature gate `fmc`
34-
//! * [SD Card (SDMMC)](crate::sdmmc) Feature gate `sdmmc`
34+
//! * [SD Card (SDMMC)](crate::sdmmc) Feature gate `sdmmc` (FAT16/32 driver is available under the `sdmmc-fatfs` feature gate)
3535
//!
3636
//! Timing functions
3737
//!
@@ -44,7 +44,7 @@
4444
//! Others
4545
//!
4646
//! * [Cyclic Redundancy Check (CRC)](crate::crc) Feature gate `crc`
47-
//! * [Random Number Generator](crate::rng)
47+
//! * [Random Number Generator](crate::rng) ([rand_core::RngCore](rand_core::RngCore) is implemented under the`rand` feature gate)
4848
//! * [System Window Watchdog](crate::watchdog)
4949
5050
#![cfg_attr(not(test), no_std)]

src/rng.rs

Lines changed: 108 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ use crate::time::Hertz;
1515

1616
#[derive(Debug)]
1717
pub enum ErrorKind {
18-
ClockError,
19-
SeedError,
18+
ClockError = 0,
19+
SeedError = 1,
2020
}
2121

2222
trait KerClk {
@@ -131,8 +131,112 @@ macro_rules! rng_core {
131131
};
132132
}
133133

134-
rng_core!(u32, u16, u8);
134+
// Only for types larger than 32 bits
135+
macro_rules! rng_core_large {
136+
($($type:ty),+) => {
137+
$(
138+
impl RngCore<$type> for Rng {
139+
fn gen(&mut self) -> Result<$type, ErrorKind> {
140+
const WORDS: usize = mem::size_of::<$type>() / mem::size_of::<u32>();
141+
let mut res: $type = 0;
142+
143+
for i in 0..WORDS {
144+
res |= (self.value()? as $type) << (i * (mem::size_of::<u32>() * 8))
145+
}
146+
147+
Ok(res)
148+
}
149+
150+
fn fill(&mut self, dest: &mut [$type]) -> Result<(), ErrorKind> {
151+
let len = dest.len() * (mem::size_of::<$type>() / mem::size_of::<u32>());
152+
let ptr = dest.as_mut_ptr() as *mut u32;
153+
let slice_u32 = unsafe { core::slice::from_raw_parts_mut(ptr, len) };
154+
self.fill(slice_u32)
155+
}
156+
}
157+
)+
158+
};
159+
}
160+
161+
macro_rules! rng_core_transmute {
162+
($($type:ty = $from:ty),+) => {
163+
$(
164+
impl RngCore<$type> for Rng {
165+
fn gen(&mut self) -> Result<$type, ErrorKind> {
166+
let num = <Self as RngCore<$from>>::gen(self)?;
167+
Ok(unsafe { mem::transmute::<$from, $type>(num) })
168+
}
135169

136-
// Test host may have > 32-bit types, which we don't consider.
170+
fn fill(&mut self, dest: &mut [$type]) -> Result<(), ErrorKind> {
171+
let unsigned_slice = unsafe { mem::transmute::<&mut [$type], &mut [$from]>(dest) };
172+
<Self as RngCore<$from>>::fill(self, unsigned_slice)
173+
}
174+
}
175+
)+
176+
};
177+
}
178+
179+
rng_core!(u8, u16, u32);
180+
181+
// Alignment of these types must be a multiple of mem::align_of::<32>()
182+
rng_core_large!(u64, u128);
183+
184+
// A and B must have the same alignment
185+
// rng_core_transmute!(A = B)
186+
// assert!(mem::align_of::<A>() == mem::align_of::<B>())
187+
rng_core_transmute!(
188+
i8 = u8,
189+
i16 = u16,
190+
i32 = u32,
191+
i64 = u64,
192+
i128 = u128,
193+
isize = usize
194+
);
195+
196+
// If usize is 32 bits, use the rng_core! impl
137197
#[cfg(target_pointer_width = "32")]
138198
rng_core!(usize);
199+
200+
// If usize is 64 bits, use the rng_core_large! impl
201+
#[cfg(target_pointer_width = "64")]
202+
rng_core_large!(usize);
203+
204+
// rand_core
205+
#[cfg(feature = "rand")]
206+
impl rand_core::RngCore for Rng {
207+
/// Generate a random u32
208+
/// Panics if RNG fails.
209+
fn next_u32(&mut self) -> u32 {
210+
self.gen().unwrap()
211+
}
212+
213+
/// Generate a random u64
214+
/// Panics if RNG fails.
215+
fn next_u64(&mut self) -> u64 {
216+
self.gen().unwrap()
217+
}
218+
219+
/// Fill a slice with random data.
220+
/// Panics if RNG fails.
221+
fn fill_bytes(&mut self, dest: &mut [u8]) {
222+
self.fill(dest).unwrap()
223+
}
224+
225+
/// Try to fill a slice with random data. Return an error if RNG fails.
226+
fn try_fill_bytes(
227+
&mut self,
228+
dest: &mut [u8],
229+
) -> Result<(), rand_core::Error> {
230+
self.fill(dest).map_err(|e| {
231+
core::num::NonZeroU32::new(
232+
rand_core::Error::CUSTOM_START + e as u32,
233+
)
234+
// This should never fail as long as no enum variant is equal to 0
235+
.expect("Internal hal error")
236+
.into()
237+
})
238+
}
239+
}
240+
241+
#[cfg(feature = "rand")]
242+
impl rand_core::CryptoRng for Rng {}

0 commit comments

Comments
 (0)