]>
Commit | Line | Data |
---|---|---|
1a4d82fc JJ |
1 | // Copyright 2013 The Rust Project Developers. See the COPYRIGHT |
2 | // file at the top-level directory of this distribution and at | |
3 | // http://rust-lang.org/COPYRIGHT. | |
4 | // | |
5 | // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | |
6 | // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | |
7 | // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | |
8 | // option. This file may not be copied, modified, or distributed | |
9 | // except according to those terms. | |
10 | ||
9346a6ac | 11 | //! A wrapper around any Read to treat it as an RNG. |
1a4d82fc | 12 | |
9346a6ac AL |
13 | #![allow(dead_code)] |
14 | ||
15 | use prelude::v1::*; | |
16 | use io::prelude::*; | |
1a4d82fc | 17 | use rand::Rng; |
1a4d82fc | 18 | |
9346a6ac | 19 | /// An RNG that reads random bytes straight from a `Read`. This will |
1a4d82fc JJ |
20 | /// work best with an infinite reader, but this is not required. |
21 | /// | |
22 | /// # Panics | |
23 | /// | |
24 | /// It will panic if it there is insufficient data to fulfill a request. | |
1a4d82fc JJ |
25 | pub struct ReaderRng<R> { |
26 | reader: R | |
27 | } | |
28 | ||
9346a6ac AL |
29 | impl<R: Read> ReaderRng<R> { |
30 | /// Create a new `ReaderRng` from a `Read`. | |
1a4d82fc JJ |
31 | pub fn new(r: R) -> ReaderRng<R> { |
32 | ReaderRng { | |
33 | reader: r | |
34 | } | |
35 | } | |
36 | } | |
37 | ||
9346a6ac | 38 | impl<R: Read> Rng for ReaderRng<R> { |
1a4d82fc JJ |
39 | fn next_u32(&mut self) -> u32 { |
40 | // This is designed for speed: reading a LE integer on a LE | |
41 | // platform just involves blitting the bytes into the memory | |
42 | // of the u32, similarly for BE on BE; avoiding byteswapping. | |
9346a6ac AL |
43 | let mut bytes = [0; 4]; |
44 | self.fill_bytes(&mut bytes); | |
45 | unsafe { *(bytes.as_ptr() as *const u32) } | |
1a4d82fc JJ |
46 | } |
47 | fn next_u64(&mut self) -> u64 { | |
48 | // see above for explanation. | |
9346a6ac AL |
49 | let mut bytes = [0; 8]; |
50 | self.fill_bytes(&mut bytes); | |
51 | unsafe { *(bytes.as_ptr() as *const u64) } | |
1a4d82fc | 52 | } |
9346a6ac AL |
53 | fn fill_bytes(&mut self, mut v: &mut [u8]) { |
54 | while !v.is_empty() { | |
55 | let t = v; | |
56 | match self.reader.read(t) { | |
57 | Ok(0) => panic!("ReaderRng.fill_bytes: EOF reached"), | |
58 | Ok(n) => v = t.split_at_mut(n).1, | |
59 | Err(e) => panic!("ReaderRng.fill_bytes: {}", e), | |
60 | } | |
1a4d82fc JJ |
61 | } |
62 | } | |
63 | } | |
64 | ||
65 | #[cfg(test)] | |
d9579d0f | 66 | mod tests { |
1a4d82fc JJ |
67 | use prelude::v1::*; |
68 | ||
69 | use super::ReaderRng; | |
1a4d82fc JJ |
70 | use rand::Rng; |
71 | ||
72 | #[test] | |
73 | fn test_reader_rng_u64() { | |
74 | // transmute from the target to avoid endianness concerns. | |
9346a6ac AL |
75 | let v = &[0, 0, 0, 0, 0, 0, 0, 1, |
76 | 0 , 0, 0, 0, 0, 0, 0, 2, | |
77 | 0, 0, 0, 0, 0, 0, 0, 3][..]; | |
78 | let mut rng = ReaderRng::new(v); | |
1a4d82fc | 79 | |
9346a6ac AL |
80 | assert_eq!(rng.next_u64(), 1u64.to_be()); |
81 | assert_eq!(rng.next_u64(), 2u64.to_be()); | |
82 | assert_eq!(rng.next_u64(), 3u64.to_be()); | |
1a4d82fc JJ |
83 | } |
84 | #[test] | |
85 | fn test_reader_rng_u32() { | |
9346a6ac AL |
86 | let v = &[0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 3][..]; |
87 | let mut rng = ReaderRng::new(v); | |
1a4d82fc | 88 | |
9346a6ac AL |
89 | assert_eq!(rng.next_u32(), 1u32.to_be()); |
90 | assert_eq!(rng.next_u32(), 2u32.to_be()); | |
91 | assert_eq!(rng.next_u32(), 3u32.to_be()); | |
1a4d82fc JJ |
92 | } |
93 | #[test] | |
94 | fn test_reader_rng_fill_bytes() { | |
c34b1796 AL |
95 | let v = [1, 2, 3, 4, 5, 6, 7, 8]; |
96 | let mut w = [0; 8]; | |
1a4d82fc | 97 | |
9346a6ac | 98 | let mut rng = ReaderRng::new(&v[..]); |
1a4d82fc JJ |
99 | rng.fill_bytes(&mut w); |
100 | ||
101 | assert!(v == w); | |
102 | } | |
103 | ||
104 | #[test] | |
c34b1796 | 105 | #[should_panic] |
1a4d82fc | 106 | fn test_reader_rng_insufficient_bytes() { |
9346a6ac | 107 | let mut rng = ReaderRng::new(&[][..]); |
c34b1796 | 108 | let mut v = [0; 3]; |
1a4d82fc JJ |
109 | rng.fill_bytes(&mut v); |
110 | } | |
111 | } |