@@ -39,31 +39,45 @@ pub fn next_u64_via_u32<R: RngCore + ?Sized>(rng: &mut R) -> u64 {
39
39
40
40
macro_rules! fill_bytes_via {
41
41
( $rng: ident, $next_u: ident, $BYTES: expr, $dest: ident) => { {
42
+ // This method is optimized to only call `$next_u()` from one place in
43
+ // the loop, which helps to minimize the code size in combination with
44
+ // inlining. This has the consequence that if `$dest.len() == 0` it will
45
+ // also use a value from the RNG, instead of returning directly. We
46
+ // could handle it as a special case, but that could reduce the
47
+ // performance of all uses just to improve that of the non-sensical
48
+ // zero-length `$dest` scenario a little.
49
+ let remainder = $dest. len( ) % $BYTES;
50
+ let len = $dest. len( ) / $BYTES;
51
+
52
+ let mut read_len = 0 ;
42
53
let mut left = $dest;
43
- while left. len( ) >= $BYTES {
44
- let ( l, r) = { left} . split_at_mut( $BYTES) ;
45
- left = r;
46
- let chunk: [ u8 ; $BYTES] = unsafe {
54
+ let mut chunk: [ u8 ; $BYTES] ;
55
+ loop {
56
+ chunk = unsafe {
47
57
transmute( $rng. $next_u( ) . to_le( ) )
48
58
} ;
49
- l. copy_from_slice( & chunk) ;
59
+ if read_len < len {
60
+ let ( l, r) = { left} . split_at_mut( $BYTES) ;
61
+ left = r;
62
+ l. copy_from_slice( & chunk) ;
63
+ read_len += $BYTES;
64
+ }
65
+ if read_len == len { break ; }
50
66
}
51
- let n = left. len( ) ;
52
- if n > 0 {
53
- let chunk: [ u8 ; $BYTES] = unsafe {
54
- transmute( $rng. $next_u( ) . to_le( ) )
55
- } ;
56
- left. copy_from_slice( & chunk[ ..n] ) ;
67
+ if remainder > 0 {
68
+ left. copy_from_slice( & chunk[ ..remainder] ) ;
57
69
}
58
70
} }
59
71
}
60
72
61
73
/// Implement `fill_bytes` via `next_u32`, little-endian order.
74
+ #[ inline( always) ]
62
75
pub fn fill_bytes_via_u32 < R : RngCore + ?Sized > ( rng : & mut R , dest : & mut [ u8 ] ) {
63
76
fill_bytes_via ! ( rng, next_u32, 4 , dest)
64
77
}
65
78
66
79
/// Implement `fill_bytes` via `next_u64`, little-endian order.
80
+ #[ inline( always) ]
67
81
pub fn fill_bytes_via_u64 < R : RngCore + ?Sized > ( rng : & mut R , dest : & mut [ u8 ] ) {
68
82
fill_bytes_via ! ( rng, next_u64, 8 , dest)
69
83
}
0 commit comments