Skip to content

Commit

Permalink
Use Hc128 on Emscripten
Browse files Browse the repository at this point in the history
This is considered an ugly hack, but easier than making the new ChaChaRng
compatible with Emscripten. Potentially support for Emscripten will be dropped
in the future, if it doesn't get support for u128.
  • Loading branch information
dhardy committed Jun 3, 2019
1 parent 33bd404 commit ff121cf
Show file tree
Hide file tree
Showing 6 changed files with 27 additions and 15 deletions.
8 changes: 7 additions & 1 deletion Cargo.toml
Expand Up @@ -55,7 +55,6 @@ members = [

[dependencies]
rand_core = { path = "rand_core", version = "0.4" }
rand_chacha = { path = "rand_chacha", version = "0.2" }
rand_pcg = { path = "rand_pcg", version = "0.1", optional = true }
# Do not depend on 'getrandom_package' directly; use the 'getrandom' feature!
getrandom_package = { version = "0.1.1", package = "getrandom", optional = true }
Expand All @@ -72,6 +71,13 @@ features = ["into_bits"]
# Used for fork protection (reseeding.rs)
libc = { version = "0.2.22", default-features = false }

# Emscripten does not support 128-bit integers, which are used by ChaCha code.
# We work around this by using a different RNG.
[target.'cfg(not(target_os = "emscripten"))'.dependencies]
rand_chacha = { path = "rand_chacha", version = "0.2" }
[target.'cfg(target_os = "emscripten")'.dependencies]
rand_hc = { path = "rand_hc", version = "0.1" }

[dev-dependencies]
rand_pcg = { path = "rand_pcg", version = "0.1" }
# Only for benches:
Expand Down
3 changes: 2 additions & 1 deletion src/distributions/integer.rs
Expand Up @@ -11,7 +11,8 @@
use {Rng};
use distributions::{Distribution, Standard};
#[cfg(rustc_1_28)]
use core::num::{NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU128, NonZeroUsize};
use core::num::{NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroUsize};
#[cfg(not(target_os = "emscripten"))] use core::num::NonZeroU128;
#[cfg(feature="simd_support")]
use packed_simd::*;
#[cfg(all(target_arch = "x86", feature="nightly"))]
Expand Down
3 changes: 2 additions & 1 deletion src/lib.rs
Expand Up @@ -62,7 +62,8 @@
extern crate getrandom_package as getrandom;

extern crate rand_core;
extern crate rand_chacha;
#[cfg(not(target_os = "emscripten"))] extern crate rand_chacha;
#[cfg(target_os = "emscripten")] extern crate rand_hc;
#[cfg(feature="small_rng")] extern crate rand_pcg;

#[cfg(feature = "log")] #[macro_use] extern crate log;
Expand Down
6 changes: 3 additions & 3 deletions src/rngs/adapter/reseeding.rs
Expand Up @@ -324,14 +324,14 @@ mod fork {
#[cfg(test)]
mod test {
use {Rng, SeedableRng};
use rand_chacha::ChaCha8Core;
use rngs::std::Core;
use rngs::mock::StepRng;
use super::ReseedingRng;

#[test]
fn test_reseeding() {
let mut zero = StepRng::new(0, 0);
let rng = ChaCha8Core::from_rng(&mut zero).unwrap();
let rng = Core::from_rng(&mut zero).unwrap();
let thresh = 1; // reseed every time the buffer is exhausted
let mut reseeding = ReseedingRng::new(rng, thresh, zero);

Expand All @@ -351,7 +351,7 @@ mod test {
#[test]
fn test_clone_reseeding() {
let mut zero = StepRng::new(0, 0);
let rng = ChaCha8Core::from_rng(&mut zero).unwrap();
let rng = Core::from_rng(&mut zero).unwrap();
let mut rng1 = ReseedingRng::new(rng, 32*4, zero);

let first: u32 = rng1.gen();
Expand Down
14 changes: 9 additions & 5 deletions src/rngs/std.rs
Expand Up @@ -9,7 +9,11 @@
//! The standard RNG

use {RngCore, CryptoRng, Error, SeedableRng};
use rand_chacha::ChaCha20Rng;

#[cfg(target_os = "emscripten")] pub(crate) use rand_hc::Hc128Core as Core;
#[cfg(not(target_os = "emscripten"))] pub(crate) use rand_chacha::ChaCha20Core as Core;
#[cfg(target_os = "emscripten")] use rand_hc::Hc128Rng as Rng;
#[cfg(not(target_os = "emscripten"))] use rand_chacha::ChaCha20Rng as Rng;

/// The standard RNG. The PRNG algorithm in `StdRng` is chosen to be efficient
/// on the current platform, to be statistically strong and unpredictable
Expand All @@ -27,7 +31,7 @@ use rand_chacha::ChaCha20Rng;
///
/// [rand_chacha]: https://crates.io/crates/rand_chacha
#[derive(Clone, Debug)]
pub struct StdRng(ChaCha20Rng);
pub struct StdRng(Rng);

impl RngCore for StdRng {
#[inline(always)]
Expand All @@ -50,14 +54,14 @@ impl RngCore for StdRng {
}

impl SeedableRng for StdRng {
type Seed = <ChaCha20Rng as SeedableRng>::Seed;
type Seed = <Rng as SeedableRng>::Seed;

fn from_seed(seed: Self::Seed) -> Self {
StdRng(ChaCha20Rng::from_seed(seed))
StdRng(Rng::from_seed(seed))
}

fn from_rng<R: RngCore>(rng: R) -> Result<Self, Error> {
ChaCha20Rng::from_rng(rng).map(StdRng)
Rng::from_rng(rng).map(StdRng)
}
}

Expand Down
8 changes: 4 additions & 4 deletions src/rngs/thread.rs
Expand Up @@ -13,7 +13,7 @@ use std::cell::UnsafeCell;
use {RngCore, CryptoRng, SeedableRng, Error};
use rngs::adapter::ReseedingRng;
use rngs::OsRng;
use rand_chacha::ChaCha20Core;
use super::std::Core;

// Rationale for using `UnsafeCell` in `ThreadRng`:
//
Expand Down Expand Up @@ -58,12 +58,12 @@ const THREAD_RNG_RESEED_THRESHOLD: u64 = 1024 * 64;
#[derive(Copy, Clone, Debug)]
pub struct ThreadRng {
// use of raw pointer implies type is neither Send nor Sync
rng: *mut ReseedingRng<ChaCha20Core, OsRng>,
rng: *mut ReseedingRng<Core, OsRng>,
}

thread_local!(
static THREAD_RNG_KEY: UnsafeCell<ReseedingRng<ChaCha20Core, OsRng>> = {
let r = ChaCha20Core::from_rng(OsRng).unwrap_or_else(|err|
static THREAD_RNG_KEY: UnsafeCell<ReseedingRng<Core, OsRng>> = {
let r = Core::from_rng(OsRng).unwrap_or_else(|err|
panic!("could not initialize thread_rng: {}", err));
let rng = ReseedingRng::new(r,
THREAD_RNG_RESEED_THRESHOLD,
Expand Down

0 comments on commit ff121cf

Please sign in to comment.