Skip to content

Commit 93a80bd

Browse files
committed
Add fill and try_fill methods to Rng
1 parent 7d72ba9 commit 93a80bd

File tree

1 file changed

+119
-1
lines changed

1 file changed

+119
-1
lines changed

src/lib.rs

Lines changed: 119 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,7 @@
261261
#[cfg(all(feature="std", not(feature = "log")))] macro_rules! warn { ($($x:tt)*) => () }
262262

263263

264-
use core::{marker, mem};
264+
use core::{marker, mem, slice};
265265
#[cfg(feature="std")] use std::cell::RefCell;
266266
#[cfg(feature="std")] use std::rc::Rc;
267267
#[cfg(all(feature="alloc", not(feature="std")))] use alloc::boxed::Box;
@@ -482,6 +482,66 @@ pub trait Rng {
482482
Ok(self.fill_bytes(dest))
483483
}
484484

485+
/// Fill `dest` entirely with random data.
486+
///
487+
/// This method provides a convenient way to fill a slice with random data.
488+
///
489+
/// On big-endian platforms this performs byte-swapping to ensure
490+
/// portability of results from reproducible generators.
491+
///
492+
/// # Example
493+
///
494+
/// ```rust
495+
/// use rand::{thread_rng, Rng};
496+
///
497+
/// let mut arr = [0i8; 20];
498+
/// thread_rng().try_fill(&mut arr[..]);
499+
/// ```
500+
///
501+
/// [`ErrorKind`]: enum.ErrorKind.html
502+
fn fill<T: AsByteSliceMut + ?Sized>(&mut self, dest: &mut T) where Self: Sized {
503+
let slice = dest.as_byte_slice_mut();
504+
self.fill_bytes(slice);
505+
for mut x in slice {
506+
x.to_le();
507+
}
508+
}
509+
510+
/// Fill `dest` entirely with random data.
511+
///
512+
/// This method provides a convenient way to fill a slice with random data.
513+
///
514+
/// On big-endian platforms this performs byte-swapping to ensure
515+
/// portability of results from reproducible generators.
516+
///
517+
/// Errors are forwarded from their source. In some cases errors may be
518+
/// resolvable; see [`ErrorKind`] and documentation for the RNG in use.
519+
///
520+
/// # Example
521+
///
522+
/// ```rust
523+
/// # use rand::Error;
524+
/// use rand::{thread_rng, Rng};
525+
///
526+
/// # fn try_inner() -> Result<(), Error> {
527+
/// let mut arr = [0u64; 4];
528+
/// thread_rng().try_fill(&mut arr[..])?;
529+
/// # Ok(())
530+
/// # }
531+
///
532+
/// # try_inner().unwrap()
533+
/// ```
534+
///
535+
/// [`ErrorKind`]: enum.ErrorKind.html
536+
fn try_fill<T: AsByteSliceMut + ?Sized>(&mut self, dest: &mut T) -> Result<(), Error> where Self: Sized {
537+
let slice = dest.as_byte_slice_mut();
538+
self.try_fill_bytes(slice)?;
539+
for mut x in slice {
540+
x.to_le();
541+
}
542+
Ok(())
543+
}
544+
485545
/// Return a random value of a `Rand` type.
486546
///
487547
/// # Example
@@ -701,6 +761,46 @@ impl<R: ?Sized> Rng for Box<R> where R: Rng {
701761
}
702762
}
703763

764+
/// Trait for casting types to byte slices
765+
pub trait AsByteSliceMut {
766+
/// Return a mutable reference to self as a byte slice
767+
fn as_byte_slice_mut<'a>(&'a mut self) -> &'a mut [u8];
768+
}
769+
770+
impl AsByteSliceMut for [u8] {
771+
fn as_byte_slice_mut<'a>(&'a mut self) -> &'a mut [u8] {
772+
self
773+
}
774+
}
775+
776+
macro_rules! impl_as_byte_slice {
777+
($t:ty) => {
778+
impl AsByteSliceMut for [$t] {
779+
fn as_byte_slice_mut<'a>(&'a mut self) -> &'a mut [u8] {
780+
unsafe {
781+
slice::from_raw_parts_mut(&mut self[0]
782+
as *mut $t
783+
as *mut u8,
784+
self.len() * mem::size_of::<$t>()
785+
)
786+
}
787+
}
788+
}
789+
}
790+
}
791+
792+
impl_as_byte_slice!(u16);
793+
impl_as_byte_slice!(u32);
794+
impl_as_byte_slice!(u64);
795+
#[cfg(feature="i128_support")] impl_as_byte_slice!(u128);
796+
impl_as_byte_slice!(usize);
797+
impl_as_byte_slice!(i8);
798+
impl_as_byte_slice!(i16);
799+
impl_as_byte_slice!(i32);
800+
impl_as_byte_slice!(i64);
801+
#[cfg(feature="i128_support")] impl_as_byte_slice!(i128);
802+
impl_as_byte_slice!(isize);
803+
704804
/// Iterator which will generate a stream of random items.
705805
///
706806
/// This iterator is created via the [`gen_iter`] method on [`Rng`].
@@ -1162,6 +1262,24 @@ mod test {
11621262
}
11631263
}
11641264
}
1265+
1266+
#[test]
1267+
fn test_fill() {
1268+
let x = 9041086907909331047; // a random u64
1269+
let mut rng = ConstRng { i: x };
1270+
1271+
// Convert to byte sequence and back to u64; byte-swap twice if BE.
1272+
let mut array = [0u64; 2];
1273+
rng.fill(&mut array[..]);
1274+
assert_eq!(array, [x, x]);
1275+
assert_eq!(rng.next_u64(), x);
1276+
1277+
// Convert to bytes then u32 in LE order
1278+
let mut array = [0u32; 2];
1279+
rng.fill(&mut array[..]);
1280+
assert_eq!(array, [x as u32, (x >> 32) as u32]);
1281+
assert_eq!(rng.next_u32(), x as u32);
1282+
}
11651283

11661284
#[test]
11671285
fn test_gen_range() {

0 commit comments

Comments
 (0)