Skip to content

Commit 84af741

Browse files
committed
Implement no_std support for Wasm
1 parent ff4a38c commit 84af741

File tree

4 files changed

+56
-5
lines changed

4 files changed

+56
-5
lines changed

.github/workflows/workspace.yml

+12
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,22 @@ jobs:
4949
env:
5050
RUSTFLAGS: -Dwarnings --cfg getrandom_backend="wasm_js"
5151
run: cargo clippy -Zbuild-std --target wasm32-unknown-unknown
52+
- name: Web WASM no_std (wasm_js.rs)
53+
env:
54+
RUSTFLAGS: -Dwarnings --cfg getrandom_backend="wasm_js"
55+
run: cargo clippy -Zbuild-std=core,alloc --target wasm32-unknown-unknown
56+
- name: Web WASM no_std with atomics (wasm_js.rs)
57+
env:
58+
RUSTFLAGS: -Dwarnings --cfg getrandom_backend="wasm_js" -Ctarget-feature=+atomics,+bulk-memory
59+
run: cargo clippy -Zbuild-std=core,alloc --target wasm32-unknown-unknown
5260
- name: Web WASMv1 (wasm_js.rs)
5361
env:
5462
RUSTFLAGS: -Dwarnings --cfg getrandom_backend="wasm_js"
5563
run: cargo clippy -Zbuild-std=core,alloc --target wasm32v1-none
64+
- name: Web WASMv1 with atomics (wasm_js.rs)
65+
env:
66+
RUSTFLAGS: -Dwarnings --cfg getrandom_backend="wasm_js" -Ctarget-feature=+atomics,+bulk-memory
67+
run: cargo clippy -Zbuild-std=core,alloc --target wasm32v1-none
5668
- name: Linux (linux_android.rs)
5769
env:
5870
RUSTFLAGS: -Dwarnings --cfg getrandom_backend="linux_getrandom"

Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ windows-targets = "0.52"
6666
[target.'cfg(all(getrandom_backend = "wasm_js", any(target_arch = "wasm32", target_arch = "wasm64"), any(target_os = "unknown", target_os = "none")))'.dependencies]
6767
wasm-bindgen = { version = "0.2.89", default-features = false }
6868
js-sys = { version = "0.3", default-features = false }
69+
once_cell = { version = "1", default-features = false }
6970
[target.'cfg(all(getrandom_backend = "wasm_js", getrandom_browser_test, target_arch = "wasm32", any(target_os = "unknown", target_os = "none")))'.dev-dependencies]
7071
wasm-bindgen-test = { version = "0.3.39", default-features = false }
7172

src/backends/wasm_js.rs

+33-5
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
//! Implementation for WASM based on Web and Node.js
22
use crate::Error;
33

4+
#[cfg(feature = "std")]
45
extern crate std;
5-
use std::{mem::MaybeUninit, thread_local};
6+
use core::mem::MaybeUninit;
67

78
pub use crate::util::{inner_u32, inner_u64};
89

@@ -13,6 +14,8 @@ pub use crate::util::{inner_u32, inner_u64};
1314
compile_error!("`wasm_js` backend can be enabled only for OS-less WASM targets!");
1415

1516
use js_sys::{global, Function, Uint8Array};
17+
#[cfg(not(feature = "std"))]
18+
use once_cell::unsync::Lazy;
1619
use wasm_bindgen::{prelude::wasm_bindgen, JsCast, JsValue};
1720

1821
// Size of our temporary Uint8Array buffer used with WebCrypto methods
@@ -28,12 +31,37 @@ enum RngSource {
2831

2932
// JsValues are always per-thread, so we initialize RngSource for each thread.
3033
// See: https://github.com/rustwasm/wasm-bindgen/pull/955
31-
thread_local!(
32-
static RNG_SOURCE: Result<RngSource, Error> = getrandom_init();
33-
);
34+
struct Local;
35+
36+
impl Local {
37+
#[cfg(feature = "std")]
38+
fn with<R>(f: impl FnOnce(&Result<RngSource, Error>) -> R) -> R {
39+
std::thread_local!(
40+
static RNG_SOURCE: Result<RngSource, Error> = getrandom_init();
41+
);
42+
RNG_SOURCE.with(f)
43+
}
44+
45+
#[cfg(all(not(feature = "std"), not(target_feature = "atomics")))]
46+
fn with<R>(f: impl FnOnce(&Result<RngSource, Error>) -> R) -> R {
47+
struct Wrapper<T>(T);
48+
unsafe impl<T> Send for Wrapper<T> {}
49+
unsafe impl<T> Sync for Wrapper<T> {}
50+
static RNG_SOURCE: Wrapper<Lazy<Result<RngSource, Error>>> =
51+
Wrapper(Lazy::new(getrandom_init));
52+
f(&RNG_SOURCE.0)
53+
}
54+
55+
#[cfg(all(not(feature = "std"), target_feature = "atomics"))]
56+
fn with<R>(f: impl FnOnce(&Result<RngSource, Error>) -> R) -> R {
57+
#[thread_local]
58+
static RNG_SOURCE: Lazy<Result<RngSource, Error>> = Lazy::new(getrandom_init);
59+
f(&RNG_SOURCE)
60+
}
61+
}
3462

3563
pub fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
36-
RNG_SOURCE.with(|result| {
64+
Local::with(|result| {
3765
let source = result.as_ref().map_err(|&e| e)?;
3866

3967
match source {

src/lib.rs

+10
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,16 @@
1212
#![warn(rust_2018_idioms, unused_lifetimes, missing_docs)]
1313
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
1414
#![cfg_attr(getrandom_sanitize, feature(cfg_sanitize))]
15+
#![cfg_attr(
16+
all(
17+
getrandom_backend = "wasm_js",
18+
any(target_arch = "wasm32", target_arch = "wasm64"),
19+
any(target_os = "unknown", target_os = "none"),
20+
not(feature = "std"),
21+
target_feature = "atomics"
22+
),
23+
feature(thread_local)
24+
)]
1525
#![deny(
1626
clippy::cast_lossless,
1727
clippy::cast_possible_truncation,

0 commit comments

Comments
 (0)