diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b41f2bc..c755b3f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -56,6 +56,8 @@ jobs: - run: cargo test --verbose - run: cargo build --verbose --manifest-path quickcheck_macros/Cargo.toml - run: cargo test --verbose --manifest-path quickcheck_macros/Cargo.toml + # Make sure that the crate compiles if all features flags are switched on at the same time. + - run: cargo check --all-features --verbose rustfmt: name: rustfmt diff --git a/Cargo.toml b/Cargo.toml index 75083f4..d2470c9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,6 +20,7 @@ members = ["quickcheck_macros"] default = ["regex", "use_logging"] use_logging = ["log", "env_logger"] regex = ["env_logger/regex"] +use_rand_core_0_6 = ["rand_core_0_6"] [lib] name = "quickcheck" @@ -28,3 +29,4 @@ name = "quickcheck" env_logger = { version = "0.8.2", default-features = false, optional = true } log = { version = "0.4", optional = true } rand = { version = "0.8", default-features = false, features = ["getrandom", "small_rng"] } +rand_core_0_6 = { package = "rand_core", version = "0.6", default-features = false, optional = true } diff --git a/README.md b/README.md index 2546a63..dd49ca7 100644 --- a/README.md +++ b/README.md @@ -125,6 +125,8 @@ Crate features: `RUST_LOG`. - `"regex"`: (Enabled by default.) Enables the use of regexes with `env_logger`. +- `"use_rand_core_0_6"`: (Disabled by default.) Provides an implementation of + `rand_core::RngCore` for `quickcheck::Gen` using version `0.6` of `rand_core`. ### Minimum Rust version policy @@ -140,10 +142,9 @@ version of Rust. In general, this crate will be conservative with respect to the minimum supported version of Rust. -With all of that said, currently, `rand` is a public dependency of -`quickcheck`. Therefore, the MSRV policy above only applies when it is more -aggressive than `rand`'s MSRV policy. Otherwise, `quickcheck` will defer to -`rand`'s MSRV policy. +If you are opting-in to use the `rand_core_X_X` feature flags, the MSRV policy +above only applies when it is more aggressive than `rand`'s MSRV policy. +Otherwise, `quickcheck` will defer to `rand`'s MSRV policy. ### Compatibility diff --git a/src/arbitrary.rs b/src/arbitrary.rs index 13b5b65..f46a5d2 100644 --- a/src/arbitrary.rs +++ b/src/arbitrary.rs @@ -24,6 +24,8 @@ use std::time::{Duration, SystemTime, UNIX_EPOCH}; use rand::seq::SliceRandom; use rand::{self, Rng, SeedableRng}; +mod rand_rng_impl; + /// Gen represents a PRNG. /// /// It is the source of randomness from which QuickCheck will generate diff --git a/src/arbitrary/rand_rng_impl.rs b/src/arbitrary/rand_rng_impl.rs new file mode 100644 index 0000000..4a97088 --- /dev/null +++ b/src/arbitrary/rand_rng_impl.rs @@ -0,0 +1,32 @@ +//! Implement the `RngCore` trait from `rand_core` for `quickcheck::Gen`. +//! This allows `quickcheck` to interoperate with other crates that rely on `rand_core`/`rand` as +//! their interface for sources of randomness. +//! +//! The `RngCore` implementations are gated behind opt-in feature flags that are explicitly tied to a +//! pinned version of `rand_core`. +//! If a new version of `rand_core` is released, `quickcheck` can add a new `use_rand_core_X_X` +//! feature flag to enable interoperability without compromising its API stability guarantees. + +#[cfg(feature = "use_rand_core_0_6")] +mod rand_core_0_6 { + use crate::Gen; + use rand::Error; + + impl rand_core_0_6::RngCore for Gen { + fn next_u32(&mut self) -> u32 { + self.rng.next_u32() + } + + fn next_u64(&mut self) -> u64 { + self.rng.next_u64() + } + + fn fill_bytes(&mut self, dest: &mut [u8]) { + self.rng.fill_bytes(dest) + } + + fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> { + self.rng.try_fill_bytes(dest) + } + } +}