@@ -91,65 +91,37 @@ impl RngCore for EntropyRng {
91
91
92
92
fn try_fill_bytes ( & mut self , dest : & mut [ u8 ] ) -> Result < ( ) , Error > {
93
93
let mut reported_error = None ;
94
-
95
- if let Source :: Os ( ref mut os_rng) = self . source {
96
- match os_rng. fill ( dest) {
97
- Ok ( ( ) ) => return Ok ( ( ) ) ,
98
- Err ( err) => {
99
- warn ! ( "EntropyRng: OsRng failed \
100
- [trying other entropy sources]: {}", err) ;
101
- reported_error = Some ( err) ;
102
- } ,
103
- }
104
- } else if Os :: is_supported ( ) {
105
- match Os :: new_and_fill ( dest) {
106
- Ok ( os_rng) => {
107
- debug ! ( "EntropyRng: using OsRng" ) ;
108
- self . source = Source :: Os ( os_rng) ;
109
- return Ok ( ( ) ) ;
110
- } ,
111
- Err ( err) => { reported_error = reported_error. or ( Some ( err) ) } ,
94
+
95
+ macro_rules! try_source {
96
+ ( $source: ident) => {
97
+ if let Source :: $source( ref mut inner) = self . source {
98
+ match inner. fill( dest) {
99
+ Ok ( ( ) ) => return Ok ( ( ) ) ,
100
+ Err ( err) => {
101
+ warn!( "EntropyRng: source {} failed: {}" , $source:: name( ) , err) ;
102
+ reported_error = Some ( err) ;
103
+ } ,
104
+ }
105
+ } else if $source:: is_available( ) {
106
+ match $source:: new( ) . and_then( |mut inner|
107
+ inner. fill( dest) . and( Ok ( inner) ) )
108
+ {
109
+ Ok ( inner) => {
110
+ debug!( "EntropyRng: using source {}" , $source:: name( ) ) ;
111
+ self . source = Source :: $source( inner) ;
112
+ return Ok ( ( ) ) ;
113
+ } ,
114
+ Err ( err) => {
115
+ reported_error = reported_error. or( Some ( err) ) ;
116
+ } ,
117
+ }
118
+ }
112
119
}
113
120
}
114
121
115
- if let Source :: Custom ( ref mut rng) = self . source {
116
- match rng. fill ( dest) {
117
- Ok ( ( ) ) => return Ok ( ( ) ) ,
118
- Err ( err) => {
119
- warn ! ( "EntropyRng: custom entropy source failed \
120
- [trying other entropy sources]: {}", err) ;
121
- reported_error = Some ( err) ;
122
- } ,
123
- }
124
- } else if Custom :: is_supported ( ) {
125
- match Custom :: new_and_fill ( dest) {
126
- Ok ( custom) => {
127
- debug ! ( "EntropyRng: using custom entropy source" ) ;
128
- self . source = Source :: Custom ( custom) ;
129
- return Ok ( ( ) ) ;
130
- } ,
131
- Err ( err) => { reported_error = reported_error. or ( Some ( err) ) } ,
132
- }
133
- }
134
-
135
- if let Source :: Jitter ( ref mut jitter_rng) = self . source {
136
- match jitter_rng. fill ( dest) {
137
- Ok ( ( ) ) => return Ok ( ( ) ) ,
138
- Err ( err) => {
139
- warn ! ( "EntropyRng: JitterRng failed: {}" , err) ;
140
- reported_error = Some ( err) ;
141
- } ,
142
- }
143
- } else if Jitter :: is_supported ( ) {
144
- match Jitter :: new_and_fill ( dest) {
145
- Ok ( jitter_rng) => {
146
- debug ! ( "EntropyRng: using JitterRng" ) ;
147
- self . source = Source :: Jitter ( jitter_rng) ;
148
- return Ok ( ( ) ) ;
149
- } ,
150
- Err ( err) => { reported_error = reported_error. or ( Some ( err) ) } ,
151
- }
152
- }
122
+ try_source ! ( Os ) ;
123
+ try_source ! ( Custom ) ;
124
+ try_source ! ( Jitter ) ;
153
125
154
126
if let Some ( err) = reported_error {
155
127
Err ( Error :: with_cause ( ErrorKind :: Unavailable ,
@@ -167,12 +139,19 @@ impl CryptoRng for EntropyRng {}
167
139
168
140
169
141
trait EntropySource {
170
- fn new_and_fill ( dest : & mut [ u8 ] ) -> Result < Self , Error >
171
- where Self : Sized ;
172
-
142
+ /// Name of this source
143
+ fn name ( ) -> & ' static str ;
144
+
145
+ /// Is this source available?
146
+ ///
147
+ /// The default implementation returns `true`.
148
+ fn is_available ( ) -> bool { true }
149
+
150
+ /// Create an instance
151
+ fn new ( ) -> Result < Self , Error > where Self : Sized ;
152
+
153
+ /// Fill `dest` with random data from the entropy source
173
154
fn fill ( & mut self , dest : & mut [ u8 ] ) -> Result < ( ) , Error > ;
174
-
175
- fn is_supported ( ) -> bool { true }
176
155
}
177
156
178
157
#[ allow( unused) ]
@@ -181,15 +160,16 @@ struct NoSource;
181
160
182
161
#[ allow( unused) ]
183
162
impl EntropySource for NoSource {
184
- fn new_and_fill ( dest : & mut [ u8 ] ) -> Result < Self , Error > {
163
+ fn name ( ) -> & ' static str { unreachable ! ( ) }
164
+ fn is_available ( ) -> bool { false }
165
+
166
+ fn new ( ) -> Result < Self , Error > {
185
167
Err ( Error :: new ( ErrorKind :: Unavailable , "Source not supported" ) )
186
168
}
187
169
188
170
fn fill ( & mut self , dest : & mut [ u8 ] ) -> Result < ( ) , Error > {
189
171
unreachable ! ( )
190
172
}
191
-
192
- fn is_supported ( ) -> bool { false }
193
173
}
194
174
195
175
@@ -231,10 +211,10 @@ pub struct Os(rngs::OsRng);
231
211
all( target_arch = "wasm32" , feature = "wasm-bindgen" ) ,
232
212
) ) ) ]
233
213
impl EntropySource for Os {
234
- fn new_and_fill ( dest : & mut [ u8 ] ) -> Result < Self , Error > {
235
- let mut rng = rngs :: OsRng :: new ( ) ? ;
236
- rng . try_fill_bytes ( dest ) ? ;
237
- Ok ( Os ( rng ) )
214
+ fn name ( ) -> & ' static str { "OsRng" }
215
+
216
+ fn new ( ) -> Result < Self , Error > {
217
+ Ok ( Os ( rngs :: OsRng :: new ( ) ? ) )
238
218
}
239
219
240
220
fn fill ( & mut self , dest : & mut [ u8 ] ) -> Result < ( ) , Error > {
@@ -271,10 +251,10 @@ pub struct Jitter(rngs::JitterRng);
271
251
272
252
#[ cfg( not( target_arch = "wasm32" ) ) ]
273
253
impl EntropySource for Jitter {
274
- fn new_and_fill ( dest : & mut [ u8 ] ) -> Result < Self , Error > {
275
- let mut rng = rngs :: JitterRng :: new ( ) ? ;
276
- rng . try_fill_bytes ( dest ) ? ;
277
- Ok ( Jitter ( rng ) )
254
+ fn name ( ) -> & ' static str { "JitterRng" }
255
+
256
+ fn new ( ) -> Result < Self , Error > {
257
+ Ok ( Jitter ( rngs :: JitterRng :: new ( ) ? ) )
278
258
}
279
259
280
260
fn fill ( & mut self , dest : & mut [ u8 ] ) -> Result < ( ) , Error > {
0 commit comments