Skip to content

Commit 1327048

Browse files
committed
fill_via_chunks: make a generic function
1 parent 45f33d1 commit 1327048

File tree

1 file changed

+34
-22
lines changed

1 file changed

+34
-22
lines changed

rand_core/src/impls.rs

Lines changed: 34 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -52,29 +52,41 @@ pub fn fill_bytes_via_next<R: RngCore + ?Sized>(rng: &mut R, dest: &mut [u8]) {
5252
}
5353
}
5454

55-
macro_rules! fill_via_chunks {
56-
($src:expr, $dst:expr, $ty:ty) => {{
57-
const SIZE: usize = core::mem::size_of::<$ty>();
58-
let chunk_size_u8 = min($src.len() * SIZE, $dst.len());
59-
let chunk_size = (chunk_size_u8 + SIZE - 1) / SIZE;
60-
61-
// Byte-swap for portability of results:
62-
if cfg!(target_endian = "big") {
63-
for x in &mut $src[..chunk_size] {
64-
*x = x.to_le();
65-
}
66-
}
55+
trait ToLe: Copy {
56+
fn to_le(self) -> Self;
57+
}
58+
impl ToLe for u32 {
59+
fn to_le(self) -> Self {
60+
self.to_le()
61+
}
62+
}
63+
impl ToLe for u64 {
64+
fn to_le(self) -> Self {
65+
self.to_le()
66+
}
67+
}
68+
69+
fn fill_via_chunks<T: ToLe>(src: &mut [T], dest: &mut [u8]) -> (usize, usize) {
70+
let size = core::mem::size_of::<T>();
71+
let chunk_size_u8 = min(src.len() * size, dest.len());
72+
let chunk_size = (chunk_size_u8 + size - 1) / size;
6773

68-
// We do a simple copy, which is 25-50% faster:
69-
unsafe {
70-
core::ptr::copy_nonoverlapping(
71-
$src.as_ptr() as *const u8,
72-
$dst.as_mut_ptr(),
73-
chunk_size_u8);
74+
// Byte-swap for portability of results:
75+
if cfg!(target_endian = "big") {
76+
for x in &mut src[..chunk_size] {
77+
*x = x.to_le();
7478
}
79+
}
80+
81+
unsafe {
82+
core::ptr::copy_nonoverlapping(
83+
src.as_ptr() as *const u8,
84+
dest.as_mut_ptr(),
85+
chunk_size_u8,
86+
);
87+
}
7588

76-
(chunk_size, chunk_size_u8)
77-
}};
89+
(chunk_size, chunk_size_u8)
7890
}
7991

8092
/// Implement `fill_bytes` by reading chunks from the output buffer of a block
@@ -111,7 +123,7 @@ macro_rules! fill_via_chunks {
111123
/// }
112124
/// ```
113125
pub fn fill_via_u32_chunks(src: &mut [u32], dest: &mut [u8]) -> (usize, usize) {
114-
fill_via_chunks!(src, dest, u32)
126+
fill_via_chunks(src, dest)
115127
}
116128

117129
/// Implement `fill_bytes` by reading chunks from the output buffer of a block
@@ -129,7 +141,7 @@ pub fn fill_via_u32_chunks(src: &mut [u32], dest: &mut [u8]) -> (usize, usize) {
129141
///
130142
/// See `fill_via_u32_chunks` for an example.
131143
pub fn fill_via_u64_chunks(src: &mut [u64], dest: &mut [u8]) -> (usize, usize) {
132-
fill_via_chunks!(src, dest, u64)
144+
fill_via_chunks(src, dest)
133145
}
134146

135147
/// Implement `next_u32` via `fill_bytes`, little-endian order.

0 commit comments

Comments
 (0)