Skip to content

Commit f18f3b3

Browse files
committed
Implement no_std support for Wasm
1 parent c619d21 commit f18f3b3

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
#[cfg(not(all(
89
any(target_arch = "wasm32", target_arch = "wasm64"),
@@ -11,6 +12,8 @@ use std::{mem::MaybeUninit, thread_local};
1112
compile_error!("`wasm_js` backend can be enabled only for OS-less WASM targets!");
1213

1314
use js_sys::{global, Function, Uint8Array};
15+
#[cfg(not(feature = "std"))]
16+
use once_cell::unsync::Lazy;
1417
use wasm_bindgen::{prelude::wasm_bindgen, JsCast, JsValue};
1518

1619
// Size of our temporary Uint8Array buffer used with WebCrypto methods
@@ -26,12 +29,37 @@ enum RngSource {
2629

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

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

3765
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)