mirror of
https://github.com/uuid-rs/uuid.git
synced 2025-09-28 05:22:02 +00:00
vendor in rng for wasm, upgrade getrandom and rand to latest
This commit is contained in:
parent
70831d21b3
commit
0729e00286
15
Cargo.toml
15
Cargo.toml
@ -68,7 +68,7 @@ v6 = ["atomic"]
|
||||
v7 = ["rng"]
|
||||
v8 = []
|
||||
|
||||
js = ["dep:wasm-bindgen", "getrandom?/js"]
|
||||
js = ["dep:wasm-bindgen"]
|
||||
|
||||
rng = ["dep:getrandom"]
|
||||
fast-rng = ["rng", "dep:rand"]
|
||||
@ -123,17 +123,16 @@ optional = true
|
||||
version = "1"
|
||||
default-features = false
|
||||
|
||||
# Public
|
||||
# Usage of `getrandom`'s pluggable randomness for custom targets is documented
|
||||
# in `uuid`'s library docs
|
||||
[dependencies.getrandom]
|
||||
# Private
|
||||
# (Formally public)
|
||||
[target.'cfg(not(all(target_arch = "wasm32", target_vendor = "unknown", target_os = "unknown")))'.dependencies.getrandom]
|
||||
optional = true
|
||||
version = "0.2"
|
||||
version = "0.3"
|
||||
|
||||
# Private
|
||||
[dependencies.rand]
|
||||
[target.'cfg(not(all(target_arch = "wasm32", target_vendor = "unknown", target_os = "unknown")))'.dependencies.rand]
|
||||
optional = true
|
||||
version = "0.8"
|
||||
version = "0.9"
|
||||
|
||||
# Private
|
||||
[dependencies.md-5]
|
||||
|
10
src/lib.rs
10
src/lib.rs
@ -163,11 +163,13 @@
|
||||
//! * `serde`.
|
||||
//!
|
||||
//! If you need to use `v4` or `v7` in a no-std environment, you'll need to
|
||||
//! follow [`getrandom`'s docs] on configuring a source of randomness
|
||||
//! on currently unsupported targets. Alternatively, you can produce
|
||||
//! random bytes yourself and then pass them to [`Builder::from_random_bytes`]
|
||||
//! produce random bytes yourself and then pass them to [`Builder::from_random_bytes`]
|
||||
//! without enabling the `v4` or `v7` features.
|
||||
//!
|
||||
//! Versions of `uuid` `1.12` or earlier relied on `getrandom` for randomness, this
|
||||
//! is no longer guaranteed and configuring `getrandom`'s provider is not guaranteed
|
||||
//! to make other features relying on randomness work.
|
||||
//!
|
||||
//! # Examples
|
||||
//!
|
||||
//! Parse a UUID given in the simple format and print it as a URN:
|
||||
@ -202,8 +204,6 @@
|
||||
//! * [RFC 9562: Universally Unique IDentifiers (UUID)](https://www.ietf.org/rfc/rfc9562.html).
|
||||
//!
|
||||
//! [`wasm-bindgen`]: https://crates.io/crates/wasm-bindgen
|
||||
//! [`cargo-web`]: https://crates.io/crates/cargo-web
|
||||
//! [`getrandom`'s docs]: https://docs.rs/getrandom
|
||||
|
||||
#![no_std]
|
||||
#![deny(missing_debug_implementations, missing_docs)]
|
||||
|
222
src/rng.rs
222
src/rng.rs
@ -1,59 +1,203 @@
|
||||
#[cfg(any(feature = "v4", feature = "v7"))]
|
||||
pub(crate) fn u128() -> u128 {
|
||||
#[cfg(not(feature = "fast-rng"))]
|
||||
{
|
||||
#[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"))]
|
||||
{
|
||||
let mut bytes = [0u8; 16];
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
#[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"))]
|
||||
{
|
||||
let mut bytes = [0u8; 8];
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
#[cfg(feature = "fast-rng")]
|
||||
{
|
||||
rand::random()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "js", 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`
|
||||
*/
|
||||
|
||||
#[cfg(any(feature = "v4", feature = "v7"))]
|
||||
pub(crate) fn u128() -> u128 {
|
||||
let mut bytes = [0u8; 16];
|
||||
|
||||
getrandom::getrandom(&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)
|
||||
});
|
||||
if !getrandom::fill(&mut bytes) {
|
||||
panic!("could not retrieve random bytes for uuid")
|
||||
}
|
||||
|
||||
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"))]
|
||||
{
|
||||
#[cfg(any(feature = "v1", feature = "v6"))]
|
||||
pub(crate) fn u16() -> u16 {
|
||||
let mut bytes = [0u8; 2];
|
||||
|
||||
getrandom::getrandom(&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)
|
||||
});
|
||||
if !getrandom::fill(&mut bytes) {
|
||||
panic!("could not retrieve random bytes for uuid")
|
||||
}
|
||||
|
||||
u16::from_ne_bytes(bytes)
|
||||
}
|
||||
|
||||
#[cfg(feature = "fast-rng")]
|
||||
{
|
||||
rand::random()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "v7")]
|
||||
pub(crate) fn u64() -> u64 {
|
||||
#[cfg(not(feature = "fast-rng"))]
|
||||
{
|
||||
#[cfg(feature = "v7")]
|
||||
pub(crate) fn u64() -> u64 {
|
||||
let mut bytes = [0u8; 8];
|
||||
|
||||
getrandom::getrandom(&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)
|
||||
});
|
||||
if !getrandom::fill(&mut bytes) {
|
||||
panic!("could not retrieve random bytes for uuid")
|
||||
}
|
||||
|
||||
u64::from_ne_bytes(bytes)
|
||||
}
|
||||
|
||||
#[cfg(feature = "fast-rng")]
|
||||
{
|
||||
rand::random()
|
||||
mod getrandom {
|
||||
/*
|
||||
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
|
||||
Copyright (c) 2014 The Rust Project Developers
|
||||
|
||||
Permission is hereby granted, free of charge, to any
|
||||
person obtaining a copy of this software and associated
|
||||
documentation files (the "Software"), to deal in the
|
||||
Software without restriction, including without
|
||||
limitation the rights to use, copy, modify, merge,
|
||||
publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software
|
||||
is furnished to do so, subject to the following
|
||||
conditions:
|
||||
|
||||
The above copyright notice and this permission notice
|
||||
shall be included in all copies or substantial portions
|
||||
of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
|
||||
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
use wasm_bindgen::{prelude::wasm_bindgen, JsValue};
|
||||
|
||||
// Maximum buffer size allowed in `Crypto.getRandomValuesSize` is 65536 bytes.
|
||||
// See https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues
|
||||
const MAX_BUFFER_SIZE: usize = 65536;
|
||||
|
||||
#[cfg(not(target_feature = "atomics"))]
|
||||
#[inline]
|
||||
pub fn fill(dest: &mut [u8]) -> bool {
|
||||
for chunk in dest.chunks_mut(MAX_BUFFER_SIZE) {
|
||||
if get_random_values(chunk).is_err() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
#[cfg(target_feature = "atomics")]
|
||||
pub fn fill(dest: &mut [u8]) -> bool {
|
||||
// getRandomValues does not work with all types of WASM memory,
|
||||
// so we initially write to browser memory to avoid exceptions.
|
||||
let buf_len = usize::min(dest.len(), MAX_BUFFER_SIZE);
|
||||
let buf_len_u32 = buf_len
|
||||
.try_into()
|
||||
.expect("buffer length is bounded by MAX_BUFFER_SIZE");
|
||||
let buf = js_sys::Uint8Array::new_with_length(buf_len_u32);
|
||||
for chunk in dest.chunks_mut(buf_len) {
|
||||
let chunk_len = chunk
|
||||
.len()
|
||||
.try_into()
|
||||
.expect("chunk length is bounded by MAX_BUFFER_SIZE");
|
||||
// The chunk can be smaller than buf's length, so we call to
|
||||
// JS to create a smaller view of buf without allocation.
|
||||
let sub_buf = if chunk_len == buf_len_u32 {
|
||||
&buf
|
||||
} else {
|
||||
&buf.subarray(0, chunk_len)
|
||||
};
|
||||
|
||||
if get_random_values(sub_buf).is_err() {
|
||||
return false;
|
||||
}
|
||||
|
||||
sub_buf.copy_to_uninit(chunk);
|
||||
}
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
extern "C" {
|
||||
// Crypto.getRandomValues()
|
||||
#[cfg(not(target_feature = "atomics"))]
|
||||
#[wasm_bindgen(js_namespace = ["globalThis", "crypto"], js_name = getRandomValues, catch)]
|
||||
fn get_random_values(buf: &mut [u8]) -> Result<(), JsValue>;
|
||||
#[cfg(target_feature = "atomics")]
|
||||
#[wasm_bindgen(js_namespace = ["globalThis", "crypto"], js_name = getRandomValues, catch)]
|
||||
fn get_random_values(buf: &js_sys::Uint8Array) -> Result<(), JsValue>;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[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::*;
|
||||
|
Loading…
x
Reference in New Issue
Block a user