diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index dd6138f7..f6e12dba 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -100,6 +100,9 @@ jobs: - name: Version features run: wasm-pack test --node -- --features "js v1 v3 v4 v5" + + - name: Fast rng + run: wasm-pack test --node -- --features "js v4 fast-rng" embedded: name: Build / Embedded diff --git a/Cargo.toml b/Cargo.toml index 18ffc877..1e8deaa0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -53,15 +53,21 @@ repository = "uuid-rs/uuid" [features] default = ["std"] -guid = ["winapi"] std = [] macros = ["uuid-macros"] + v1 = ["atomic"] v3 = ["md-5"] -v4 = ["getrandom"] +v4 = ["rng"] v5 = ["sha-1"] + +guid = ["winapi"] + js = ["getrandom", "getrandom/js"] +rng = ["getrandom"] +fast-rng = ["rng", "rand"] + # Unstable features (these also need RUSTFLAGS="--cfg uuid_unstable" to work) zerocopy-unstable = ["zerocopy"] @@ -70,6 +76,11 @@ zerocopy-unstable = ["zerocopy"] optional = true version = "0.2" +# Private +[dependencies.rand] +optional = true +version = "0.8" + # Private [dependencies.atomic] default-features = false diff --git a/README.md b/README.md index 888e5260..a6740b39 100644 --- a/README.md +++ b/README.md @@ -45,6 +45,9 @@ various pieces of functionality: UUID based on the SHA1 hash of some data. * `serde` - adds the ability to serialize and deserialize a `Uuid` using the `serde` crate. +* `fast-rng` - when combined with `v4` uses a faster algorithm for generating + random UUIDs. This feature requires more dependencies to compile, but is just + as suitable for UUIDs as the default algorithm. You need to enable one of the following Cargo features together with the `v4` feature if you're targeting `wasm32-unknown-unknown` target: diff --git a/benches/v4.rs b/benches/v4.rs new file mode 100644 index 00000000..573fc690 --- /dev/null +++ b/benches/v4.rs @@ -0,0 +1,12 @@ +#![cfg(feature = "v4")] + +#![feature(test)] +extern crate test; + +use test::Bencher; +use uuid::Uuid; + +#[bench] +fn new_v4(b: &mut Bencher) { + b.iter(|| Uuid::new_v4()); +} diff --git a/src/lib.rs b/src/lib.rs index 45e3978e..4c5dd0c5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -42,6 +42,9 @@ //! UUID based on the SHA1 hash of some data. //! * `serde` - adds the ability to serialize and deserialize a UUID using the //! `serde` crate. +//! * `fast-rng` - when combined with `v4` uses a faster algorithm for generating +//! random UUIDs. This feature requires more dependencies to compile, but is just +//! as suitable for UUIDs as the default algorithm. //! //! By default, `uuid` can be depended on with: //! @@ -54,7 +57,7 @@ //! //! ```toml //! [dependencies] -//! uuid = { version = "0.8", features = ["serde", "v4"] } +//! uuid = { version = "0.8", features = ["serde", "v4", "fast-rng"] } //! ``` //! //! You can disable default features with: @@ -190,19 +193,22 @@ mod error; mod parser; pub mod fmt; + #[cfg(feature = "v1")] pub mod v1; - -#[cfg(feature = "serde")] -mod serde_support; -#[cfg(feature = "slog")] -mod slog_support; #[cfg(feature = "v3")] mod v3; #[cfg(feature = "v4")] mod v4; #[cfg(feature = "v5")] mod v5; + +#[cfg(feature = "rng")] +mod rng; +#[cfg(feature = "serde")] +mod serde_support; +#[cfg(feature = "slog")] +mod slog_support; #[cfg(all(windows, feature = "winapi"))] mod winapi_support; diff --git a/src/rng.rs b/src/rng.rs new file mode 100644 index 00000000..68936595 --- /dev/null +++ b/src/rng.rs @@ -0,0 +1,25 @@ +#[cfg(feature = "v4")] +pub(crate) fn bytes() -> [u8; 16] { + #[cfg(not(feature = "fast-rng"))] + { + 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) + }); + + bytes + } + + #[cfg(feature = "fast-rng")] + { + use rand::RngCore; + let mut rng = rand::thread_rng(); + + let mut bytes = [0u8; 16]; + rng.fill_bytes(&mut bytes); + + bytes + } +} diff --git a/src/v4.rs b/src/v4.rs index 0e693064..f122c13a 100644 --- a/src/v4.rs +++ b/src/v4.rs @@ -27,13 +27,7 @@ impl Uuid { /// [`getrandom`]: https://crates.io/crates/getrandom /// [from_random_bytes]: struct.Builder.html#method.from_random_bytes pub fn new_v4() -> Uuid { - 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) - }); - - crate::Builder::from_bytes(bytes) + crate::Builder::from_bytes(crate::rng::bytes()) .set_variant(Variant::RFC4122) .set_version(Version::Random) .build()