|
261 | 261 | #[cfg(all(feature="std", not(feature = "log")))] macro_rules! warn { ($($x:tt)*) => () }
|
262 | 262 |
|
263 | 263 |
|
264 |
| -use core::{marker, mem}; |
| 264 | +use core::{marker, mem, slice}; |
265 | 265 | #[cfg(feature="std")] use std::cell::RefCell;
|
266 | 266 | #[cfg(feature="std")] use std::rc::Rc;
|
267 | 267 | #[cfg(all(feature="alloc", not(feature="std")))] use alloc::boxed::Box;
|
@@ -482,6 +482,66 @@ pub trait Rng {
|
482 | 482 | Ok(self.fill_bytes(dest))
|
483 | 483 | }
|
484 | 484 |
|
| 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 | + |
485 | 545 | /// Return a random value of a `Rand` type.
|
486 | 546 | ///
|
487 | 547 | /// # Example
|
@@ -701,6 +761,46 @@ impl<R: ?Sized> Rng for Box<R> where R: Rng {
|
701 | 761 | }
|
702 | 762 | }
|
703 | 763 |
|
| 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 | + |
704 | 804 | /// Iterator which will generate a stream of random items.
|
705 | 805 | ///
|
706 | 806 | /// This iterator is created via the [`gen_iter`] method on [`Rng`].
|
@@ -1162,6 +1262,24 @@ mod test {
|
1162 | 1262 | }
|
1163 | 1263 | }
|
1164 | 1264 | }
|
| 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 | + } |
1165 | 1283 |
|
1166 | 1284 | #[test]
|
1167 | 1285 | fn test_gen_range() {
|
|
0 commit comments