Skip to content

Commit 34a8f13

Browse files
committed
Replace ToLe with Observable, including as_byte_slice method
1 parent 19b7a76 commit 34a8f13

File tree

1 file changed

+18
-13
lines changed

1 file changed

+18
-13
lines changed

rand_core/src/impls.rs

+18-13
Original file line numberDiff line numberDiff line change
@@ -52,39 +52,44 @@ pub fn fill_bytes_via_next<R: RngCore + ?Sized>(rng: &mut R, dest: &mut [u8]) {
5252
}
5353
}
5454

55-
/// Contract: implementing type must be memory-safe to observe as a byte array
56-
/// (implies no uninitialised padding).
57-
unsafe trait ToLe: Copy {
55+
trait Observable: Copy {
5856
type Bytes: AsRef<[u8]>;
5957
fn to_le_bytes(self) -> Self::Bytes;
58+
59+
// Contract: observing self is memory-safe (implies no uninitialised padding)
60+
fn as_byte_slice(x: &[Self]) -> &[u8];
6061
}
61-
unsafe impl ToLe for u32 {
62+
impl Observable for u32 {
6263
type Bytes = [u8; 4];
6364
fn to_le_bytes(self) -> Self::Bytes {
6465
self.to_le_bytes()
6566
}
67+
fn as_byte_slice(x: &[Self]) -> &[u8] {
68+
let ptr = x.as_ptr() as *const u8;
69+
let len = x.len() * core::mem::size_of::<Self>();
70+
unsafe { core::slice::from_raw_parts(ptr, len) }
71+
}
6672
}
67-
unsafe impl ToLe for u64 {
73+
impl Observable for u64 {
6874
type Bytes = [u8; 8];
6975
fn to_le_bytes(self) -> Self::Bytes {
7076
self.to_le_bytes()
7177
}
78+
fn as_byte_slice(x: &[Self]) -> &[u8] {
79+
let ptr = x.as_ptr() as *const u8;
80+
let len = x.len() * core::mem::size_of::<Self>();
81+
unsafe { core::slice::from_raw_parts(ptr, len) }
82+
}
7283
}
7384

74-
fn fill_via_chunks<T: ToLe>(src: &[T], dest: &mut [u8]) -> (usize, usize) {
85+
fn fill_via_chunks<T: Observable>(src: &[T], dest: &mut [u8]) -> (usize, usize) {
7586
let size = core::mem::size_of::<T>();
7687
let byte_len = min(src.len() * size, dest.len());
7788
let num_chunks = (byte_len + size - 1) / size;
7889

7990
if cfg!(target_endian = "little") {
8091
// On LE we can do a simple copy, which is 25-50% faster:
81-
unsafe {
82-
core::ptr::copy_nonoverlapping(
83-
src.as_ptr() as *const u8,
84-
dest.as_mut_ptr(),
85-
byte_len,
86-
);
87-
}
92+
dest[..byte_len].copy_from_slice(&T::as_byte_slice(&src[..num_chunks])[..byte_len]);
8893
} else {
8994
// This code is valid on all arches, but slower than the above:
9095
let mut i = 0;

0 commit comments

Comments
 (0)