20
20
//! `SeedFromRng` and `SeedableRng` are extension traits for construction and
21
21
//! reseeding.
22
22
//!
23
- //! `Error` and `Result` are provided for error-handling. They are safe to use
24
- //! in `no_std` environments.
23
+ //! `Error` is provided for error-handling. It is safe to use in `no_std`
24
+ //! environments.
25
25
//!
26
26
//! The `impls` sub-module includes a few small functions to assist
27
27
//! implementation of `Rng`. Since this module is only of interest to `Rng`
43
43
#[ cfg( feature="std" ) ]
44
44
extern crate core;
45
45
46
+ use core:: fmt;
47
+
46
48
pub mod impls;
47
49
pub mod mock;
48
50
@@ -89,16 +91,29 @@ pub trait Rng {
89
91
/// Return the next random u128.
90
92
#[ cfg( feature = "i128_support" ) ]
91
93
fn next_u128 ( & mut self ) -> u128 ;
92
-
94
+
95
+ /// Fill `dest` entirely with random data.
96
+ ///
97
+ /// This method does *not* have any requirement on how much of the
98
+ /// generated random number stream is consumed; e.g. `fill_bytes_via_u64`
99
+ /// implementation uses `next_u64` thus consuming 8 bytes even when only
100
+ /// 1 is required. A different implementation might use `next_u32` and
101
+ /// only consume 4 bytes; *however* any change affecting *reproducibility*
102
+ /// of output must be considered a breaking change.
103
+ fn fill_bytes ( & mut self , dest : & mut [ u8 ] ) ;
104
+
93
105
/// Fill `dest` entirely with random data.
94
106
///
107
+ /// If a RNG can encounter an error, this is the only method that reports
108
+ /// it. The other methods either handle the error, or panic.
109
+ ///
95
110
/// This method does *not* have any requirement on how much of the
96
111
/// generated random number stream is consumed; e.g. `try_fill_via_u64`
97
112
/// implementation uses `next_u64` thus consuming 8 bytes even when only
98
113
/// 1 is required. A different implementation might use `next_u32` and
99
114
/// only consume 4 bytes; *however* any change affecting *reproducibility*
100
115
/// of output must be considered a breaking change.
101
- fn try_fill ( & mut self , dest : & mut [ u8 ] ) -> Result < ( ) > ;
116
+ fn try_fill ( & mut self , dest : & mut [ u8 ] ) -> Result < ( ) , Error > ;
102
117
}
103
118
104
119
impl < ' a , R : Rng +?Sized > Rng for & ' a mut R {
@@ -115,7 +130,11 @@ impl<'a, R: Rng+?Sized> Rng for &'a mut R {
115
130
( * * self ) . next_u128 ( )
116
131
}
117
132
118
- fn try_fill ( & mut self , dest : & mut [ u8 ] ) -> Result < ( ) > {
133
+ fn fill_bytes ( & mut self , dest : & mut [ u8 ] ) {
134
+ ( * * self ) . fill_bytes ( dest)
135
+ }
136
+
137
+ fn try_fill ( & mut self , dest : & mut [ u8 ] ) -> Result < ( ) , Error > {
119
138
( * * self ) . try_fill ( dest)
120
139
}
121
140
}
@@ -135,7 +154,11 @@ impl<R: Rng+?Sized> Rng for Box<R> {
135
154
( * * self ) . next_u128 ( )
136
155
}
137
156
138
- fn try_fill ( & mut self , dest : & mut [ u8 ] ) -> Result < ( ) > {
157
+ fn fill_bytes ( & mut self , dest : & mut [ u8 ] ) {
158
+ ( * * self ) . fill_bytes ( dest)
159
+ }
160
+
161
+ fn try_fill ( & mut self , dest : & mut [ u8 ] ) -> Result < ( ) , Error > {
139
162
( * * self ) . try_fill ( dest)
140
163
}
141
164
}
@@ -158,10 +181,9 @@ pub trait SeedFromRng: Sized {
158
181
/// hand, seeding a simple numerical generator from another of the same
159
182
/// type sometimes has serious side effects such as effectively cloning the
160
183
/// generator.
161
- fn from_rng < R : Rng +?Sized > ( rng : & mut R ) -> Result < Self > ;
184
+ fn from_rng < R : Rng +?Sized > ( rng : & mut R ) -> Result < Self , Error > ;
162
185
}
163
186
164
-
165
187
/// A random number generator that can be explicitly seeded to produce
166
188
/// the same stream of randomness multiple times.
167
189
///
@@ -180,21 +202,71 @@ pub trait SeedableRng<Seed>: Rng {
180
202
}
181
203
182
204
183
- /// Error type for cryptographic generators. Technically external generators
184
- /// such as the operating system or hardware generators could fail. A PRNG
185
- /// (algorithm) could also fail if it detects cycles, though most PRNGs have
186
- /// sufficiently long cycles that looping is not usually feasible.
187
- ///
188
- /// TODO: how should error details be reported?
189
- #[ derive( Debug ) ]
190
- pub struct Error ;
205
+ /// Error kind which can be matched over.
206
+ #[ derive( PartialEq , Eq , Debug , Copy , Clone ) ]
207
+ pub enum ErrorKind {
208
+ /// Permanent failure: likely not recoverable without user action.
209
+ Unavailable ,
210
+ /// Temporary failure: recommended to retry a few times, but may also be
211
+ /// irrecoverable.
212
+ Transient ,
213
+ /// Not ready yet: recommended to try again a little later.
214
+ NotReady ,
215
+ /// Uncategorised error
216
+ Other ,
217
+ #[ doc( hidden) ]
218
+ __Nonexhaustive,
219
+ }
191
220
192
221
#[ cfg( feature="std" ) ]
193
- impl From < :: std:: io:: Error > for Error {
194
- fn from ( _: :: std:: io:: Error ) -> Error {
195
- Error
222
+ #[ derive( Debug ) ]
223
+ pub struct Error {
224
+ pub kind : ErrorKind ,
225
+ pub cause : Option < Box < std:: error:: Error > > ,
226
+ }
227
+
228
+ #[ cfg( not( feature="std" ) ) ]
229
+ #[ derive( Debug , Clone , PartialEq , Eq ) ]
230
+ pub struct Error {
231
+ pub kind : ErrorKind ,
232
+ pub cause : Option < & ' static str > ,
233
+ }
234
+
235
+ impl Error {
236
+ #[ cfg( feature="std" ) ]
237
+ pub fn new ( kind : ErrorKind , cause : Option < Box < std:: error:: Error > > ) -> Error {
238
+ Error {
239
+ kind : kind,
240
+ cause : cause,
241
+ }
196
242
}
197
243
}
198
244
199
- /// Result type (convenience type-def)
200
- pub type Result < T > = :: std:: result:: Result < T , Error > ;
245
+ impl fmt:: Display for Error {
246
+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
247
+ match self . kind {
248
+ ErrorKind :: Unavailable => write ! ( f, "RNG not available." ) ,
249
+ ErrorKind :: Transient => write ! ( f, "RNG has failed, probably temporary." ) ,
250
+ ErrorKind :: NotReady => write ! ( f, "RNG not ready yet." ) ,
251
+ ErrorKind :: Other => write ! ( f, "An unspecified RNG error occurred." ) ,
252
+ ErrorKind :: __Nonexhaustive => unreachable ! ( ) ,
253
+ }
254
+ }
255
+ }
256
+
257
+ #[ cfg( feature="std" ) ]
258
+ impl :: std:: error:: Error for Error {
259
+ fn description ( & self ) -> & str {
260
+ match self . kind {
261
+ ErrorKind :: Unavailable => "not available" ,
262
+ ErrorKind :: Transient => "temporary failure" ,
263
+ ErrorKind :: NotReady => "not ready yet" ,
264
+ ErrorKind :: Other => "Uncategorised rng error" ,
265
+ ErrorKind :: __Nonexhaustive => unreachable ! ( ) ,
266
+ }
267
+ }
268
+
269
+ fn cause ( & self ) -> Option < & :: std:: error:: Error > {
270
+ self . cause . as_ref ( ) . map ( |e| & * * e)
271
+ }
272
+ }
0 commit comments