mirror of
https://github.com/uuid-rs/uuid.git
synced 2025-09-30 06:21:02 +00:00
Merge pull request #794 from uuid-rs/feat/getrandom-wasm32
Support forcing `getrandom` on `wasm32-unknown-unknown` without JavaScript
This commit is contained in:
commit
6494c4b0f2
12
.github/workflows/ci.yml
vendored
12
.github/workflows/ci.yml
vendored
@ -133,6 +133,18 @@ jobs:
|
||||
- name: Fast RNG
|
||||
run: wasm-pack test --node -- --features "js v4 fast-rng"
|
||||
|
||||
- name: rng-getrandom
|
||||
env:
|
||||
RUSTFLAGS: '--cfg getrandom_backend="wasm_js"'
|
||||
working-directory: ./tests/wasm32-getrandom-test
|
||||
run: wasm-pack test --node
|
||||
|
||||
- name: rng-rand
|
||||
env:
|
||||
RUSTFLAGS: '--cfg getrandom_backend="wasm_js"'
|
||||
working-directory: ./tests/wasm32-getrandom-test
|
||||
run: wasm-pack test --node -- --features "rand"
|
||||
|
||||
wasi:
|
||||
name: Tests / WebAssembly (WASI)
|
||||
runs-on: ubuntu-latest
|
||||
|
18
Cargo.toml
18
Cargo.toml
@ -71,6 +71,9 @@ v8 = []
|
||||
js = ["dep:wasm-bindgen"]
|
||||
|
||||
rng = ["dep:getrandom"]
|
||||
rng-getrandom = ["rng", "dep:getrandom", "uuid-rng-internal-lib", "uuid-rng-internal-lib/getrandom"]
|
||||
rng-rand = ["rng", "dep:rand", "uuid-rng-internal-lib", "uuid-rng-internal-lib/rand"]
|
||||
|
||||
fast-rng = ["rng", "dep:rand"]
|
||||
|
||||
sha1 = ["dep:sha1_smol"]
|
||||
@ -126,13 +129,20 @@ default-features = false
|
||||
# Private
|
||||
# (Formally public)
|
||||
[target.'cfg(not(all(target_arch = "wasm32", target_vendor = "unknown", target_os = "unknown")))'.dependencies.getrandom]
|
||||
optional = true
|
||||
version = "0.3"
|
||||
optional = true
|
||||
|
||||
[target.'cfg(all(target_arch = "wasm32", target_vendor = "unknown", target_os = "unknown"))'.dependencies.uuid-rng-internal-lib]
|
||||
# Work-around lack of support for both `dep:x` and `x/` in MSRV
|
||||
package = "uuid-rng-internal"
|
||||
version = "1.12.1"
|
||||
path = "rng"
|
||||
optional = true
|
||||
|
||||
# Private
|
||||
[target.'cfg(not(all(target_arch = "wasm32", target_vendor = "unknown", target_os = "unknown")))'.dependencies.rand]
|
||||
optional = true
|
||||
version = "0.9"
|
||||
optional = true
|
||||
|
||||
# Private
|
||||
[dependencies.md-5]
|
||||
@ -175,7 +185,7 @@ version = "1.0"
|
||||
[dev-dependencies.serde_test]
|
||||
version = "1.0.56"
|
||||
|
||||
[target.'cfg(target = "wasm32-unknown-unknown")'.dev-dependencies.wasm-bindgen]
|
||||
[target.'cfg(all(target_arch = "wasm32", target_vendor = "unknown", target_os = "unknown"))'.dev-dependencies.wasm-bindgen]
|
||||
version = "0.2"
|
||||
|
||||
[target.'cfg(all(target_arch = "wasm32", target_vendor = "unknown", target_os = "unknown"))'.dev-dependencies.wasm-bindgen-test]
|
||||
@ -190,6 +200,8 @@ version = "1"
|
||||
[workspace]
|
||||
members = [
|
||||
"macros",
|
||||
"rng",
|
||||
"examples",
|
||||
"tests/smoke-test",
|
||||
"tests/wasm32-getrandom-test",
|
||||
]
|
||||
|
26
rng/Cargo.toml
Normal file
26
rng/Cargo.toml
Normal file
@ -0,0 +1,26 @@
|
||||
[package]
|
||||
name = "uuid-rng-internal"
|
||||
version = "1.12.1"
|
||||
edition = "2018"
|
||||
authors = [
|
||||
"uuid-rs contributors"
|
||||
]
|
||||
categories = [
|
||||
"data-structures",
|
||||
"no-std",
|
||||
"parser-implementations",
|
||||
"wasm"
|
||||
]
|
||||
description = "Private implementation details of the uuid crate."
|
||||
documentation = "https://docs.rs/uuid"
|
||||
repository = "https://github.com/uuid-rs/uuid"
|
||||
license = "Apache-2.0 OR MIT"
|
||||
|
||||
# Forces a dependency on `getrandom`
|
||||
[dependencies.getrandom]
|
||||
version = "0.3"
|
||||
optional = true
|
||||
|
||||
[dependencies.rand]
|
||||
version = "0.9"
|
||||
optional = true
|
20
rng/src/lib.rs
Normal file
20
rng/src/lib.rs
Normal file
@ -0,0 +1,20 @@
|
||||
//! Implementation details for the `uuid` crate.
|
||||
//!
|
||||
//! This crate is not meant to be used directly. It
|
||||
//! allows `wasm32-unknown-unknown` users who aren't
|
||||
//! in a JS-enabled runtime to configure a source of
|
||||
//! randomness via `getrandom`:
|
||||
//!
|
||||
//! ```toml
|
||||
//! [dependencies.uuid]
|
||||
//! features = ["v4", "rng-getrandom"]
|
||||
//! ```
|
||||
|
||||
#[doc(hidden)]
|
||||
pub mod __private {
|
||||
#[cfg(feature = "getrandom")]
|
||||
pub use getrandom;
|
||||
|
||||
#[cfg(feature = "rand")]
|
||||
pub use rand;
|
||||
}
|
4
src/external/serde_support.rs
vendored
4
src/external/serde_support.rs
vendored
@ -145,7 +145,9 @@ impl<'de> Deserialize<'de> for NonNilUuid {
|
||||
{
|
||||
let uuid = Uuid::deserialize(deserializer)?;
|
||||
|
||||
NonNilUuid::try_from(uuid).map_err(|_| de::Error::invalid_value(de::Unexpected::Other("nil UUID"), &"a non-nil UUID"))
|
||||
NonNilUuid::try_from(uuid).map_err(|_| {
|
||||
de::Error::invalid_value(de::Unexpected::Other("nil UUID"), &"a non-nil UUID")
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -438,7 +438,13 @@ pub enum Variant {
|
||||
// NOTE: Also check `NonNilUuid` when ading new derives here
|
||||
#[cfg_attr(
|
||||
all(uuid_unstable, feature = "zerocopy"),
|
||||
derive(zerocopy::IntoBytes, zerocopy::FromBytes, zerocopy::KnownLayout, zerocopy::Immutable, zerocopy::Unaligned)
|
||||
derive(
|
||||
zerocopy::IntoBytes,
|
||||
zerocopy::FromBytes,
|
||||
zerocopy::KnownLayout,
|
||||
zerocopy::Immutable,
|
||||
zerocopy::Unaligned
|
||||
)
|
||||
)]
|
||||
#[cfg_attr(
|
||||
feature = "borsh",
|
||||
|
244
src/rng.rs
244
src/rng.rs
@ -1,9 +1,61 @@
|
||||
#[cfg(not(all(target_arch = "wasm32", target_vendor = "unknown", target_os = "unknown")))]
|
||||
#![allow(dead_code)] // Keeps our cfg's from becoming too convoluted in here
|
||||
|
||||
trait Rng {
|
||||
fn u128() -> u128;
|
||||
fn u64() -> u64;
|
||||
fn u16() -> u16;
|
||||
}
|
||||
|
||||
pub(crate) fn u128() -> u128 {
|
||||
imp::RngImp::u128()
|
||||
}
|
||||
|
||||
pub(crate) fn u64() -> u64 {
|
||||
imp::RngImp::u64()
|
||||
}
|
||||
|
||||
pub(crate) fn u16() -> u16 {
|
||||
imp::RngImp::u16()
|
||||
}
|
||||
|
||||
#[cfg(not(all(
|
||||
target_arch = "wasm32",
|
||||
target_vendor = "unknown",
|
||||
target_os = "unknown"
|
||||
)))]
|
||||
mod imp {
|
||||
#[cfg(any(feature = "v4", feature = "v7"))]
|
||||
pub(crate) fn u128() -> u128 {
|
||||
#[cfg(not(feature = "fast-rng"))]
|
||||
{
|
||||
/*
|
||||
Random support for non `wasm32-unknown-unknown` platforms.
|
||||
*/
|
||||
|
||||
use super::*;
|
||||
|
||||
// Using `rand`
|
||||
#[cfg(any(feature = "rng-rand", feature = "fast-rng"))]
|
||||
pub(super) struct RngImp;
|
||||
|
||||
#[cfg(any(feature = "rng-rand", feature = "fast-rng"))]
|
||||
impl Rng for RngImp {
|
||||
fn u128() -> u128 {
|
||||
rand::random()
|
||||
}
|
||||
|
||||
fn u64() -> u64 {
|
||||
rand::random()
|
||||
}
|
||||
|
||||
fn u16() -> u16 {
|
||||
rand::random()
|
||||
}
|
||||
}
|
||||
|
||||
// Using `getrandom`
|
||||
#[cfg(all(not(feature = "fast-rng"), not(feature = "rng-rand")))]
|
||||
pub(super) struct RngImp;
|
||||
|
||||
#[cfg(all(not(feature = "fast-rng"), not(feature = "rng-rand")))]
|
||||
impl Rng for RngImp {
|
||||
fn u128() -> u128 {
|
||||
let mut bytes = [0u8; 16];
|
||||
|
||||
getrandom::fill(&mut bytes).unwrap_or_else(|err| {
|
||||
@ -14,36 +66,7 @@ mod imp {
|
||||
u128::from_ne_bytes(bytes)
|
||||
}
|
||||
|
||||
#[cfg(feature = "fast-rng")]
|
||||
{
|
||||
rand::random()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "v1", feature = "v6"))]
|
||||
pub(crate) fn u16() -> u16 {
|
||||
#[cfg(not(feature = "fast-rng"))]
|
||||
{
|
||||
let mut bytes = [0u8; 2];
|
||||
|
||||
getrandom::fill(&mut bytes).unwrap_or_else(|err| {
|
||||
// NB: getrandom::Error has no source; this is adequate display
|
||||
panic!("could not retrieve random bytes for uuid: {}", err)
|
||||
});
|
||||
|
||||
u16::from_ne_bytes(bytes)
|
||||
}
|
||||
|
||||
#[cfg(feature = "fast-rng")]
|
||||
{
|
||||
rand::random()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "v7")]
|
||||
pub(crate) fn u64() -> u64 {
|
||||
#[cfg(not(feature = "fast-rng"))]
|
||||
{
|
||||
fn u64() -> u64 {
|
||||
let mut bytes = [0u8; 8];
|
||||
|
||||
getrandom::fill(&mut bytes).unwrap_or_else(|err| {
|
||||
@ -54,56 +77,142 @@ mod imp {
|
||||
u64::from_ne_bytes(bytes)
|
||||
}
|
||||
|
||||
#[cfg(feature = "fast-rng")]
|
||||
{
|
||||
rand::random()
|
||||
fn u16() -> u16 {
|
||||
let mut bytes = [0u8; 2];
|
||||
|
||||
getrandom::fill(&mut bytes).unwrap_or_else(|err| {
|
||||
// NB: getrandom::Error has no source; this is adequate display
|
||||
panic!("could not retrieve random bytes for uuid: {}", err)
|
||||
});
|
||||
|
||||
u16::from_ne_bytes(bytes)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "js", target_arch = "wasm32", target_vendor = "unknown", target_os = "unknown"))]
|
||||
#[cfg(all(
|
||||
target_arch = "wasm32",
|
||||
target_vendor = "unknown",
|
||||
target_os = "unknown"
|
||||
))]
|
||||
mod imp {
|
||||
/*
|
||||
This module preserves the stabilized behavior of `uuid` that requires the
|
||||
`js` feature to enable rng on `wasm32-unknown-unknown`, which it inherited
|
||||
from `getrandom` `0.2`
|
||||
Random support for `wasm32-unknown-unknown`.
|
||||
*/
|
||||
|
||||
#[cfg(any(feature = "v4", feature = "v7"))]
|
||||
pub(crate) fn u128() -> u128 {
|
||||
let mut bytes = [0u8; 16];
|
||||
use super::*;
|
||||
|
||||
if !getrandom::fill(&mut bytes) {
|
||||
panic!("could not retrieve random bytes for uuid")
|
||||
// Using `rand`
|
||||
#[cfg(feature = "rng-rand")]
|
||||
pub(super) struct RngImp;
|
||||
|
||||
#[cfg(feature = "rng-rand")]
|
||||
impl Rng for RngImp {
|
||||
fn u128() -> u128 {
|
||||
uuid_rng_internal_lib::__private::rand::random()
|
||||
}
|
||||
|
||||
u128::from_ne_bytes(bytes)
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "v1", feature = "v6"))]
|
||||
pub(crate) fn u16() -> u16 {
|
||||
let mut bytes = [0u8; 2];
|
||||
|
||||
if !getrandom::fill(&mut bytes) {
|
||||
panic!("could not retrieve random bytes for uuid")
|
||||
fn u64() -> u64 {
|
||||
uuid_rng_internal_lib::__private::rand::random()
|
||||
}
|
||||
|
||||
u16::from_ne_bytes(bytes)
|
||||
fn u16() -> u16 {
|
||||
uuid_rng_internal_lib::__private::rand::random()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "v7")]
|
||||
pub(crate) fn u64() -> u64 {
|
||||
let mut bytes = [0u8; 8];
|
||||
// Using `getrandom`
|
||||
#[cfg(all(feature = "rng-getrandom", not(feature = "rng-rand")))]
|
||||
pub(super) struct RngImp;
|
||||
|
||||
if !getrandom::fill(&mut bytes) {
|
||||
panic!("could not retrieve random bytes for uuid")
|
||||
#[cfg(all(feature = "rng-getrandom", not(feature = "rng-rand")))]
|
||||
impl Rng for RngImp {
|
||||
fn u128() -> u128 {
|
||||
let mut bytes = [0u8; 16];
|
||||
|
||||
uuid_rng_internal_lib::__private::getrandom::fill(&mut bytes).unwrap_or_else(|err| {
|
||||
// NB: getrandom::Error has no source; this is adequate display
|
||||
panic!("could not retrieve random bytes for uuid: {}", err)
|
||||
});
|
||||
|
||||
u128::from_ne_bytes(bytes)
|
||||
}
|
||||
|
||||
u64::from_ne_bytes(bytes)
|
||||
fn u64() -> u64 {
|
||||
let mut bytes = [0u8; 8];
|
||||
|
||||
uuid_rng_internal_lib::__private::getrandom::fill(&mut bytes).unwrap_or_else(|err| {
|
||||
// NB: getrandom::Error has no source; this is adequate display
|
||||
panic!("could not retrieve random bytes for uuid: {}", err)
|
||||
});
|
||||
|
||||
u64::from_ne_bytes(bytes)
|
||||
}
|
||||
|
||||
fn u16() -> u16 {
|
||||
let mut bytes = [0u8; 2];
|
||||
|
||||
uuid_rng_internal_lib::__private::getrandom::fill(&mut bytes).unwrap_or_else(|err| {
|
||||
// NB: getrandom::Error has no source; this is adequate display
|
||||
panic!("could not retrieve random bytes for uuid: {}", err)
|
||||
});
|
||||
|
||||
u16::from_ne_bytes(bytes)
|
||||
}
|
||||
}
|
||||
|
||||
mod getrandom {
|
||||
// Using WebCrypto via `wasm-bindgen`
|
||||
#[cfg(all(
|
||||
feature = "js",
|
||||
not(feature = "rng-rand"),
|
||||
not(feature = "rng-getrandom")
|
||||
))]
|
||||
pub(super) struct RngImp;
|
||||
|
||||
#[cfg(all(
|
||||
feature = "js",
|
||||
not(feature = "rng-rand"),
|
||||
not(feature = "rng-getrandom")
|
||||
))]
|
||||
impl Rng for RngImp {
|
||||
fn u128() -> u128 {
|
||||
let mut bytes = [0u8; 16];
|
||||
|
||||
if !webcrypto::fill(&mut bytes) {
|
||||
panic!("could not retrieve random bytes for uuid")
|
||||
}
|
||||
|
||||
u128::from_ne_bytes(bytes)
|
||||
}
|
||||
|
||||
fn u64() -> u64 {
|
||||
let mut bytes = [0u8; 8];
|
||||
|
||||
if !webcrypto::fill(&mut bytes) {
|
||||
panic!("could not retrieve random bytes for uuid")
|
||||
}
|
||||
|
||||
u64::from_ne_bytes(bytes)
|
||||
}
|
||||
|
||||
fn u16() -> u16 {
|
||||
let mut bytes = [0u8; 2];
|
||||
|
||||
if !webcrypto::fill(&mut bytes) {
|
||||
panic!("could not retrieve random bytes for uuid")
|
||||
}
|
||||
|
||||
u16::from_ne_bytes(bytes)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "js")]
|
||||
mod webcrypto {
|
||||
/*
|
||||
This module preserves the stabilized behavior of `uuid` that requires the
|
||||
`js` feature to enable rng on `wasm32-unknown-unknown`, which it inherited
|
||||
from `getrandom` `0.2`.
|
||||
|
||||
Vendored from `getrandom`: https://github.com/rust-random/getrandom/blob/ce3b017fdee0233c6ecd61e68b96a84bf6f911bf/src/backends/wasm_js.rs
|
||||
|
||||
Copyright (c) 2018-2024 The rust-random Project Developers
|
||||
@ -180,7 +289,7 @@ mod imp {
|
||||
|
||||
sub_buf.copy_to_uninit(chunk);
|
||||
}
|
||||
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
@ -196,8 +305,3 @@ mod imp {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(not(feature = "js"), target_arch = "wasm32", target_vendor = "unknown", target_os = "unknown"))]
|
||||
compile_error!("the `js` feature is required for the `wasm32-unknown-unknown` target");
|
||||
|
||||
pub(crate) use self::imp::*;
|
||||
|
21
tests/wasm32-getrandom-test/Cargo.toml
Normal file
21
tests/wasm32-getrandom-test/Cargo.toml
Normal file
@ -0,0 +1,21 @@
|
||||
[package]
|
||||
name = "uuid-wasm32-getrandom-test"
|
||||
version = "0.1.0"
|
||||
edition = "2018"
|
||||
|
||||
[features]
|
||||
rand = ["uuid/rng-rand"]
|
||||
|
||||
[dependencies.uuid]
|
||||
path = "../../"
|
||||
features = ["v4", "rng-getrandom"]
|
||||
|
||||
[dependencies.getrandom]
|
||||
version = "0.3"
|
||||
features = ["wasm_js"]
|
||||
|
||||
[dependencies.wasm-bindgen]
|
||||
version = "0.2"
|
||||
|
||||
[dependencies.wasm-bindgen-test]
|
||||
version = "0.3"
|
14
tests/wasm32-getrandom-test/src/lib.rs
Normal file
14
tests/wasm32-getrandom-test/src/lib.rs
Normal file
@ -0,0 +1,14 @@
|
||||
#![cfg(test)]
|
||||
|
||||
use uuid::{Uuid, Variant, Version};
|
||||
|
||||
use wasm_bindgen_test::*;
|
||||
|
||||
#[test]
|
||||
#[wasm_bindgen_test]
|
||||
fn test_new() {
|
||||
let uuid = Uuid::new_v4();
|
||||
|
||||
assert_eq!(uuid.get_version(), Some(Version::Random));
|
||||
assert_eq!(uuid.get_variant(), Variant::RFC4122);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user