27
27
//!
28
28
//! struct MyRngCore;
29
29
//!
30
+ //! #[derive(Eq, PartialEq, Default)]
31
+ //! pub struct Results([u64; 8]);
32
+ //!
33
+ //! // implement `AsRef<[u8]>`, `AsRef<[u32]>`, and `AsRef<[u64]>` for `Results`
34
+ //!
30
35
//! impl BlockRngCore for MyRngCore {
31
- //! type Results = [u8; 32] ;
36
+ //! type Results = Results ;
32
37
//!
33
38
//! fn generate(&mut self, results: &mut Self::Results) {
34
39
//! unimplemented!()
54
59
//! [`fill_bytes`]: RngCore::fill_bytes
55
60
56
61
use crate :: { CryptoRng , Error , RngCore , SeedableRng } ;
57
- use core:: convert:: { AsRef , TryInto } ;
62
+ use core:: convert:: AsRef ;
58
63
use core:: fmt;
59
64
#[ cfg( feature = "serde1" ) ]
60
65
use serde:: { Deserialize , Serialize } ;
@@ -67,10 +72,49 @@ use serde::{Deserialize, Serialize};
67
72
pub trait BlockRngCore {
68
73
/// Results type. This is the 'block' an RNG implementing `BlockRngCore`
69
74
/// generates, which will usually be an array like `[u8; 64]`.
70
- type Results : AsRef < [ u8 ] > + AsMut < [ u8 ] > + Default ;
75
+ type Results : AsRef < [ u8 ] > + AsRef < [ u32 ] > + AsRef < [ u64 ] > + Default + Sized ;
71
76
72
77
/// Generate a new block of results.
73
78
fn generate ( & mut self , results : & mut Self :: Results ) ;
79
+
80
+ /// Try to generate a new block of results.
81
+ #[ inline]
82
+ fn try_generate ( & mut self , results : & mut Self :: Results ) -> Result < ( ) , Error > {
83
+ self . generate ( results) ;
84
+ Ok ( ( ) )
85
+ }
86
+ }
87
+
88
+ #[ derive( Copy , Clone , Debug , Eq , PartialEq ) ]
89
+ enum IndexLevel {
90
+ Bit ,
91
+ Byte ,
92
+ U32 ,
93
+ U64 ,
94
+ }
95
+
96
+ impl IndexLevel {
97
+ #[ inline( always) ]
98
+ fn convert ( & mut self , index : usize , level : Self ) -> usize {
99
+ use IndexLevel :: * ;
100
+ let res = match ( * self , level) {
101
+ ( Bit , Bit ) | ( Byte , Byte ) | ( U32 , U32 ) | ( U64 , U64 ) => return index,
102
+ ( Bit , Byte ) => ( index / 8 ) + ( ( index & 0b111 ) != 0 ) as usize ,
103
+ ( Bit , U32 ) => ( index / 32 ) + ( ( index & 0b1_1111 ) != 0 ) as usize ,
104
+ ( Bit , U64 ) => ( index / 64 ) + ( ( index & 0b11_1111 ) != 0 ) as usize ,
105
+ ( Byte , Bit ) => 8 * index,
106
+ ( Byte , U32 ) => ( index / 4 ) + ( ( index & 0b11 ) != 0 ) as usize ,
107
+ ( Byte , U64 ) => ( index / 8 ) + ( ( index & 0b111 ) != 0 ) as usize ,
108
+ ( U32 , Bit ) => 32 * index,
109
+ ( U32 , Byte ) => 4 * index,
110
+ ( U32 , U64 ) => ( index / 2 ) + ( ( index & 0b1 ) != 0 ) as usize ,
111
+ ( U64 , Bit ) => 64 * index,
112
+ ( U64 , Byte ) => 8 * index,
113
+ ( U64 , U32 ) => 2 * index,
114
+ } ;
115
+ * self = level;
116
+ res
117
+ }
74
118
}
75
119
76
120
/// A wrapper type implementing [`RngCore`] for some type implementing
@@ -110,11 +154,12 @@ pub trait BlockRngCore {
110
154
/// [`try_fill_bytes`]: RngCore::try_fill_bytes
111
155
#[ derive( Clone , Eq , PartialEq ) ]
112
156
#[ cfg_attr( feature = "serde1" , derive( Serialize , Deserialize ) ) ]
113
- pub struct BlockRng < R : BlockRngCore + ?Sized > {
114
- results : R :: Results ,
115
- index : usize ,
157
+ pub struct BlockRng < R : BlockRngCore + Sized > {
116
158
/// The *core* part of the RNG, implementing the `generate` function.
117
159
pub core : R ,
160
+ results : R :: Results ,
161
+ index : usize ,
162
+ level : IndexLevel ,
118
163
}
119
164
120
165
// Custom Debug implementation that does not expose the contents of `results`.
@@ -133,76 +178,96 @@ impl<R: BlockRngCore> BlockRng<R> {
133
178
/// `BlockRngCore`. Results will be generated on first use.
134
179
#[ inline]
135
180
pub fn new ( core : R ) -> BlockRng < R > {
136
- let results_empty = R :: Results :: default ( ) ;
137
- BlockRng {
138
- core,
139
- index : 8 * results_empty. as_ref ( ) . len ( ) ,
140
- results : results_empty,
141
- }
181
+ let results = R :: Results :: default ( ) ;
182
+ let index = AsRef :: < [ u8 ] > :: as_ref ( & results) . len ( ) ;
183
+ BlockRng { core, results, index, level : IndexLevel :: Byte }
184
+ }
185
+
186
+ #[ inline( always) ]
187
+ fn get_results_u8 ( & self ) -> & [ u8 ] {
188
+ AsRef :: < [ u8 ] > :: as_ref ( & self . results )
189
+ }
190
+
191
+ #[ inline( always) ]
192
+ fn get_results_u32 ( & self ) -> & [ u32 ] {
193
+ AsRef :: < [ u32 ] > :: as_ref ( & self . results )
194
+ }
195
+
196
+ #[ inline( always) ]
197
+ fn get_results_u64 ( & self ) -> & [ u64 ] {
198
+ AsRef :: < [ u64 ] > :: as_ref ( & self . results )
142
199
}
143
200
}
144
201
145
202
impl < R : BlockRngCore > RngCore for BlockRng < R >
146
203
where
147
- <R as BlockRngCore >:: Results : AsRef < [ u8 ] > + AsMut < [ u8 ] > ,
204
+ <R as BlockRngCore >:: Results : AsRef < [ u8 ] > + AsRef < [ u32 ] > + AsRef < [ u64 ] > + Default + Sized ,
148
205
{
149
206
#[ inline]
150
207
fn next_bool ( & mut self ) -> bool {
151
- let mut index = self . index ;
152
-
153
- if index / 8 >= self . results . as_ref ( ) . len ( ) {
154
- self . core . generate ( & mut self . results ) ;
155
- index = 0 ;
208
+ let index = self . level . convert ( self . index , IndexLevel :: Bit ) ;
209
+ match self . get_results_u8 ( ) . get ( index / 8 ) {
210
+ Some ( & v) => {
211
+ self . index = index + 1 ;
212
+ ( v >> ( index % 8 ) & 1 ) != 0
213
+ }
214
+ None => {
215
+ self . core . generate ( & mut self . results ) ;
216
+ self . index = 1 ;
217
+ ( self . get_results_u8 ( ) [ 0 ] & 1 ) != 0
218
+ }
156
219
}
157
-
158
- let res = ( self . results . as_ref ( ) [ index / 8 ] >> ( index % 8 ) ) & 0b1 != 0 ;
159
- self . index = index + 1 ;
160
- res
161
220
}
162
221
163
222
#[ inline]
164
223
fn next_u32 ( & mut self ) -> u32 {
165
- let mut index = self . index ;
166
- index = 4 * ( ( index / 32 ) + ( ( index & 0b1_1111 ) != 0 ) as usize ) ;
167
-
168
- if index + 4 > self . results . as_ref ( ) . len ( ) {
169
- self . core . generate ( & mut self . results ) ;
170
- index = 0 ;
224
+ let index = self . level . convert ( self . index , IndexLevel :: U32 ) ;
225
+ match self . get_results_u32 ( ) . get ( index) {
226
+ Some ( & v) => {
227
+ self . index = index + 1 ;
228
+ v
229
+ }
230
+ None => {
231
+ self . core . generate ( & mut self . results ) ;
232
+ self . index = 1 ;
233
+ self . get_results_u32 ( ) [ 0 ]
234
+ }
171
235
}
172
-
173
- let buf = self . results . as_ref ( ) [ index..index + 4 ] . try_into ( ) . unwrap ( ) ;
174
- self . index = 8 * ( index + 4 ) ;
175
- u32:: from_le_bytes ( buf)
176
236
}
177
237
178
238
#[ inline]
179
239
fn next_u64 ( & mut self ) -> u64 {
180
- let mut index = self . index ;
181
- index = 8 * ( ( index / 64 ) + ( ( index & 0b11_1111 ) != 0 ) as usize ) ;
182
-
183
- if index + 8 > self . results . as_ref ( ) . len ( ) {
184
- self . core . generate ( & mut self . results ) ;
185
- index = 0 ;
240
+ let index = self . level . convert ( self . index , IndexLevel :: U64 ) ;
241
+ match self . get_results_u64 ( ) . get ( index) {
242
+ Some ( & v) => {
243
+ self . index = index + 1 ;
244
+ v
245
+ }
246
+ None => {
247
+ self . core . generate ( & mut self . results ) ;
248
+ self . index = 1 ;
249
+ self . get_results_u64 ( ) [ 0 ]
250
+ }
186
251
}
252
+ }
187
253
188
- let buf = self . results . as_ref ( ) [ index..index + 8 ] . try_into ( ) . unwrap ( ) ;
189
- self . index = 8 * ( index + 8 ) ;
190
- u64 :: from_le_bytes ( buf )
254
+ # [ inline ]
255
+ fn fill_bytes ( & mut self , dest : & mut [ u8 ] ) {
256
+ self . try_fill_bytes ( dest ) . unwrap ( ) ;
191
257
}
192
258
193
259
#[ inline]
194
- fn fill_bytes ( & mut self , mut dest : & mut [ u8 ] ) {
195
- let mut index = self . index ;
196
- index = ( index / 8 ) + ( ( index & 0b111 ) != 0 ) as usize ;
260
+ fn try_fill_bytes ( & mut self , mut dest : & mut [ u8 ] ) -> Result < ( ) , Error > {
261
+ let index = self . level . convert ( self . index , IndexLevel :: Byte ) ;
197
262
198
- let rlen = self . results . as_ref ( ) . len ( ) ;
263
+ let rlen = self . get_results_u8 ( ) . len ( ) ;
199
264
if index < rlen {
200
265
let dlen = dest. len ( ) ;
201
- let res = self . results . as_ref ( ) ;
266
+ let res = self . get_results_u8 ( ) ;
202
267
if dlen <= rlen - index {
203
268
dest. copy_from_slice ( & res[ index..index + dlen] ) ;
204
- self . index = 8 * ( index + dlen) ;
205
- return ;
269
+ self . index = index + dlen;
270
+ return Ok ( ( ) ) ;
206
271
} else {
207
272
let ( l, r) = dest. split_at_mut ( rlen - index) ;
208
273
l. copy_from_slice ( & res[ index..] ) ;
@@ -211,26 +276,20 @@ where
211
276
}
212
277
213
278
let mut chunks = dest. chunks_exact_mut ( rlen) ;
214
-
215
279
for chunk in & mut chunks {
216
280
let mut buf = R :: Results :: default ( ) ;
217
- self . core . generate ( & mut buf) ;
281
+ self . core . try_generate ( & mut buf) ? ;
218
282
chunk. copy_from_slice ( buf. as_ref ( ) ) ;
219
283
}
220
284
221
285
let rem = chunks. into_remainder ( ) ;
222
286
if !rem. is_empty ( ) {
223
- self . core . generate ( & mut self . results ) ;
224
- rem. copy_from_slice ( & self . results . as_ref ( ) [ ..rem. len ( ) ] ) ;
225
- self . index = 8 * rem. len ( ) ;
287
+ self . core . try_generate ( & mut self . results ) ? ;
288
+ rem. copy_from_slice ( & self . get_results_u8 ( ) [ ..rem. len ( ) ] ) ;
289
+ self . index = rem. len ( ) ;
226
290
} else {
227
- self . index = 8 * rlen;
291
+ self . index = rlen;
228
292
}
229
- }
230
-
231
- #[ inline( always) ]
232
- fn try_fill_bytes ( & mut self , dest : & mut [ u8 ] ) -> Result < ( ) , Error > {
233
- self . fill_bytes ( dest) ;
234
293
Ok ( ( ) )
235
294
}
236
295
}
0 commit comments