(index<- ) ./libstd/rand/reader.rs
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
11 //! A wrapper around any Reader to treat it as an RNG.
12
13 use option::{Some, None};
14 use rt::io::Reader;
15 use rt::io::ReaderByteConversions;
16
17 use rand::Rng;
18
19 /// An RNG that reads random bytes straight from a `Reader`. This will
20 /// work best with an infinite reader, but this is not required.
21 ///
22 /// It will fail if it there is insufficient data to fulfill a request.
23 ///
24 /// # Example
25 ///
26 /// ```rust
27 /// use std::rand::{reader, Rng};
28 /// use std::rt::io::mem;
29 ///
30 /// fn main() {
31 /// let mut rng = reader::ReaderRng::new(mem::MemReader::new(~[1,2,3,4,5,6,7,8]));
32 /// println!("{:x}", rng.gen::<uint>());
33 /// }
34 /// ```
35 pub struct ReaderRng<R> {
36 priv reader: R
37 }
38
39 impl<R: Reader> ReaderRng<R> {
40 /// Create a new `ReaderRng` from a `Reader`.
41 pub fn new(r: R) -> ReaderRng<R> {
42 ReaderRng {
43 reader: r
44 }
45 }
46 }
47
48 impl<R: Reader> Rng for ReaderRng<R> {
49 fn next_u32(&mut self) -> u32 {
50 // This is designed for speed: reading a LE integer on a LE
51 // platform just involves blitting the bytes into the memory
52 // of the u32, similarly for BE on BE; avoiding byteswapping.
53 if cfg!(target_endian="little") {
54 self.reader.read_le_u32_()
55 } else {
56 self.reader.read_be_u32_()
57 }
58 }
59 fn next_u64(&mut self) -> u64 {
60 // see above for explanation.
61 if cfg!(target_endian="little") {
62 self.reader.read_le_u64_()
63 } else {
64 self.reader.read_be_u64_()
65 }
66 }
67 fn fill_bytes(&mut self, v: &mut [u8]) {
68 if v.len() == 0 { return }
69 match self.reader.read(v) {
70 Some(n) if n == v.len() => return,
71 Some(n) => fail2!("ReaderRng.fill_bytes could not fill buffer: \
72 read {} out of {} bytes.", n, v.len()),
73 None => fail2!("ReaderRng.fill_bytes reached eof.")
74 }
75 }
76 }
77
78 #[cfg(test)]
79 mod test {
80 use super::*;
81 use rt::io::mem::MemReader;
82 use cast;
83
84 #[test]
85 fn test_reader_rng_u64() {
86 // transmute from the target to avoid endianness concerns.
87 let v = ~[1u64, 2u64, 3u64];
88 let bytes: ~[u8] = unsafe {cast::transmute(v)};
89 let mut rng = ReaderRng::new(MemReader::new(bytes));
90
91 assert_eq!(rng.next_u64(), 1);
92 assert_eq!(rng.next_u64(), 2);
93 assert_eq!(rng.next_u64(), 3);
94 }
95 #[test]
96 fn test_reader_rng_u32() {
97 // transmute from the target to avoid endianness concerns.
98 let v = ~[1u32, 2u32, 3u32];
99 let bytes: ~[u8] = unsafe {cast::transmute(v)};
100 let mut rng = ReaderRng::new(MemReader::new(bytes));
101
102 assert_eq!(rng.next_u32(), 1);
103 assert_eq!(rng.next_u32(), 2);
104 assert_eq!(rng.next_u32(), 3);
105 }
106 #[test]
107 fn test_reader_rng_fill_bytes() {
108 let v = [1u8, 2, 3, 4, 5, 6, 7, 8];
109 let mut w = [0u8, .. 8];
110
111 let mut rng = ReaderRng::new(MemReader::new(v.to_owned()));
112 rng.fill_bytes(w);
113
114 assert_eq!(v, w);
115 }
116
117 #[test]
118 #[should_fail]
119 fn test_reader_rng_insufficient_bytes() {
120 let mut rng = ReaderRng::new(MemReader::new(~[]));
121 let mut v = [0u8, .. 3];
122 rng.fill_bytes(v);
123 }
124 }