diff --git a/.travis.yml b/.travis.yml
index e11aaa49..2ca90477 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -3,12 +3,12 @@ sudo: false
 
 matrix:
   include:
-    - rust: 1.28.0
-      env: DESCRIPTION="Linux, 1.28.0"
+    - rust: 1.32.0
+      env: DESCRIPTION="Linux, 1.32.0"
       os: linux
 
-    - rust: 1.28.0
-      env: DESCRIPTION="OSX, 1.22.0"
+    - rust: 1.32.0
+      env: DESCRIPTION="OSX, 1.32.0"
       os: osx
 
     - rust: stable
@@ -123,7 +123,7 @@ matrix:
         - source ~/.cargo/env || true
       script:
         - bash utils/ci/script.sh
-    
+
     - rust: stable
       sudo: required
       dist: trusty
diff --git a/Cargo.toml b/Cargo.toml
index 005d3167..7f89670f 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,7 @@
 [package]
 name = "getrandom"
 version = "0.1.0"
+edition = "2018"
 authors = ["The Rand Project Developers"]
 license = "MIT OR Apache-2.0"
 description = "A small cross-platform library for retrieving random data from system source"
@@ -14,9 +15,7 @@ travis-ci = { repository = "rust-random/getrandom" }
 appveyor = { repository = "rust-random/getrandom" }
 
 [workspace]
-members = [
-    "tests/wasm_bindgen",
-]
+members = ["tests/wasm_bindgen"]
 
 [dependencies]
 log = { version = "0.4", optional = true }
@@ -36,3 +35,6 @@ fuchsia-cprng = "0.1"
 [target.wasm32-unknown-unknown.dependencies]
 wasm-bindgen = { version = "0.2.29", optional = true }
 stdweb = { version = "0.4.9", optional = true }
+
+[features]
+std = []
diff --git a/README.md b/README.md
index f56f7ab7..420af4ff 100644
--- a/README.md
+++ b/README.md
@@ -16,7 +16,7 @@ the same set of platforms as Rust's `std` lib.
 This is a low-level API. Most users should prefer using high-level random-number
 library like [`rand`].
 
-[Rand]: https://crates.io/crates/rand
+[`rand`]: https://crates.io/crates/rand
 
 
 ## Usage
@@ -53,7 +53,7 @@ one of the following features must be enabled:
 
 ## Minimum Supported Rust Version
 
-This crate requires Rustc version 1.28.0 or later due to usage of `NonZeroU32`.
+This crate requires Rust 1.32.0 or later.
 
 
 # License
diff --git a/src/cloudabi.rs b/src/cloudabi.rs
index fc5f49d7..5631c2c5 100644
--- a/src/cloudabi.rs
+++ b/src/cloudabi.rs
@@ -7,11 +7,8 @@
 // except according to those terms.
 
 //! Implementation for CloudABI
-
-extern crate cloudabi;
-
 use core::num::NonZeroU32;
-use Error;
+use crate::Error;
 
 pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> {
     let errno = unsafe { cloudabi::random_get(dest) };
diff --git a/src/dragonfly_haiku.rs b/src/dragonfly_haiku.rs
deleted file mode 100644
index 8b8b947a..00000000
--- a/src/dragonfly_haiku.rs
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright 2018 Developers of the Rand project.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! Implementation for DragonFly / Haiku
-use Error;
-use utils::use_init;
-use std::fs::File;
-use std::io::Read;
-use std::cell::RefCell;
-use std::num::NonZeroU32;
-
-thread_local!(static RNG_FILE: RefCell<Option<File>> = RefCell::new(None));
-
-pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> {
-    RNG_FILE.with(|f| {
-        use_init(f,
-            || File::open("/dev/random").map_err(From::from),
-            |f| f.read_exact(dest).map_err(From::from),
-        )
-    })
-}
-
-#[inline(always)]
-pub fn error_msg_inner(_: NonZeroU32) -> Option<&'static str> { None }
diff --git a/src/dummy.rs b/src/dummy.rs
index 49c72aeb..e0ab8ced 100644
--- a/src/dummy.rs
+++ b/src/dummy.rs
@@ -8,8 +8,8 @@
 
 //! A dummy implementation for unsupported targets which always returns
 //! `Err(Error::UNAVAILABLE)`
-use std::num::NonZeroU32;
-use Error;
+use core::num::NonZeroU32;
+use crate::Error;
 
 pub fn getrandom_inner(_: &mut [u8]) -> Result<(), Error> {
     error!("no support for this platform");
diff --git a/src/emscripten.rs b/src/emscripten.rs
deleted file mode 100644
index 471fc686..00000000
--- a/src/emscripten.rs
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright 2018 Developers of the Rand project.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! Implementation for Emscripten
-use Error;
-use std::fs::File;
-use std::io::Read;
-use std::cell::RefCell;
-use std::num::NonZeroU32;
-use utils::use_init;
-
-thread_local!(static RNG_FILE: RefCell<Option<File>> = RefCell::new(None));
-
-pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> {
-    // `Crypto.getRandomValues` documents `dest` should be at most 65536
-    // bytes. `crypto.randomBytes` documents: "To minimize threadpool
-    // task length variation, partition large randomBytes requests when
-    // doing so as part of fulfilling a client request.
-    RNG_FILE.with(|f| {
-        use_init(f, || File::open("/dev/random").map_err(From::from), |f| {
-            for chunk in dest.chunks_mut(65536) {
-                f.read_exact(chunk)?;
-            }
-            Ok(())
-        })
-    })
-}
-
-#[inline(always)]
-pub fn error_msg_inner(_: NonZeroU32) -> Option<&'static str> { None }
diff --git a/src/error.rs b/src/error.rs
index f0e9b62f..802e680f 100644
--- a/src/error.rs
+++ b/src/error.rs
@@ -5,12 +5,9 @@
 // <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
-
 use core::num::NonZeroU32;
 use core::convert::From;
 use core::fmt;
-#[cfg(not(target_env = "sgx"))]
-use std::{io, error};
 
 // A randomly-chosen 24-bit prefix for our codes
 pub(crate) const CODE_PREFIX: u32 = 0x57f4c500;
@@ -21,7 +18,7 @@ const CODE_UNAVAILABLE: u32 = CODE_PREFIX | 0x01;
 ///
 /// This type is small and no-std compatible.
 #[derive(Copy, Clone, Eq, PartialEq)]
-pub struct Error(NonZeroU32);
+pub struct Error(pub(crate) NonZeroU32);
 
 impl Error {
     /// An unknown error.
@@ -44,7 +41,7 @@ impl Error {
         self.0
     }
 
-    fn msg(&self) -> Option<&'static str> {
+    pub(crate) fn msg(&self) -> Option<&'static str> {
         if let Some(msg) = super::error_msg_inner(self.0) {
             Some(msg)
         } else {
@@ -81,33 +78,9 @@ impl From<NonZeroU32> for Error {
     }
 }
 
-#[cfg(not(target_env = "sgx"))]
-impl From<io::Error> for Error {
-    fn from(err: io::Error) -> Self {
-        err.raw_os_error()
-            .and_then(|code| NonZeroU32::new(code as u32))
-            .map(|code| Error(code))
-            // in practice this should never happen
-            .unwrap_or(Error::UNKNOWN)
-    }
-}
-
-#[cfg(not(target_env = "sgx"))]
-impl From<Error> for io::Error {
-    fn from(err: Error) -> Self {
-        match err.msg() {
-            Some(msg) => io::Error::new(io::ErrorKind::Other, msg),
-            None => io::Error::from_raw_os_error(err.0.get() as i32),
-        }
-    }
-}
-
-#[cfg(not(target_env = "sgx"))]
-impl error::Error for Error { }
-
 #[cfg(test)]
 mod tests {
-    use std::mem::size_of;
+    use core::mem::size_of;
     use super::Error;
 
     #[test]
diff --git a/src/error_impls.rs b/src/error_impls.rs
new file mode 100644
index 00000000..4dd1db4e
--- /dev/null
+++ b/src/error_impls.rs
@@ -0,0 +1,34 @@
+// Copyright 2018 Developers of the Rand project.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+extern crate std;
+
+use std::{io, error};
+use core::convert::From;
+use core::num::NonZeroU32;
+use crate::error::Error;
+
+impl From<io::Error> for Error {
+    fn from(err: io::Error) -> Self {
+        err.raw_os_error()
+            .and_then(|code| NonZeroU32::new(code as u32))
+            .map(|code| Error(code))
+            // in practice this should never happen
+            .unwrap_or(Error::UNKNOWN)
+    }
+}
+
+impl From<Error> for io::Error {
+    fn from(err: Error) -> Self {
+        match err.msg() {
+            Some(msg) => io::Error::new(io::ErrorKind::Other, msg),
+            None => io::Error::from_raw_os_error(err.0.get() as i32),
+        }
+    }
+}
+
+impl error::Error for Error { }
diff --git a/src/freebsd.rs b/src/freebsd.rs
index fcad6e58..6e0dd970 100644
--- a/src/freebsd.rs
+++ b/src/freebsd.rs
@@ -7,12 +7,12 @@
 // except according to those terms.
 
 //! Implementation for FreeBSD
-extern crate libc;
+extern crate std;
 
-use Error;
-use core::ptr;
+use crate::Error;
 use std::io;
-use std::num::NonZeroU32;
+use core::ptr;
+use core::num::NonZeroU32;
 
 pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> {
     let mib = [libc::CTL_KERN, libc::KERN_ARND];
diff --git a/src/fuchsia.rs b/src/fuchsia.rs
index 59defc0e..5375f486 100644
--- a/src/fuchsia.rs
+++ b/src/fuchsia.rs
@@ -7,10 +7,8 @@
 // except according to those terms.
 
 //! Implementation for Fuchsia Zircon
-extern crate fuchsia_cprng;
-
-use std::num::NonZeroU32;
-use Error;
+use core::num::NonZeroU32;
+use crate::Error;
 
 pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> {
     fuchsia_cprng::cprng_draw(dest);
diff --git a/src/lib.rs b/src/lib.rs
index 322e11e9..e55b9a51 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -112,26 +112,19 @@
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk.png",
        html_favicon_url = "https://www.rust-lang.org/favicon.ico",
        html_root_url = "https://rust-random.github.io/rand/")]
-
 #![no_std]
-
 #![cfg_attr(feature = "stdweb", recursion_limit="128")]
 
-#[cfg(not(target_env = "sgx"))]
-#[macro_use] extern crate std;
-
-// We have to do it here because we load macros
-#[cfg(all(target_arch = "wasm32", not(target_os = "emscripten"),
-          feature = "wasm-bindgen"))]
-extern crate wasm_bindgen;
-#[cfg(all(target_arch = "wasm32", not(target_os = "emscripten"),
-          not(feature = "wasm-bindgen"),
-          feature = "stdweb"))]
-#[macro_use] extern crate stdweb;
-
-#[cfg(feature = "log")] #[macro_use] extern crate log;
+#[cfg(feature = "log")]
+#[macro_use]
+extern crate log;
+#[cfg(not(feature = "log"))]
 #[allow(unused)]
-#[cfg(not(feature = "log"))] macro_rules! error { ($($x:tt)*) => () }
+macro_rules! error { ($($x:tt)*) => () }
+
+// temp fix for stdweb
+#[cfg(target_arch = "wasm32")]
+extern crate std;
 
 #[cfg(any(
     target_os = "android",
@@ -146,7 +139,7 @@ extern crate wasm_bindgen;
 ))]
 mod utils;
 mod error;
-pub use error::Error;
+pub use crate::error::Error;
 
 // System-specific implementations.
 //
@@ -157,25 +150,34 @@ macro_rules! mod_use {
         #[$cond]
         mod $module;
         #[$cond]
-        use $module::{getrandom_inner, error_msg_inner};
+        use crate::$module::{getrandom_inner, error_msg_inner};
     }
 }
 
+#[cfg(any(
+    feature = "std",
+    windows, unix,
+    target_os = "redox",
+    target_arch = "wasm32",
+))]
+mod error_impls;
+
 mod_use!(cfg(target_os = "android"), linux_android);
 mod_use!(cfg(target_os = "bitrig"), openbsd_bitrig);
 mod_use!(cfg(target_os = "cloudabi"), cloudabi);
-mod_use!(cfg(target_os = "dragonfly"), dragonfly_haiku);
-mod_use!(cfg(target_os = "emscripten"), emscripten);
+mod_use!(cfg(target_os = "dragonfly"), use_file);
+mod_use!(cfg(target_os = "emscripten"), use_file);
 mod_use!(cfg(target_os = "freebsd"), freebsd);
 mod_use!(cfg(target_os = "fuchsia"), fuchsia);
-mod_use!(cfg(target_os = "haiku"), dragonfly_haiku);
+mod_use!(cfg(target_os = "haiku"), use_file);
+mod_use!(cfg(target_os = "illumos"), solaris_illumos);
 mod_use!(cfg(target_os = "ios"), macos);
 mod_use!(cfg(target_os = "linux"), linux_android);
 mod_use!(cfg(target_os = "macos"), macos);
-mod_use!(cfg(target_os = "netbsd"), netbsd);
+mod_use!(cfg(target_os = "netbsd"), use_file);
 mod_use!(cfg(target_os = "openbsd"), openbsd_bitrig);
-mod_use!(cfg(target_os = "redox"), redox);
-mod_use!(cfg(any(target_os = "solaris", target_os = "illumos")), solarish);
+mod_use!(cfg(target_os = "redox"), use_file);
+mod_use!(cfg(target_os = "solaris"), solaris_illumos);
 mod_use!(cfg(windows), windows);
 mod_use!(cfg(target_env = "sgx"), sgx);
 
@@ -245,58 +247,3 @@ mod_use!(
 pub fn getrandom(dest: &mut [u8]) -> Result<(), error::Error> {
     getrandom_inner(dest)
 }
-
-// Due to rustwasm/wasm-bindgen#201 this can't be defined in the inner os
-// modules, so hack around it for now and place it at the root.
-#[cfg(all(feature = "wasm-bindgen", target_arch = "wasm32"))]
-#[doc(hidden)]
-#[allow(missing_debug_implementations)]
-pub mod __wbg_shims {
-
-    // `extern { type Foo; }` isn't supported on 1.22 syntactically, so use a
-    // macro to work around that.
-    macro_rules! rust_122_compat {
-        ($($t:tt)*) => ($($t)*)
-    }
-
-    rust_122_compat! {
-        extern crate wasm_bindgen;
-
-        pub use wasm_bindgen::prelude::*;
-
-        #[wasm_bindgen]
-        extern "C" {
-            pub type Function;
-            #[wasm_bindgen(constructor)]
-            pub fn new(s: &str) -> Function;
-            #[wasm_bindgen(method)]
-            pub fn call(this: &Function, self_: &JsValue) -> JsValue;
-
-            pub type This;
-            #[wasm_bindgen(method, getter, structural, js_name = self)]
-            pub fn self_(me: &This) -> JsValue;
-            #[wasm_bindgen(method, getter, structural)]
-            pub fn crypto(me: &This) -> JsValue;
-
-            #[derive(Clone, Debug)]
-            pub type BrowserCrypto;
-
-            // TODO: these `structural` annotations here ideally wouldn't be here to
-            // avoid a JS shim, but for now with feature detection they're
-            // unavoidable.
-            #[wasm_bindgen(method, js_name = getRandomValues, structural, getter)]
-            pub fn get_random_values_fn(me: &BrowserCrypto) -> JsValue;
-            #[wasm_bindgen(method, js_name = getRandomValues, structural)]
-            pub fn get_random_values(me: &BrowserCrypto, buf: &mut [u8]);
-
-            #[wasm_bindgen(js_name = require)]
-            pub fn node_require(s: &str) -> NodeCrypto;
-
-            #[derive(Clone, Debug)]
-            pub type NodeCrypto;
-
-            #[wasm_bindgen(method, js_name = randomFillSync, structural)]
-            pub fn random_fill_sync(me: &NodeCrypto, buf: &mut [u8]);
-        }
-    }
-}
diff --git a/src/linux_android.rs b/src/linux_android.rs
index 51702c97..2d260755 100644
--- a/src/linux_android.rs
+++ b/src/linux_android.rs
@@ -7,16 +7,14 @@
 // except according to those terms.
 
 //! Implementation for Linux / Android
-extern crate libc;
+extern crate std;
 
-use Error;
-use utils::use_init;
-use std::fs::File;
-use std::io;
-use std::io::Read;
-use std::cell::RefCell;
-use std::num::NonZeroU32;
-use std::sync::atomic::{AtomicBool, Ordering};
+use crate::Error;
+use crate::utils::use_init;
+use std::{thread_local, io::{self, Read}, fs::File};
+use core::cell::RefCell;
+use core::num::NonZeroU32;
+use core::sync::atomic::{AtomicBool, Ordering};
 
 static RNG_INIT: AtomicBool = AtomicBool::new(false);
 
diff --git a/src/macos.rs b/src/macos.rs
index 776e2a95..bace43c3 100644
--- a/src/macos.rs
+++ b/src/macos.rs
@@ -7,12 +7,11 @@
 // except according to those terms.
 
 //! Implementation for MacOS / iOS
-extern crate libc;
+extern crate std;
 
-use Error;
+use crate::Error;
 use std::io;
-use std::num::NonZeroU32;
-use self::libc::{c_int, size_t};
+use core::num::NonZeroU32;
 
 enum SecRandom {}
 
@@ -23,15 +22,15 @@ const kSecRandomDefault: *const SecRandom = 0 as *const SecRandom;
 #[link(name = "Security", kind = "framework")]
 extern {
     fn SecRandomCopyBytes(
-        rnd: *const SecRandom, count: size_t, bytes: *mut u8,
-    ) -> c_int;
+        rnd: *const SecRandom, count: libc::size_t, bytes: *mut u8,
+    ) -> libc::c_int;
 }
 
 pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> {
     let ret = unsafe {
         SecRandomCopyBytes(
             kSecRandomDefault,
-            dest.len() as size_t,
+            dest.len() as libc::size_t,
             dest.as_mut_ptr(),
         )
     };
diff --git a/src/netbsd.rs b/src/netbsd.rs
deleted file mode 100644
index a3a4aeee..00000000
--- a/src/netbsd.rs
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright 2018 Developers of the Rand project.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! Implementation for NetBSD
-
-use Error;
-use utils::use_init;
-use std::fs::File;
-use std::io::Read;
-use std::cell::RefCell;
-use std::num::NonZeroU32;
-use std::sync::atomic::{AtomicBool, Ordering};
-
-static RNG_INIT: AtomicBool = AtomicBool::new(false);
-
-thread_local!(static RNG_FILE: RefCell<Option<File>> = RefCell::new(None));
-
-pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> {
-    RNG_FILE.with(|f| {
-        use_init(f, || {
-            // read one byte from "/dev/random" to ensure that
-            // OS RNG has initialized
-            if !RNG_INIT.load(Ordering::Relaxed) {
-                File::open("/dev/random")?.read_exact(&mut [0u8; 1])?;
-                RNG_INIT.store(true, Ordering::Relaxed)
-            }
-            File::open("/dev/urandom").map_err(From::from)
-        }, |f| f.read_exact(dest).map_err(From::from))
-    })
-}
-
-#[inline(always)]
-pub fn error_msg_inner(_: NonZeroU32) -> Option<&'static str> { None }
diff --git a/src/openbsd_bitrig.rs b/src/openbsd_bitrig.rs
index fa80bb51..86d3fb35 100644
--- a/src/openbsd_bitrig.rs
+++ b/src/openbsd_bitrig.rs
@@ -7,9 +7,9 @@
 // except according to those terms.
 
 //! Implementation for OpenBSD / Bitrig
-extern crate libc;
+extern crate std;
 
-use Error;
+use crate::Error;
 use std::io;
 use std::num::NonZeroU32;
 
diff --git a/src/redox.rs b/src/redox.rs
deleted file mode 100644
index 6321feac..00000000
--- a/src/redox.rs
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright 2018 Developers of the Rand project.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! Implementation for Redox
-use Error;
-use utils::use_init;
-use std::fs::File;
-use std::io::Read;
-use std::cell::RefCell;
-use std::num::NonZeroU32;
-
-thread_local!(static RNG_FILE: RefCell<Option<File>> = RefCell::new(None));
-
-pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> {
-    RNG_FILE.with(|f| {
-        use_init(f,
-            || File::open("rand:").map_err(From::from),
-            |f| f.read_exact(dest).map_err(From::from),
-        )
-    }).map_err(From::from)
-}
-
-#[inline(always)]
-pub fn error_msg_inner(_: NonZeroU32) -> Option<&'static str> { None }
diff --git a/src/sgx.rs b/src/sgx.rs
index a0734eb3..8fba627b 100644
--- a/src/sgx.rs
+++ b/src/sgx.rs
@@ -7,8 +7,7 @@
 // except according to those terms.
 
 //! Implementation for SGX using RDRAND instruction
-use Error;
-
+use crate::Error;
 use core::{mem, ptr};
 use core::arch::x86_64::_rdrand64_step;
 use core::num::NonZeroU32;
diff --git a/src/solarish.rs b/src/solaris_illumos.rs
similarity index 95%
rename from src/solarish.rs
rename to src/solaris_illumos.rs
index ec9cff1e..5484dd0f 100644
--- a/src/solarish.rs
+++ b/src/solaris_illumos.rs
@@ -17,15 +17,13 @@
 //! To make sure we can compile on both Solaris and its derivatives, as well as
 //! function, we check for the existance of getrandom(2) in libc by calling
 //! libc::dlsym.
-extern crate libc;
+extern crate std;
 
-use Error;
-use std::cell::RefCell;
-use std::fs::File;
-use std::io;
-use std::io::Read;
-use std::num::NonZeroU32;
-use utils::use_init;
+use crate::Error;
+use crate::utils::use_init;
+use std::{thread_local, io::{self, Read}, fs::File};
+use core::cell::RefCell;
+use core::num::NonZeroU32;
 
 #[cfg(target_os = "illumos")]
 type GetRandomFn = unsafe extern "C" fn(*mut u8, libc::size_t, libc::c_uint) -> libc::ssize_t;
diff --git a/src/use_file.rs b/src/use_file.rs
new file mode 100644
index 00000000..404c13b2
--- /dev/null
+++ b/src/use_file.rs
@@ -0,0 +1,56 @@
+// Copyright 2018 Developers of the Rand project.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Implementation for DragonFly / Haiku
+extern crate std;
+
+use crate::Error;
+use crate::utils::use_init;
+use std::{thread_local, io::Read, fs::File};
+use core::cell::RefCell;
+use core::num::NonZeroU32;
+
+thread_local!(static RNG_FILE: RefCell<Option<File>> = RefCell::new(None));
+
+#[cfg(target_os = "redox")]
+const FILE_PATH: &str = "rand:";
+#[cfg(target_os = "netbsd")]
+const FILE_PATH: &str = "/dev/urandom";
+#[cfg(any(target_os = "dragonfly", target_os = "emscripten", target_os = "haiku"))]
+const FILE_PATH: &str = "/dev/random";
+
+pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> {
+    RNG_FILE.with(|f| {
+        use_init(f, || init_file(), |f| use_file(f, dest))
+    })
+}
+
+fn use_file(f: &mut File, dest: &mut [u8]) -> Result<(), Error> {
+    if cfg!(target_os = "emscripten") {
+        // `Crypto.getRandomValues` documents `dest` should be at most 65536 bytes.
+        for chunk in dest.chunks_mut(65536) {
+            f.read_exact(chunk)?;
+        }
+    } else {
+        f.read_exact(dest)?;
+    }
+    core::mem::forget(f);
+    Ok(())
+}
+
+fn init_file() -> Result<File, Error> {
+    if cfg!(target_os = "netbsd") {
+        // read one byte from "/dev/random" to ensure that OS RNG has initialized
+        File::open("/dev/random")?.read_exact(&mut [0u8; 1])?;
+    }
+    let f = File::open(FILE_PATH)?;
+    Ok(f)
+}
+
+#[inline(always)]
+pub fn error_msg_inner(_: NonZeroU32) -> Option<&'static str> { None }
diff --git a/src/utils.rs b/src/utils.rs
index d7722c06..1d8f40a5 100644
--- a/src/utils.rs
+++ b/src/utils.rs
@@ -5,7 +5,7 @@
 // <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
-use Error;
+use crate::Error;
 use core::cell::RefCell;
 use core::ops::DerefMut;
 
diff --git a/src/wasm32_bindgen.rs b/src/wasm32_bindgen.rs
index 0e00f464..7c835383 100644
--- a/src/wasm32_bindgen.rs
+++ b/src/wasm32_bindgen.rs
@@ -7,23 +7,24 @@
 // except according to those terms.
 
 //! Implementation for WASM via wasm-bindgen
+extern crate std;
 
-use std::cell::RefCell;
-use std::mem;
-use std::num::NonZeroU32;
+use core::cell::RefCell;
+use core::mem;
+use core::num::NonZeroU32;
+use std::thread_local;
 
 use wasm_bindgen::prelude::*;
 
-use __wbg_shims::*;
-use Error;
-use error::CODE_PREFIX;
-use utils::use_init;
+use crate::Error;
+use crate::error::CODE_PREFIX;
+use crate::utils::use_init;
 
 const CODE_CRYPTO_UNDEF: u32 = CODE_PREFIX | 0x80;
 const CODE_GRV_UNDEF: u32 = CODE_PREFIX | 0x81;
 
 #[derive(Clone, Debug)]
-pub enum RngSource {
+enum RngSource {
     Node(NodeCrypto),
     Browser(BrowserCrypto),
 }
@@ -105,3 +106,38 @@ pub fn error_msg_inner(n: NonZeroU32) -> Option<&'static str> {
         _ => None
     }
 }
+
+#[wasm_bindgen]
+extern "C" {
+    type Function;
+    #[wasm_bindgen(constructor)]
+    fn new(s: &str) -> Function;
+    #[wasm_bindgen(method)]
+    fn call(this: &Function, self_: &JsValue) -> JsValue;
+
+    type This;
+    #[wasm_bindgen(method, getter, structural, js_name = self)]
+    fn self_(me: &This) -> JsValue;
+    #[wasm_bindgen(method, getter, structural)]
+    fn crypto(me: &This) -> JsValue;
+
+    #[derive(Clone, Debug)]
+    type BrowserCrypto;
+
+    // TODO: these `structural` annotations here ideally wouldn't be here to
+    // avoid a JS shim, but for now with feature detection they're
+    // unavoidable.
+    #[wasm_bindgen(method, js_name = getRandomValues, structural, getter)]
+    fn get_random_values_fn(me: &BrowserCrypto) -> JsValue;
+    #[wasm_bindgen(method, js_name = getRandomValues, structural)]
+    fn get_random_values(me: &BrowserCrypto, buf: &mut [u8]);
+
+    #[wasm_bindgen(js_name = require)]
+    fn node_require(s: &str) -> NodeCrypto;
+
+    #[derive(Clone, Debug)]
+    type NodeCrypto;
+
+    #[wasm_bindgen(method, js_name = randomFillSync, structural)]
+    fn random_fill_sync(me: &NodeCrypto, buf: &mut [u8]);
+}
diff --git a/src/wasm32_stdweb.rs b/src/wasm32_stdweb.rs
index 7fe6c390..02f89aa0 100644
--- a/src/wasm32_stdweb.rs
+++ b/src/wasm32_stdweb.rs
@@ -7,16 +7,17 @@
 // except according to those terms.
 
 //! Implementation for WASM via stdweb
+use core::cell::RefCell;
+use core::mem;
+use core::num::NonZeroU32;
+use std::thread_local;
 
-use std::cell::RefCell;
-use std::mem;
-use std::num::NonZeroU32;
-
+use stdweb::{js, _js_impl};
 use stdweb::unstable::TryInto;
 use stdweb::web::error::Error as WebError;
 
-use Error;
-use utils::use_init;
+use crate::Error;
+use crate::utils::use_init;
 
 #[derive(Clone, Debug)]
 enum RngSource {
diff --git a/src/windows.rs b/src/windows.rs
index 5055783f..92feea17 100644
--- a/src/windows.rs
+++ b/src/windows.rs
@@ -7,14 +7,14 @@
 // except according to those terms.
 
 //! Implementation for Windows
-extern crate winapi;
+extern crate std;
 
-use self::winapi::shared::minwindef::ULONG;
-use self::winapi::um::ntsecapi::RtlGenRandom;
-use self::winapi::um::winnt::PVOID;
+use winapi::shared::minwindef::ULONG;
+use winapi::um::ntsecapi::RtlGenRandom;
+use winapi::um::winnt::PVOID;
 use std::io;
-use std::num::NonZeroU32;
-use Error;
+use core::num::NonZeroU32;
+use crate::Error;
 
 pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> {
     let ret = unsafe {