|
262 | 262 | #[cfg(all(feature="std", not(feature = "log")))] macro_rules! error { ($($x:tt)*) => () }
|
263 | 263 |
|
264 | 264 |
|
265 |
| -use core::{marker, mem}; |
| 265 | +use core::{marker, mem, slice}; |
266 | 266 | #[cfg(feature="std")] use std::cell::RefCell;
|
267 | 267 | #[cfg(feature="std")] use std::rc::Rc;
|
268 | 268 | #[cfg(all(feature="alloc", not(feature="std")))] use alloc::boxed::Box;
|
@@ -538,6 +538,71 @@ pub trait RngCore {
|
538 | 538 | ///
|
539 | 539 | /// [`RngCore`]: trait.RngCore.html
|
540 | 540 | pub trait Rng: RngCore + Sized {
|
| 541 | + /// Fill `dest` entirely with random bytes, where `dest` is any type |
| 542 | + /// supporting [`AsByteSliceMut`], namely slices over primitive integer |
| 543 | + /// types (`i8`, `i16`, `u32`, etc.). |
| 544 | + /// |
| 545 | + /// On big-endian platforms this performs byte-swapping to ensure |
| 546 | + /// portability of results from reproducible generators. |
| 547 | + /// |
| 548 | + /// This uses [`fill_bytes`] internally which may handle some RNG errors |
| 549 | + /// implicitly (e.g. waiting if the OS generator is not ready), but panics |
| 550 | + /// on other errors. See also [`try_fill`] which returns errors. |
| 551 | + /// |
| 552 | + /// # Example |
| 553 | + /// |
| 554 | + /// ```rust |
| 555 | + /// use rand::{thread_rng, Rng}; |
| 556 | + /// |
| 557 | + /// let mut arr = [0i8; 20]; |
| 558 | + /// thread_rng().try_fill(&mut arr[..]); |
| 559 | + /// ``` |
| 560 | + /// |
| 561 | + /// [`fill_bytes`]: trait.RngCore.html#method.fill_bytes |
| 562 | + /// [`try_fill`]: trait.Rng.html#method.try_fill |
| 563 | + /// [`AsByteSliceMut`]: trait.AsByteSliceMut.html |
| 564 | + fn fill<T: AsByteSliceMut + ?Sized>(&mut self, dest: &mut T) where Self: Sized { |
| 565 | + self.fill_bytes(dest.as_byte_slice_mut()); |
| 566 | + dest.to_le(); |
| 567 | + } |
| 568 | + |
| 569 | + /// Fill `dest` entirely with random bytes, where `dest` is any type |
| 570 | + /// supporting [`AsByteSliceMut`], namely slices over primitive integer |
| 571 | + /// types (`i8`, `i16`, `u32`, etc.). |
| 572 | + /// |
| 573 | + /// On big-endian platforms this performs byte-swapping to ensure |
| 574 | + /// portability of results from reproducible generators. |
| 575 | + /// |
| 576 | + /// This uses [`try_fill_bytes`] internally and forwards all RNG errors. In |
| 577 | + /// some cases errors may be resolvable; see [`ErrorKind`] and |
| 578 | + /// documentation for the RNG in use. If you do not plan to handle these |
| 579 | + /// errors you may prefer to use [`fill`]. |
| 580 | + /// |
| 581 | + /// # Example |
| 582 | + /// |
| 583 | + /// ```rust |
| 584 | + /// # use rand::Error; |
| 585 | + /// use rand::{thread_rng, Rng}; |
| 586 | + /// |
| 587 | + /// # fn try_inner() -> Result<(), Error> { |
| 588 | + /// let mut arr = [0u64; 4]; |
| 589 | + /// thread_rng().try_fill(&mut arr[..])?; |
| 590 | + /// # Ok(()) |
| 591 | + /// # } |
| 592 | + /// |
| 593 | + /// # try_inner().unwrap() |
| 594 | + /// ``` |
| 595 | + /// |
| 596 | + /// [`ErrorKind`]: enum.ErrorKind.html |
| 597 | + /// [`try_fill_bytes`]: trait.RngCore.html#method.try_fill_bytes |
| 598 | + /// [`fill`]: trait.Rng.html#method.fill |
| 599 | + /// [`AsByteSliceMut`]: trait.AsByteSliceMut.html |
| 600 | + fn try_fill<T: AsByteSliceMut + ?Sized>(&mut self, dest: &mut T) -> Result<(), Error> where Self: Sized { |
| 601 | + self.try_fill_bytes(dest.as_byte_slice_mut())?; |
| 602 | + dest.to_le(); |
| 603 | + Ok(()) |
| 604 | + } |
| 605 | + |
541 | 606 | /// Return a random value of a `Rand` type.
|
542 | 607 | ///
|
543 | 608 | /// # Example
|
@@ -759,6 +824,62 @@ impl<R: RngCore + ?Sized> RngCore for Box<R> {
|
759 | 824 | }
|
760 | 825 | }
|
761 | 826 |
|
| 827 | +/// Trait for casting types to byte slices |
| 828 | +/// |
| 829 | +/// This is used by the [`fill`] and [`try_fill`] methods. |
| 830 | +/// |
| 831 | +/// [`fill`]: trait.Rng.html#method.fill |
| 832 | +/// [`try_fill`]: trait.Rng.html#method.try_fill |
| 833 | +pub trait AsByteSliceMut { |
| 834 | + /// Return a mutable reference to self as a byte slice |
| 835 | + fn as_byte_slice_mut<'a>(&'a mut self) -> &'a mut [u8]; |
| 836 | + |
| 837 | + /// Call `to_le` on each element (i.e. byte-swap on Big Endian platforms). |
| 838 | + fn to_le(&mut self); |
| 839 | +} |
| 840 | + |
| 841 | +impl AsByteSliceMut for [u8] { |
| 842 | + fn as_byte_slice_mut<'a>(&'a mut self) -> &'a mut [u8] { |
| 843 | + self |
| 844 | + } |
| 845 | + |
| 846 | + fn to_le(&mut self) {} |
| 847 | +} |
| 848 | + |
| 849 | +macro_rules! impl_as_byte_slice { |
| 850 | + ($t:ty) => { |
| 851 | + impl AsByteSliceMut for [$t] { |
| 852 | + fn as_byte_slice_mut<'a>(&'a mut self) -> &'a mut [u8] { |
| 853 | + unsafe { |
| 854 | + slice::from_raw_parts_mut(&mut self[0] |
| 855 | + as *mut $t |
| 856 | + as *mut u8, |
| 857 | + self.len() * mem::size_of::<$t>() |
| 858 | + ) |
| 859 | + } |
| 860 | + } |
| 861 | + |
| 862 | + fn to_le(&mut self) { |
| 863 | + for mut x in self { |
| 864 | + *x = x.to_le(); |
| 865 | + } |
| 866 | + } |
| 867 | + } |
| 868 | + } |
| 869 | +} |
| 870 | + |
| 871 | +impl_as_byte_slice!(u16); |
| 872 | +impl_as_byte_slice!(u32); |
| 873 | +impl_as_byte_slice!(u64); |
| 874 | +#[cfg(feature="i128_support")] impl_as_byte_slice!(u128); |
| 875 | +impl_as_byte_slice!(usize); |
| 876 | +impl_as_byte_slice!(i8); |
| 877 | +impl_as_byte_slice!(i16); |
| 878 | +impl_as_byte_slice!(i32); |
| 879 | +impl_as_byte_slice!(i64); |
| 880 | +#[cfg(feature="i128_support")] impl_as_byte_slice!(i128); |
| 881 | +impl_as_byte_slice!(isize); |
| 882 | + |
762 | 883 | /// Iterator which will generate a stream of random items.
|
763 | 884 | ///
|
764 | 885 | /// This iterator is created via the [`gen_iter`] method on [`Rng`].
|
@@ -1364,6 +1485,24 @@ mod test {
|
1364 | 1485 | }
|
1365 | 1486 | }
|
1366 | 1487 | }
|
| 1488 | + |
| 1489 | + #[test] |
| 1490 | + fn test_fill() { |
| 1491 | + let x = 9041086907909331047; // a random u64 |
| 1492 | + let mut rng = ConstRng { i: x }; |
| 1493 | + |
| 1494 | + // Convert to byte sequence and back to u64; byte-swap twice if BE. |
| 1495 | + let mut array = [0u64; 2]; |
| 1496 | + rng.fill(&mut array[..]); |
| 1497 | + assert_eq!(array, [x, x]); |
| 1498 | + assert_eq!(rng.next_u64(), x); |
| 1499 | + |
| 1500 | + // Convert to bytes then u32 in LE order |
| 1501 | + let mut array = [0u32; 2]; |
| 1502 | + rng.fill(&mut array[..]); |
| 1503 | + assert_eq!(array, [x as u32, (x >> 32) as u32]); |
| 1504 | + assert_eq!(rng.next_u32(), x as u32); |
| 1505 | + } |
1367 | 1506 |
|
1368 | 1507 | #[test]
|
1369 | 1508 | fn test_gen_range() {
|
|
0 commit comments