Skip to content

Commit e236d01

Browse files
committed
Let trait Fill be implemented for element types, not sliceable types
1 parent 14c9fd1 commit e236d01

File tree

2 files changed

+38
-44
lines changed

2 files changed

+38
-44
lines changed

src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -293,8 +293,8 @@ pub fn random_ratio(numerator: u32, denominator: u32) -> bool {
293293
#[cfg(feature = "thread_rng")]
294294
#[inline]
295295
#[track_caller]
296-
pub fn fill<T: Fill + ?Sized>(dest: &mut T) {
297-
dest.fill(&mut rng())
296+
pub fn fill<T: Fill>(dest: &mut [T]) {
297+
Fill::fill_slice(dest, &mut rng())
298298
}
299299

300300
#[cfg(test)]

src/rng.rs

Lines changed: 36 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -311,8 +311,8 @@ pub trait Rng: RngCore {
311311
///
312312
/// [`fill_bytes`]: RngCore::fill_bytes
313313
#[track_caller]
314-
fn fill<T: Fill + ?Sized>(&mut self, dest: &mut T) {
315-
dest.fill(self)
314+
fn fill<T: Fill>(&mut self, dest: &mut [T]) {
315+
Fill::fill_slice(dest, self)
316316
}
317317

318318
/// Alias for [`Rng::random`].
@@ -356,21 +356,24 @@ pub trait Rng: RngCore {
356356

357357
impl<R: RngCore + ?Sized> Rng for R {}
358358

359-
/// Types which may be filled with random data
359+
/// Support filling a slice with random data
360360
///
361-
/// This trait allows arrays to be efficiently filled with random data.
361+
/// This trait allows slices of "plain data" types to be efficiently filled
362+
/// with random data.
362363
///
363364
/// Implementations are expected to be portable across machines unless
364365
/// clearly documented otherwise (see the
365366
/// [Chapter on Portability](https://rust-random.github.io/book/portability.html)).
366-
pub trait Fill {
367-
/// Fill self with random data
368-
fn fill<R: Rng + ?Sized>(&mut self, rng: &mut R);
367+
/// The implementations provided achieve this by byte-swapping on big-endian
368+
/// machines.
369+
pub trait Fill: Sized {
370+
/// Fill this with random data
371+
fn fill_slice<R: Rng + ?Sized>(this: &mut [Self], rng: &mut R);
369372
}
370373

371-
impl Fill for [u8] {
372-
fn fill<R: Rng + ?Sized>(&mut self, rng: &mut R) {
373-
rng.fill_bytes(self)
374+
impl Fill for u8 {
375+
fn fill_slice<R: Rng + ?Sized>(this: &mut [Self], rng: &mut R) {
376+
rng.fill_bytes(this)
374377
}
375378
}
376379

@@ -387,48 +390,48 @@ macro_rules! impl_fill {
387390
// Force caller to wrap with an `unsafe` block
388391
__unsafe();
389392

390-
impl Fill for [$t] {
391-
fn fill<R: Rng + ?Sized>(&mut self, rng: &mut R) {
392-
if self.len() > 0 {
393-
let size = mem::size_of_val(self);
393+
impl Fill for $t {
394+
fn fill_slice<R: Rng + ?Sized>(this: &mut [Self], rng: &mut R) {
395+
if this.len() > 0 {
396+
let size = mem::size_of_val(this);
394397
rng.fill_bytes(
395-
// SAFETY: `self` non-null and valid for reads and writes within its `size`
396-
// bytes. `self` meets the alignment requirements of `&mut [u8]`.
397-
// The contents of `self` are initialized. Both `[u8]` and `[$t]` are valid
398+
// SAFETY: `this` non-null and valid for reads and writes within its `size`
399+
// bytes. `this` meets the alignment requirements of `&mut [u8]`.
400+
// The contents of `this` are initialized. Both `[u8]` and `[$t]` are valid
398401
// for all bit-patterns of their contents (note that the SAFETY requirement
399-
// on callers of this macro). `self` is not borrowed.
402+
// on callers of this macro). `this` is not borrowed.
400403
unsafe {
401-
slice::from_raw_parts_mut(self.as_mut_ptr()
404+
slice::from_raw_parts_mut(this.as_mut_ptr()
402405
as *mut u8,
403406
size
404407
)
405408
}
406409
);
407-
for x in self {
410+
for x in this {
408411
*x = x.to_le();
409412
}
410413
}
411414
}
412415
}
413416

414-
impl Fill for [Wrapping<$t>] {
415-
fn fill<R: Rng + ?Sized>(&mut self, rng: &mut R) {
416-
if self.len() > 0 {
417-
let size = self.len() * mem::size_of::<$t>();
417+
impl Fill for Wrapping<$t> {
418+
fn fill_slice<R: Rng + ?Sized>(this: &mut [Self], rng: &mut R) {
419+
if this.len() > 0 {
420+
let size = this.len() * mem::size_of::<$t>();
418421
rng.fill_bytes(
419-
// SAFETY: `self` non-null and valid for reads and writes within its `size`
420-
// bytes. `self` meets the alignment requirements of `&mut [u8]`.
421-
// The contents of `self` are initialized. Both `[u8]` and `[$t]` are valid
422+
// SAFETY: `this` non-null and valid for reads and writes within its `size`
423+
// bytes. `this` meets the alignment requirements of `&mut [u8]`.
424+
// The contents of `this` are initialized. Both `[u8]` and `[$t]` are valid
422425
// for all bit-patterns of their contents (note that the SAFETY requirement
423-
// on callers of this macro). `self` is not borrowed.
426+
// on callers of this macro). `this` is not borrowed.
424427
unsafe {
425-
slice::from_raw_parts_mut(self.as_mut_ptr()
428+
slice::from_raw_parts_mut(this.as_mut_ptr()
426429
as *mut u8,
427430
size
428431
)
429432
}
430433
);
431-
for x in self {
434+
for x in this {
432435
*x = Wrapping(x.0.to_le());
433436
}
434437
}
@@ -448,15 +451,6 @@ const _: () = unsafe { impl_fill!(u16, u32, u64, u128,) };
448451
// SAFETY: All bit patterns of `[u8; size_of::<$t>()]` represent values of `i*`.
449452
const _: () = unsafe { impl_fill!(i8, i16, i32, i64, i128,) };
450453

451-
impl<T, const N: usize> Fill for [T; N]
452-
where
453-
[T]: Fill,
454-
{
455-
fn fill<R: Rng + ?Sized>(&mut self, rng: &mut R) {
456-
<[T] as Fill>::fill(self, rng)
457-
}
458-
}
459-
460454
#[cfg(test)]
461455
mod test {
462456
use super::*;
@@ -491,19 +485,19 @@ mod test {
491485

492486
// Convert to byte sequence and back to u64; byte-swap twice if BE.
493487
let mut array = [0u64; 2];
494-
rng.fill(&mut array[..]);
488+
rng.fill(&mut array);
495489
assert_eq!(array, [x, x]);
496490
assert_eq!(rng.next_u64(), x);
497491

498492
// Convert to bytes then u32 in LE order
499493
let mut array = [0u32; 2];
500-
rng.fill(&mut array[..]);
494+
rng.fill(&mut array);
501495
assert_eq!(array, [x as u32, (x >> 32) as u32]);
502496
assert_eq!(rng.next_u32(), x as u32);
503497

504498
// Check equivalence using wrapped arrays
505499
let mut warray = [Wrapping(0u32); 2];
506-
rng.fill(&mut warray[..]);
500+
rng.fill(&mut warray);
507501
assert_eq!(array[0], warray[0].0);
508502
assert_eq!(array[1], warray[1].0);
509503
}

0 commit comments

Comments
 (0)