Skip to content

Commit 7a07c36

Browse files
committed
Rename to EntropyRng and make new infallible
1 parent 29170c2 commit 7a07c36

File tree

1 file changed

+70
-58
lines changed

1 file changed

+70
-58
lines changed

src/lib.rs

+70-58
Original file line numberDiff line numberDiff line change
@@ -830,8 +830,7 @@ pub trait NewRng: SeedableRng {
830830
#[cfg(feature="std")]
831831
impl<R: SeedableRng> NewRng for R {
832832
fn new() -> Result<Self, Error> {
833-
let mut source = EntropySource::new()?;
834-
R::from_rng(&mut source)
833+
R::from_rng(EntropyRng::new())
835834
}
836835
}
837836

@@ -929,15 +928,14 @@ pub fn weak_rng() -> XorShiftRng {
929928
#[cfg(feature="std")]
930929
#[derive(Clone, Debug)]
931930
pub struct ThreadRng {
932-
rng: Rc<RefCell<ReseedingRng<StdRng, EntropySource>>>,
931+
rng: Rc<RefCell<ReseedingRng<StdRng, EntropyRng>>>,
933932
}
934933

935934
#[cfg(feature="std")]
936935
thread_local!(
937-
static THREAD_RNG_KEY: Rc<RefCell<ReseedingRng<StdRng, EntropySource>>> = {
936+
static THREAD_RNG_KEY: Rc<RefCell<ReseedingRng<StdRng, EntropyRng>>> = {
938937
const THREAD_RNG_RESEED_THRESHOLD: u64 = 32_768;
939-
let mut entropy_source = EntropySource::new()
940-
.expect("could not initialize thread_rng");
938+
let mut entropy_source = EntropyRng::new();
941939
let r = StdRng::from_rng(&mut entropy_source)
942940
.expect("could not initialize thread_rng");
943941
let rng = ReseedingRng::new(r,
@@ -985,49 +983,42 @@ impl Rng for ThreadRng {
985983

986984
/// An RNG provided specifically for seeding PRNG's.
987985
///
988-
/// `EntropySource` uses the interface for random numbers provided by the
989-
/// operating system (`OsRng`). If that returns an error, it will fall back to
990-
/// the `JitterRng` entropy collector. Occasionally it will then check if
991-
/// `OsRng` is still not available, and switch back if possible.
986+
/// `EntropyRng` uses the interface for random numbers provided by the operating
987+
/// system ([`OsRng`]). If that returns an error, it will fall back to the
988+
/// [`JitterRng`] entropy collector. Occasionally it will then check if `OsRng`
989+
/// is still not available, and switch back if possible.
990+
///
991+
/// [`OsRng`]: os/struct.OsRng.html
992+
/// [`JitterRng`]: jitter/struct.JitterRng.html
992993
#[cfg(feature="std")]
993994
#[derive(Debug)]
994-
pub struct EntropySource {
995-
rng: EntropySourceInner,
995+
pub struct EntropyRng {
996+
rng: EntropySource,
996997
counter: u32,
997998
}
998999

9991000
#[cfg(feature="std")]
10001001
#[derive(Debug)]
1001-
enum EntropySourceInner {
1002+
enum EntropySource {
10021003
Os(OsRng),
10031004
Jitter(JitterRng),
1005+
None,
10041006
}
10051007

10061008
#[cfg(feature="std")]
1007-
impl EntropySource {
1008-
pub fn new() -> Result<Self, Error> {
1009-
match OsRng::new() {
1010-
Ok(r) =>
1011-
Ok(EntropySource { rng: EntropySourceInner::Os(r),
1012-
counter: 0u32 }),
1013-
Err(e1) => {
1014-
match JitterRng::new() {
1015-
Ok(r) =>
1016-
Ok(EntropySource { rng: EntropySourceInner::Jitter(r),
1017-
counter: 0 }),
1018-
Err(_) =>
1019-
Err(Error::with_cause(
1020-
ErrorKind::Unavailable,
1021-
"Both OS and Jitter entropy sources are unavailable",
1022-
e1))
1023-
}
1024-
}
1025-
}
1009+
impl EntropyRng {
1010+
/// Create a new `EntropyRng`.
1011+
///
1012+
/// This method will do no system calls or other initialization routines,
1013+
/// those are done on first use. This is done to make `new` infallible,
1014+
/// and `try_fill_bytes` the only place to report errors.
1015+
pub fn new() -> Self {
1016+
EntropyRng { rng: EntropySource::None, counter: 0u32 }
10261017
}
10271018
}
10281019

10291020
#[cfg(feature="std")]
1030-
impl Rng for EntropySource {
1021+
impl Rng for EntropyRng {
10311022
fn next_u32(&mut self) -> u32 {
10321023
impls::next_u32_via_fill(self)
10331024
}
@@ -1041,45 +1032,66 @@ impl Rng for EntropySource {
10411032
}
10421033

10431034
fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
1035+
fn try_os_new(dest: &mut [u8]) -> Result<OsRng, Error>
1036+
{
1037+
let mut rng = OsRng::new()?;
1038+
rng.try_fill_bytes(dest)?;
1039+
Ok(rng)
1040+
}
1041+
1042+
fn try_jitter_new(dest: &mut [u8]) -> Result<JitterRng, Error>
1043+
{
1044+
let mut rng = JitterRng::new()?;
1045+
rng.try_fill_bytes(dest)?;
1046+
Ok(rng)
1047+
}
1048+
10441049
let mut switch_rng = None;
1045-
let mut result;
10461050
match self.rng {
1047-
EntropySourceInner::Os(ref mut rng) => {
1048-
result = rng.try_fill_bytes(dest);
1049-
if result.is_err() {
1050-
// Fall back to JitterRng.
1051-
let mut rng2_result = JitterRng::new();
1052-
if let Ok(mut rng2) = rng2_result {
1053-
result = rng2.try_fill_bytes(dest); // Can't fail
1054-
switch_rng = Some(EntropySourceInner::Jitter(rng2));
1051+
EntropySource::None => {
1052+
let os_rng_result = try_os_new(dest);
1053+
match os_rng_result {
1054+
Ok(os_rng) => {
1055+
switch_rng = Some(EntropySource::Os(os_rng));
10551056
}
1056-
}
1057-
}
1058-
EntropySourceInner::Jitter(ref mut rng) => {
1059-
if self.counter < 8 {
1060-
result = rng.try_fill_bytes(dest); // use JitterRng
1061-
self.counter = (self.counter + 1) % 8;
1062-
} else {
1063-
// Try if OsRng is still unavailable
1064-
let os_rng_result = OsRng::new();
1065-
if let Ok(mut os_rng) = os_rng_result {
1066-
result = os_rng.try_fill_bytes(dest);
1067-
if result.is_ok() {
1068-
switch_rng = Some(EntropySourceInner::Os(os_rng));
1057+
Err(os_rng_error) => {
1058+
if let Ok(jitter_rng) = try_jitter_new(dest) {
1059+
switch_rng = Some(EntropySource::Jitter(jitter_rng));
10691060
} else {
1070-
result = rng.try_fill_bytes(dest); // use JitterRng
1061+
return Err(os_rng_error);
10711062
}
1063+
}
1064+
}
1065+
}
1066+
EntropySource::Os(ref mut rng) => {
1067+
let os_rng_result = rng.try_fill_bytes(dest);
1068+
if os_rng_result.is_err() {
1069+
if let Ok(jitter_rng) = try_jitter_new(dest) {
1070+
switch_rng = Some(EntropySource::Jitter(jitter_rng));
10721071
} else {
1073-
result = rng.try_fill_bytes(dest); // use JitterRng
1072+
return os_rng_result;
10741073
}
10751074
}
10761075
}
1076+
EntropySource::Jitter(ref mut rng) => {
1077+
if self.counter >= 8 {
1078+
if let Ok(os_rng) = try_os_new(dest) {
1079+
switch_rng = Some(EntropySource::Os(os_rng));
1080+
} else {
1081+
self.counter = (self.counter + 1) % 8;
1082+
return rng.try_fill_bytes(dest); // use JitterRng
1083+
}
1084+
} else {
1085+
self.counter = (self.counter + 1) % 8;
1086+
return rng.try_fill_bytes(dest); // use JitterRng
1087+
}
1088+
}
10771089
}
10781090
if let Some(rng) = switch_rng {
10791091
self.rng = rng;
10801092
self.counter = 0;
10811093
}
1082-
result
1094+
Ok(())
10831095
}
10841096
}
10851097

0 commit comments

Comments
 (0)