Skip to content

Commit

Permalink
Implement no_std support for Wasm
Browse files Browse the repository at this point in the history
  • Loading branch information
daxpedda committed Nov 28, 2024
1 parent ff4a38c commit 84af741
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 5 deletions.
12 changes: 12 additions & 0 deletions .github/workflows/workspace.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,22 @@ jobs:
env:
RUSTFLAGS: -Dwarnings --cfg getrandom_backend="wasm_js"
run: cargo clippy -Zbuild-std --target wasm32-unknown-unknown
- name: Web WASM no_std (wasm_js.rs)
env:
RUSTFLAGS: -Dwarnings --cfg getrandom_backend="wasm_js"
run: cargo clippy -Zbuild-std=core,alloc --target wasm32-unknown-unknown
- name: Web WASM no_std with atomics (wasm_js.rs)
env:
RUSTFLAGS: -Dwarnings --cfg getrandom_backend="wasm_js" -Ctarget-feature=+atomics,+bulk-memory
run: cargo clippy -Zbuild-std=core,alloc --target wasm32-unknown-unknown
- name: Web WASMv1 (wasm_js.rs)
env:
RUSTFLAGS: -Dwarnings --cfg getrandom_backend="wasm_js"
run: cargo clippy -Zbuild-std=core,alloc --target wasm32v1-none
- name: Web WASMv1 with atomics (wasm_js.rs)
env:
RUSTFLAGS: -Dwarnings --cfg getrandom_backend="wasm_js" -Ctarget-feature=+atomics,+bulk-memory
run: cargo clippy -Zbuild-std=core,alloc --target wasm32v1-none
- name: Linux (linux_android.rs)
env:
RUSTFLAGS: -Dwarnings --cfg getrandom_backend="linux_getrandom"
Expand Down
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ windows-targets = "0.52"
[target.'cfg(all(getrandom_backend = "wasm_js", any(target_arch = "wasm32", target_arch = "wasm64"), any(target_os = "unknown", target_os = "none")))'.dependencies]
wasm-bindgen = { version = "0.2.89", default-features = false }
js-sys = { version = "0.3", default-features = false }
once_cell = { version = "1", default-features = false }
[target.'cfg(all(getrandom_backend = "wasm_js", getrandom_browser_test, target_arch = "wasm32", any(target_os = "unknown", target_os = "none")))'.dev-dependencies]
wasm-bindgen-test = { version = "0.3.39", default-features = false }

Expand Down
38 changes: 33 additions & 5 deletions src/backends/wasm_js.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
//! Implementation for WASM based on Web and Node.js
use crate::Error;

#[cfg(feature = "std")]
extern crate std;
use std::{mem::MaybeUninit, thread_local};
use core::mem::MaybeUninit;

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

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

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

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

// JsValues are always per-thread, so we initialize RngSource for each thread.
// See: https://github.com/rustwasm/wasm-bindgen/pull/955
thread_local!(
static RNG_SOURCE: Result<RngSource, Error> = getrandom_init();
);
struct Local;

impl Local {
#[cfg(feature = "std")]
fn with<R>(f: impl FnOnce(&Result<RngSource, Error>) -> R) -> R {
std::thread_local!(
static RNG_SOURCE: Result<RngSource, Error> = getrandom_init();
);
RNG_SOURCE.with(f)
}

#[cfg(all(not(feature = "std"), not(target_feature = "atomics")))]
fn with<R>(f: impl FnOnce(&Result<RngSource, Error>) -> R) -> R {
struct Wrapper<T>(T);
unsafe impl<T> Send for Wrapper<T> {}
unsafe impl<T> Sync for Wrapper<T> {}
static RNG_SOURCE: Wrapper<Lazy<Result<RngSource, Error>>> =
Wrapper(Lazy::new(getrandom_init));
f(&RNG_SOURCE.0)
}

#[cfg(all(not(feature = "std"), target_feature = "atomics"))]
fn with<R>(f: impl FnOnce(&Result<RngSource, Error>) -> R) -> R {
#[thread_local]
static RNG_SOURCE: Lazy<Result<RngSource, Error>> = Lazy::new(getrandom_init);
f(&RNG_SOURCE)
}
}

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

match source {
Expand Down
10 changes: 10 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,16 @@
#![warn(rust_2018_idioms, unused_lifetimes, missing_docs)]
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
#![cfg_attr(getrandom_sanitize, feature(cfg_sanitize))]
#![cfg_attr(
all(
getrandom_backend = "wasm_js",
any(target_arch = "wasm32", target_arch = "wasm64"),
any(target_os = "unknown", target_os = "none"),
not(feature = "std"),
target_feature = "atomics"
),
feature(thread_local)
)]
#![deny(
clippy::cast_lossless,
clippy::cast_possible_truncation,
Expand Down

0 comments on commit 84af741

Please sign in to comment.