@@ -44,24 +44,24 @@ fn main () {
44
44
*/
45
45
46
46
use cast;
47
- use cmp;
48
47
use container:: Container ;
49
48
use int;
50
- use iter:: { Iterator , range, range_step } ;
49
+ use iter:: { Iterator , range} ;
51
50
use local_data;
52
51
use prelude:: * ;
53
52
use str;
54
- use sys;
55
53
use u32;
56
54
use u64;
57
55
use uint;
58
56
use vec;
59
- use libc:: size_t;
60
57
61
58
pub use self :: isaac:: { IsaacRng , Isaac64Rng } ;
59
+ pub use self :: os:: OSRng ;
62
60
63
61
pub mod distributions;
64
62
pub mod isaac;
63
+ pub mod os;
64
+ pub mod reader;
65
65
66
66
/// A type that can be randomly generated using an Rng
67
67
pub trait Rand {
@@ -233,15 +233,6 @@ impl<T: Rand + 'static> Rand for @T {
233
233
fn rand < R : Rng > ( rng : & mut R ) -> @T { @rng. gen ( ) }
234
234
}
235
235
236
- #[ abi = "cdecl" ]
237
- pub mod rustrt {
238
- use libc:: size_t;
239
-
240
- extern {
241
- pub fn rand_gen_seed ( buf : * mut u8 , sz : size_t ) ;
242
- }
243
- }
244
-
245
236
/// A value with a particular weight compared to other values
246
237
pub struct Weighted < T > {
247
238
/// The numerical weight of this item
@@ -252,7 +243,8 @@ pub struct Weighted<T> {
252
243
253
244
/// A random number generator
254
245
pub trait Rng {
255
- /// Return the next random u32.
246
+ /// Return the next random u32. This rarely needs to be called
247
+ /// directly, prefer `r.gen()` to `r.next_u32()`.
256
248
///
257
249
/// By default this is implemented in terms of `next_u64`. An
258
250
/// implementation of this trait must provide at least one of
@@ -261,7 +253,8 @@ pub trait Rng {
261
253
self . next_u64 ( ) as u32
262
254
}
263
255
264
- /// Return the next random u64.
256
+ /// Return the next random u64. This rarely needs to be called
257
+ /// directly, prefer `r.gen()` to `r.next_u64()`.
265
258
///
266
259
/// By default this is implemented in terms of `next_u32`. An
267
260
/// implementation of this trait must provide at least one of
@@ -270,6 +263,76 @@ pub trait Rng {
270
263
( self . next_u32 ( ) as u64 << 32 ) | ( self . next_u32 ( ) as u64 )
271
264
}
272
265
266
+ /// Fill `dest` with random data.
267
+ ///
268
+ /// This has a default implementation in terms of `next_u64` and
269
+ /// `next_u32`, but should be overriden by implementations that
270
+ /// offer a more efficient solution than just calling those
271
+ /// methods repeatedly.
272
+ ///
273
+ /// This method does *not* have a requirement to bear any fixed
274
+ /// relationship to the other methods, for example, it does *not*
275
+ /// have to result in the same output as progressively filling
276
+ /// `dest` with `self.gen::<u8>()`, and any such behaviour should
277
+ /// not be relied upon.
278
+ ///
279
+ /// This method should guarantee that `dest` is entirely filled
280
+ /// with new data, and may fail if this is impossible
281
+ /// (e.g. reading past the end of a file that is being used as the
282
+ /// source of randomness).
283
+ ///
284
+ /// # Example
285
+ ///
286
+ /// ~~~{.rust}
287
+ /// use std::rand::{task_rng, Rng};
288
+ ///
289
+ /// fn main() {
290
+ /// let mut v = [0u8, .. 13579];
291
+ /// task_rng().fill_bytes(v);
292
+ /// printfln!(v);
293
+ /// }
294
+ /// ~~~
295
+ fn fill_bytes ( & mut self , mut dest : & mut [ u8 ] ) {
296
+ // this relies on the lengths being transferred correctly when
297
+ // transmuting between vectors like this.
298
+ let as_u64: & mut & mut [ u64 ] = unsafe { cast:: transmute ( & mut dest) } ;
299
+ for dest in as_u64. mut_iter ( ) {
300
+ * dest = self . next_u64 ( ) ;
301
+ }
302
+
303
+ // the above will have filled up the vector as much as
304
+ // possible in multiples of 8 bytes.
305
+ let mut remaining = dest. len ( ) % 8 ;
306
+
307
+ // space for a u32
308
+ if remaining >= 4 {
309
+ let as_u32: & mut & mut [ u32 ] = unsafe { cast:: transmute ( & mut dest) } ;
310
+ as_u32[ as_u32. len ( ) - 1 ] = self . next_u32 ( ) ;
311
+ remaining -= 4 ;
312
+ }
313
+ // exactly filled
314
+ if remaining == 0 { return }
315
+
316
+ // now we know we've either got 1, 2 or 3 spots to go,
317
+ // i.e. exactly one u32 is enough.
318
+ let rand = self . next_u32 ( ) ;
319
+ let remaining_index = dest. len ( ) - remaining;
320
+ match dest. mut_slice_from ( remaining_index) {
321
+ [ ref mut a] => {
322
+ * a = rand as u8 ;
323
+ }
324
+ [ ref mut a, ref mut b] => {
325
+ * a = rand as u8 ;
326
+ * b = ( rand >> 8 ) as u8 ;
327
+ }
328
+ [ ref mut a, ref mut b, ref mut c] => {
329
+ * a = rand as u8 ;
330
+ * b = ( rand >> 8 ) as u8 ;
331
+ * c = ( rand >> 16 ) as u8 ;
332
+ }
333
+ _ => fail2 ! ( "Rng.fill_bytes: the impossible occurred: remaining != 1, 2 or 3" )
334
+ }
335
+ }
273
336
274
337
/// Return a random value of a Rand type.
275
338
///
@@ -630,11 +693,9 @@ impl XorShiftRng {
630
693
// specific size, so we can just use a fixed buffer.
631
694
let mut s = [ 0u8 , ..16 ] ;
632
695
loop {
633
- do s. as_mut_buf |p, sz| {
634
- unsafe {
635
- rustrt:: rand_gen_seed ( p, sz as size_t ) ;
636
- }
637
- }
696
+ let mut r = OSRng :: new ( ) ;
697
+ r. fill_bytes ( s) ;
698
+
638
699
if !s. iter ( ) . all ( |x| * x == 0 ) {
639
700
break ;
640
701
}
@@ -660,15 +721,10 @@ impl XorShiftRng {
660
721
661
722
/// Create a new random seed of length `n`.
662
723
pub fn seed ( n : uint ) -> ~[ u8 ] {
663
- #[ fixed_stack_segment] ; #[ inline( never) ] ;
664
-
665
- unsafe {
666
- let mut s = vec:: from_elem ( n as uint , 0_u8 ) ;
667
- do s. as_mut_buf |p, sz| {
668
- rustrt:: rand_gen_seed ( p, sz as size_t )
669
- }
670
- s
671
- }
724
+ let mut s = vec:: from_elem ( n as uint , 0_u8 ) ;
725
+ let mut r = OSRng :: new ( ) ;
726
+ r. fill_bytes ( s) ;
727
+ s
672
728
}
673
729
674
730
// used to make space in TLS for a random number generator
@@ -719,6 +775,14 @@ mod test {
719
775
use option:: { Option , Some } ;
720
776
use super :: * ;
721
777
778
+ #[ test]
779
+ fn test_fill_bytes_default ( ) {
780
+ let mut r = weak_rng ( ) ;
781
+
782
+ let mut v = [ 0u8 , .. 100 ] ;
783
+ r. fill_bytes ( v) ;
784
+ }
785
+
722
786
#[ test]
723
787
fn test_gen_integer_range ( ) {
724
788
let mut r = rng ( ) ;
0 commit comments