Skip to content

Commit c34a6e4

Browse files
committed
EntropyRng: revise EntropySource trait and use macro
1 parent af8aa52 commit c34a6e4

File tree

1 file changed

+52
-72
lines changed

1 file changed

+52
-72
lines changed

src/rngs/entropy.rs

+52-72
Original file line numberDiff line numberDiff line change
@@ -91,65 +91,37 @@ impl RngCore for EntropyRng {
9191

9292
fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
9393
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+
}
112119
}
113120
}
114121

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);
153125

154126
if let Some(err) = reported_error {
155127
Err(Error::with_cause(ErrorKind::Unavailable,
@@ -167,12 +139,19 @@ impl CryptoRng for EntropyRng {}
167139

168140

169141
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
173154
fn fill(&mut self, dest: &mut [u8]) -> Result<(), Error>;
174-
175-
fn is_supported() -> bool { true }
176155
}
177156

178157
#[allow(unused)]
@@ -181,15 +160,16 @@ struct NoSource;
181160

182161
#[allow(unused)]
183162
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> {
185167
Err(Error::new(ErrorKind::Unavailable, "Source not supported"))
186168
}
187169

188170
fn fill(&mut self, dest: &mut [u8]) -> Result<(), Error> {
189171
unreachable!()
190172
}
191-
192-
fn is_supported() -> bool { false }
193173
}
194174

195175

@@ -231,10 +211,10 @@ pub struct Os(rngs::OsRng);
231211
all(target_arch = "wasm32", feature = "wasm-bindgen"),
232212
)))]
233213
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()?))
238218
}
239219

240220
fn fill(&mut self, dest: &mut [u8]) -> Result<(), Error> {
@@ -271,10 +251,10 @@ pub struct Jitter(rngs::JitterRng);
271251

272252
#[cfg(not(target_arch = "wasm32"))]
273253
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()?))
278258
}
279259

280260
fn fill(&mut self, dest: &mut [u8]) -> Result<(), Error> {

0 commit comments

Comments
 (0)