1 // Copyright 2018 Developers of the Rand project. 2 // Copyright 2013 The Rust Project Developers. 3 // 4 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or 5 // https://www.apache.org/licenses/LICENSE-2.0> or the MIT license 6 // <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your 7 // option. This file may not be copied, modified, or distributed 8 // except according to those terms. 9 10 //! A wrapper around any Read to treat it as an RNG. 11 12 #![allow(deprecated)] 13 14 use std::fmt; 15 use std::io::Read; 16 17 use rand_core::{impls, Error, RngCore}; 18 19 20 /// An RNG that reads random bytes straight from any type supporting 21 /// [`std::io::Read`], for example files. 22 /// 23 /// This will work best with an infinite reader, but that is not required. 24 /// 25 /// This can be used with `/dev/urandom` on Unix but it is recommended to use 26 /// [`OsRng`] instead. 27 /// 28 /// # Panics 29 /// 30 /// `ReadRng` uses [`std::io::Read::read_exact`], which retries on interrupts. 31 /// All other errors from the underlying reader, including when it does not 32 /// have enough data, will only be reported through [`try_fill_bytes`]. 33 /// The other [`RngCore`] methods will panic in case of an error. 34 /// 35 /// [`OsRng`]: crate::rngs::OsRng 36 /// [`try_fill_bytes`]: RngCore::try_fill_bytes 37 #[derive(Debug)] 38 #[deprecated(since="0.8.4", note="removal due to lack of usage")] 39 pub struct ReadRng<R> { 40 reader: R, 41 } 42 43 impl<R: Read> ReadRng<R> { 44 /// Create a new `ReadRng` from a `Read`. new(r: R) -> ReadRng<R>45 pub fn new(r: R) -> ReadRng<R> { 46 ReadRng { reader: r } 47 } 48 } 49 50 impl<R: Read> RngCore for ReadRng<R> { next_u32(&mut self) -> u3251 fn next_u32(&mut self) -> u32 { 52 impls::next_u32_via_fill(self) 53 } 54 next_u64(&mut self) -> u6455 fn next_u64(&mut self) -> u64 { 56 impls::next_u64_via_fill(self) 57 } 58 fill_bytes(&mut self, dest: &mut [u8])59 fn fill_bytes(&mut self, dest: &mut [u8]) { 60 self.try_fill_bytes(dest).unwrap_or_else(|err| { 61 panic!( 62 "reading random bytes from Read implementation failed; error: {}", 63 err 64 ) 65 }); 66 } 67 try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error>68 fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> { 69 if dest.is_empty() { 70 return Ok(()); 71 } 72 // Use `std::io::read_exact`, which retries on `ErrorKind::Interrupted`. 73 self.reader 74 .read_exact(dest) 75 .map_err(|e| Error::new(ReadError(e))) 76 } 77 } 78 79 /// `ReadRng` error type 80 #[derive(Debug)] 81 #[deprecated(since="0.8.4")] 82 pub struct ReadError(std::io::Error); 83 84 impl fmt::Display for ReadError { fmt(&self, f: &mut fmt::Formatter) -> fmt::Result85 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 86 write!(f, "ReadError: {}", self.0) 87 } 88 } 89 90 impl std::error::Error for ReadError { source(&self) -> Option<&(dyn std::error::Error + 'static)>91 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { 92 Some(&self.0) 93 } 94 } 95 96 97 #[cfg(test)] 98 mod test { 99 use std::println; 100 101 use super::ReadRng; 102 use crate::RngCore; 103 104 #[test] test_reader_rng_u64()105 fn test_reader_rng_u64() { 106 // transmute from the target to avoid endianness concerns. 107 #[rustfmt::skip] 108 let v = [0u8, 0, 0, 0, 0, 0, 0, 1, 109 0, 4, 0, 0, 3, 0, 0, 2, 110 5, 0, 0, 0, 0, 0, 0, 0]; 111 let mut rng = ReadRng::new(&v[..]); 112 113 assert_eq!(rng.next_u64(), 1 << 56); 114 assert_eq!(rng.next_u64(), (2 << 56) + (3 << 32) + (4 << 8)); 115 assert_eq!(rng.next_u64(), 5); 116 } 117 118 #[test] test_reader_rng_u32()119 fn test_reader_rng_u32() { 120 let v = [0u8, 0, 0, 1, 0, 0, 2, 0, 3, 0, 0, 0]; 121 let mut rng = ReadRng::new(&v[..]); 122 123 assert_eq!(rng.next_u32(), 1 << 24); 124 assert_eq!(rng.next_u32(), 2 << 16); 125 assert_eq!(rng.next_u32(), 3); 126 } 127 128 #[test] test_reader_rng_fill_bytes()129 fn test_reader_rng_fill_bytes() { 130 let v = [1u8, 2, 3, 4, 5, 6, 7, 8]; 131 let mut w = [0u8; 8]; 132 133 let mut rng = ReadRng::new(&v[..]); 134 rng.fill_bytes(&mut w); 135 136 assert!(v == w); 137 } 138 139 #[test] test_reader_rng_insufficient_bytes()140 fn test_reader_rng_insufficient_bytes() { 141 let v = [1u8, 2, 3, 4, 5, 6, 7, 8]; 142 let mut w = [0u8; 9]; 143 144 let mut rng = ReadRng::new(&v[..]); 145 146 let result = rng.try_fill_bytes(&mut w); 147 assert!(result.is_err()); 148 println!("Error: {}", result.unwrap_err()); 149 } 150 } 151