diff --git a/.github/workflows/gh-pages.yml b/.github/workflows/gh-pages.yml index c0cab03b92..1d83a77bd7 100644 --- a/.github/workflows/gh-pages.yml +++ b/.github/workflows/gh-pages.yml @@ -30,7 +30,7 @@ jobs: RUSTDOCFLAGS: --cfg doc_cfg # --all builds all crates, but with default features for other crates (okay in this case) run: | - cargo doc --all --features nightly,serde,getrandom,small_rng + cargo doc --all --all-features --no-deps cp utils/redirect.html target/doc/index.html rm target/doc/.lock diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 4a05842243..4a8989c513 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -90,8 +90,8 @@ jobs: - name: Test rand run: | cargo test --target ${{ matrix.target }} --lib --tests --no-default-features - cargo build --target ${{ matrix.target }} --no-default-features --features alloc,getrandom,small_rng,unbiased - cargo test --target ${{ matrix.target }} --lib --tests --no-default-features --features=alloc,getrandom,small_rng + cargo build --target ${{ matrix.target }} --no-default-features --features alloc,os_rng,small_rng,unbiased + cargo test --target ${{ matrix.target }} --lib --tests --no-default-features --features=alloc,os_rng,small_rng cargo test --target ${{ matrix.target }} --examples - name: Test rand (all stable features) run: | @@ -100,7 +100,7 @@ jobs: run: | cargo test --target ${{ matrix.target }} --manifest-path rand_core/Cargo.toml cargo test --target ${{ matrix.target }} --manifest-path rand_core/Cargo.toml --no-default-features - cargo test --target ${{ matrix.target }} --manifest-path rand_core/Cargo.toml --no-default-features --features=alloc,getrandom + cargo test --target ${{ matrix.target }} --manifest-path rand_core/Cargo.toml --no-default-features --features=alloc,os_rng - name: Test rand_distr run: | cargo test --target ${{ matrix.target }} --manifest-path rand_distr/Cargo.toml --features=serde diff --git a/CHANGELOG.md b/CHANGELOG.md index 8a9fc39ab3..3e53dc3ba2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -34,6 +34,7 @@ You may also find the [Upgrade Guide](https://rust-random.github.io/book/update. - Remove impl of `Distribution>` for `Standard` (#1526) - Remove `SmallRng::from_thread_rng` (#1532) - Remove first parameter (`rng`) of `ReseedingRng::new` (#1533) +- Rename feature `getrandom` to `os_rng` ## [0.9.0-alpha.1] - 2024-03-18 - Add the `Slice::num_choices` method to the Slice distribution (#1402) diff --git a/Cargo.toml b/Cargo.toml index 73a36ac6c5..b5b254ba2a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,7 +28,7 @@ features = ["small_rng", "serde"] [features] # Meta-features: -default = ["std", "std_rng", "getrandom", "small_rng"] +default = ["std", "std_rng", "os_rng", "small_rng"] nightly = [] # some additions requiring nightly Rust serde = ["dep:serde", "rand_core/serde"] @@ -39,8 +39,8 @@ std = ["rand_core/std", "rand_chacha?/std", "alloc"] # Option: "alloc" enables support for Vec and Box when not using "std" alloc = ["rand_core/alloc"] -# Option: use getrandom package for seeding -getrandom = ["rand_core/getrandom"] +# Option: enable OsRng +os_rng = ["rand_core/os_rng"] # Option (requires nightly Rust): experimental SIMD support simd_support = ["zerocopy/simd-nightly"] diff --git a/README.md b/README.md index b8e089099f..0ac3aaac18 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ Rand is a set of crates supporting (pseudo-)random generators: - With fast implementations of both [strong](https://rust-random.github.io/book/guide-rngs.html#cryptographically-secure-pseudo-random-number-generators-csprngs) and [small](https://rust-random.github.io/book/guide-rngs.html#basic-pseudo-random-number-generators-prngs) generators: [`rand::rngs`](https://docs.rs/rand/latest/rand/rngs/index.html), and more RNGs: [`rand_chacha`](https://docs.rs/rand_chacha), [`rand_xoshiro`](https://docs.rs/rand_xoshiro/), [`rand_pcg`](https://docs.rs/rand_pcg/), [rngs repo](https://github.com/rust-random/rngs/) - [`rand::rng`](https://docs.rs/rand/latest/rand/fn.rng.html) is an asymptotically-fast, automatically-seeded and reasonably strong generator available on all `std` targets -- Direct support for seeding generators from the [`getrandom` crate](https://crates.io/crates/getrandom) +- Direct support for seeding generators from the [getrandom] crate With broad support for random value generation and random processes: @@ -80,8 +80,7 @@ Rand is built with these features enabled by default: - `std` enables functionality dependent on the `std` lib - `alloc` (implied by `std`) enables functionality requiring an allocator -- `getrandom` (implied by `std`) is an optional dependency providing the code - behind `rngs::OsRng` +- `os_rng` (implied by `std`) enables `rngs::OsRng`, using the [getrandom] crate - `std_rng` enables inclusion of `StdRng`, `ThreadRng` Optionally, the following dependencies can be enabled: @@ -101,23 +100,23 @@ experimental `simd_support` feature. Rand supports limited functionality in `no_std` mode (enabled via `default-features = false`). In this case, `OsRng` and `from_os_rng` are -unavailable (unless `getrandom` is enabled), large parts of `seq` are +unavailable (unless `os_rng` is enabled), large parts of `seq` are unavailable (unless `alloc` is enabled), and `ThreadRng` is unavailable. ## Portability and platform support Many (but not all) algorithms are intended to have reproducible output. Read more in the book: [Portability](https://rust-random.github.io/book/portability.html). -The Rand library supports a variety of CPU architectures. Platform integration is outsourced to [getrandom](https://docs.rs/getrandom/latest/getrandom/). +The Rand library supports a variety of CPU architectures. Platform integration is outsourced to [getrandom]. ### WASM support Seeding entropy from OS on WASM target `wasm32-unknown-unknown` is not *automatically* supported by `rand` or `getrandom`. If you are fine with -seeding the generator manually, you can disable the `getrandom` feature +seeding the generator manually, you can disable the `os_rng` feature and use the methods on the `SeedableRng` trait. To enable seeding from OS, either use a different target such as `wasm32-wasi` or add a direct -dependency on `getrandom` with the `js` feature (if the target supports +dependency on [getrandom] with the `js` feature (if the target supports JavaScript). See [getrandom#WebAssembly support](https://docs.rs/getrandom/latest/getrandom/#webassembly-support). @@ -128,3 +127,5 @@ Apache License (Version 2.0). See [LICENSE-APACHE](LICENSE-APACHE) and [LICENSE-MIT](LICENSE-MIT), and [COPYRIGHT](COPYRIGHT) for details. + +[getrandom]: https://crates.io/crates/getrandom diff --git a/rand_chacha/CHANGELOG.md b/rand_chacha/CHANGELOG.md index 8543c1e403..68dba7dfdc 100644 --- a/rand_chacha/CHANGELOG.md +++ b/rand_chacha/CHANGELOG.md @@ -6,6 +6,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] - The `serde1` feature has been renamed `serde` (#1477) +- Rename feature `getrandom` to `os_rng` ## [0.9.0-alpha.1] - 2024-03-18 diff --git a/rand_chacha/Cargo.toml b/rand_chacha/Cargo.toml index 385b9a6eed..168b39def5 100644 --- a/rand_chacha/Cargo.toml +++ b/rand_chacha/Cargo.toml @@ -27,10 +27,10 @@ serde = { version = "1.0", features = ["derive"], optional = true } [dev-dependencies] # Only to test serde serde_json = "1.0" -rand_core = { path = "../rand_core", version = "=0.9.0-alpha.1", features = ["getrandom"] } +rand_core = { path = "../rand_core", version = "=0.9.0-alpha.1", features = ["os_rng"] } [features] default = ["std"] -getrandom = ["rand_core/getrandom"] +os_rng = ["rand_core/os_rng"] std = ["ppv-lite86/std", "rand_core/std"] serde = ["dep:serde"] diff --git a/rand_chacha/README.md b/rand_chacha/README.md index 1b555ad086..35a49a366d 100644 --- a/rand_chacha/README.md +++ b/rand_chacha/README.md @@ -36,7 +36,7 @@ Links: `rand_chacha` is `no_std` compatible when disabling default features; the `std` feature can be explicitly required to re-enable `std` support. Using `std` allows detection of CPU features and thus better optimisation. Using `std` -also enables `getrandom` functionality, such as `ChaCha20Rng::from_os_rng()`. +also enables `os_rng` functionality, such as `ChaCha20Rng::from_os_rng()`. # License diff --git a/rand_core/CHANGELOG.md b/rand_core/CHANGELOG.md index c8876be32e..a2d60c2da1 100644 --- a/rand_core/CHANGELOG.md +++ b/rand_core/CHANGELOG.md @@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] - Bump the MSRV to 1.63.0 - The `serde1` feature has been renamed `serde` (#1477) +- Rename feature `getrandom` to `os_rng` ## [0.9.0-alpha.1] - 2024-03-18 diff --git a/rand_core/Cargo.toml b/rand_core/Cargo.toml index 5870328c17..6f11b895a3 100644 --- a/rand_core/Cargo.toml +++ b/rand_core/Cargo.toml @@ -27,7 +27,7 @@ all-features = true [features] std = ["alloc", "getrandom?/std"] alloc = [] # enables Vec and Box support without std -getrandom = ["dep:getrandom"] +os_rng = ["dep:getrandom"] serde = ["dep:serde"] # enables serde for BlockRng wrapper [dependencies] diff --git a/rand_core/src/lib.rs b/rand_core/src/lib.rs index 4e75faf25b..adc7177081 100644 --- a/rand_core/src/lib.rs +++ b/rand_core/src/lib.rs @@ -45,13 +45,11 @@ use core::{fmt, ops::DerefMut}; pub mod block; pub mod impls; pub mod le; -#[cfg(feature = "getrandom")] +#[cfg(feature = "os_rng")] mod os; -#[cfg(feature = "getrandom")] -pub use getrandom; -#[cfg(feature = "getrandom")] -pub use os::OsRng; +#[cfg(feature = "os_rng")] +pub use os::{OsError, OsRng}; /// Implementation-level interface for RNGs /// @@ -495,7 +493,7 @@ pub trait SeedableRng: Sized { /// /// [`getrandom`]: https://docs.rs/getrandom /// [`try_from_os_rng`]: SeedableRng::try_from_os_rng - #[cfg(feature = "getrandom")] + #[cfg(feature = "os_rng")] fn from_os_rng() -> Self { match Self::try_from_os_rng() { Ok(res) => res, @@ -511,7 +509,7 @@ pub trait SeedableRng: Sized { /// `from_rng(&mut rand::rng()).unwrap()`. /// /// [`getrandom`]: https://docs.rs/getrandom - #[cfg(feature = "getrandom")] + #[cfg(feature = "os_rng")] fn try_from_os_rng() -> Result { let mut seed = Self::Seed::default(); getrandom::getrandom(seed.as_mut())?; diff --git a/rand_core/src/os.rs b/rand_core/src/os.rs index 78b689bc02..44efe700c1 100644 --- a/rand_core/src/os.rs +++ b/rand_core/src/os.rs @@ -19,7 +19,7 @@ use getrandom::getrandom; /// [getrandom] documentation for details. /// /// This struct is available as `rand_core::OsRng` and as `rand::rngs::OsRng`. -/// In both cases, this requires the crate feature `getrandom` or `std` +/// In both cases, this requires the crate feature `os_rng` or `std` /// (enabled by default in `rand` but not in `rand_core`). /// /// # Blocking and error handling @@ -47,26 +47,69 @@ use getrandom::getrandom; #[derive(Clone, Copy, Debug, Default)] pub struct OsRng; +/// Error type of [`OsRng`] +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct OsError(getrandom::Error); + +impl core::fmt::Display for OsError { + #[inline] + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + self.0.fmt(f) + } +} + +// NOTE: this can use core::error::Error from rustc 1.81.0 +#[cfg(feature = "std")] +impl std::error::Error for OsError { + #[inline] + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + std::error::Error::source(&self.0) + } +} + +impl OsError { + /// Extract the raw OS error code (if this error came from the OS) + /// + /// This method is identical to [`std::io::Error::raw_os_error()`][1], except + /// that it works in `no_std` contexts. If this method returns `None`, the + /// error value can still be formatted via the `Display` implementation. + /// + /// [1]: https://doc.rust-lang.org/std/io/struct.Error.html#method.raw_os_error + #[inline] + pub fn raw_os_error(self) -> Option { + self.0.raw_os_error() + } + + /// Extract the bare error code. + /// + /// This code can either come from the underlying OS, or be a custom error. + /// Use [`OsError::raw_os_error()`] to disambiguate. + #[inline] + pub const fn code(self) -> core::num::NonZeroU32 { + self.0.code() + } +} + impl TryRngCore for OsRng { - type Error = getrandom::Error; + type Error = OsError; #[inline] fn try_next_u32(&mut self) -> Result { let mut buf = [0u8; 4]; - getrandom(&mut buf)?; + getrandom(&mut buf).map_err(OsError)?; Ok(u32::from_ne_bytes(buf)) } #[inline] fn try_next_u64(&mut self) -> Result { let mut buf = [0u8; 8]; - getrandom(&mut buf)?; + getrandom(&mut buf).map_err(OsError)?; Ok(u64::from_ne_bytes(buf)) } #[inline] fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Self::Error> { - getrandom(dest)?; + getrandom(dest).map_err(OsError)?; Ok(()) } } diff --git a/rand_pcg/CHANGELOG.md b/rand_pcg/CHANGELOG.md index 80940a93a0..0133909a97 100644 --- a/rand_pcg/CHANGELOG.md +++ b/rand_pcg/CHANGELOG.md @@ -6,6 +6,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] - The `serde1` feature has been renamed `serde` (#1477) +- Rename feature `getrandom` to `os_rng` ## [0.9.0-alpha.1] - 2024-03-18 diff --git a/rand_pcg/Cargo.toml b/rand_pcg/Cargo.toml index a66abb0521..fb4dd17b00 100644 --- a/rand_pcg/Cargo.toml +++ b/rand_pcg/Cargo.toml @@ -21,7 +21,7 @@ rustdoc-args = ["--generate-link-to-definition"] [features] serde = ["dep:serde"] -getrandom = ["rand_core/getrandom"] +os_rng = ["rand_core/os_rng"] [dependencies] rand_core = { path = "../rand_core", version = "=0.9.0-alpha.1" } @@ -32,4 +32,4 @@ serde = { version = "1", features = ["derive"], optional = true } # deps yet, see: https://github.com/rust-lang/cargo/issues/1596 # Versions prior to 1.1.4 had incorrect minimal dependencies. bincode = { version = "1.1.4" } -rand_core = { path = "../rand_core", version = "=0.9.0-alpha.1", features = ["getrandom"] } +rand_core = { path = "../rand_core", version = "=0.9.0-alpha.1", features = ["os_rng"] } diff --git a/src/lib.rs b/src/lib.rs index 5b410ca8cb..192605a502 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -103,13 +103,13 @@ pub mod rngs; pub mod seq; // Public exports -#[cfg(all(feature = "std", feature = "std_rng", feature = "getrandom"))] +#[cfg(all(feature = "std", feature = "std_rng", feature = "os_rng"))] pub use crate::rngs::thread::rng; /// Access the thread-local generator /// /// Use [`rand::rng()`](rng()) instead. -#[cfg(all(feature = "std", feature = "std_rng", feature = "getrandom"))] +#[cfg(all(feature = "std", feature = "std_rng", feature = "os_rng"))] #[deprecated(since = "0.9.0", note = "renamed to `rng`")] #[inline] pub fn thread_rng() -> crate::rngs::ThreadRng { @@ -118,7 +118,7 @@ pub fn thread_rng() -> crate::rngs::ThreadRng { pub use rng::{Fill, Rng}; -#[cfg(all(feature = "std", feature = "std_rng", feature = "getrandom"))] +#[cfg(all(feature = "std", feature = "std_rng", feature = "os_rng"))] use crate::distr::{Distribution, StandardUniform}; /// Generate a random value using the thread-local random number generator. @@ -159,7 +159,7 @@ use crate::distr::{Distribution, StandardUniform}; /// /// [`StandardUniform`]: distr::StandardUniform /// [`ThreadRng`]: rngs::ThreadRng -#[cfg(all(feature = "std", feature = "std_rng", feature = "getrandom"))] +#[cfg(all(feature = "std", feature = "std_rng", feature = "os_rng"))] #[inline] pub fn random() -> T where @@ -179,7 +179,7 @@ where /// let v: Vec = rand::random_iter().take(5).collect(); /// println!("{v:?}"); /// ``` -#[cfg(all(feature = "std", feature = "std_rng", feature = "getrandom"))] +#[cfg(all(feature = "std", feature = "std_rng", feature = "os_rng"))] #[inline] pub fn random_iter() -> distr::DistIter where @@ -204,7 +204,7 @@ where /// ``` /// Note that the first example can also be achieved (without `collect`'ing /// to a `Vec`) using [`seq::IteratorRandom::choose`]. -#[cfg(all(feature = "std", feature = "std_rng", feature = "getrandom"))] +#[cfg(all(feature = "std", feature = "std_rng", feature = "os_rng"))] #[inline] pub fn random_range(range: R) -> T where @@ -228,7 +228,7 @@ where /// # Panics /// /// If `p < 0` or `p > 1`. -#[cfg(all(feature = "std", feature = "std_rng", feature = "getrandom"))] +#[cfg(all(feature = "std", feature = "std_rng", feature = "os_rng"))] #[inline] #[track_caller] pub fn random_bool(p: f64) -> bool { @@ -260,7 +260,7 @@ pub fn random_bool(p: f64) -> bool { /// ``` /// /// [`Bernoulli`]: distr::Bernoulli -#[cfg(all(feature = "std", feature = "std_rng", feature = "getrandom"))] +#[cfg(all(feature = "std", feature = "std_rng", feature = "os_rng"))] #[inline] #[track_caller] pub fn random_ratio(numerator: u32, denominator: u32) -> bool { @@ -282,7 +282,7 @@ pub fn random_ratio(numerator: u32, denominator: u32) -> bool { /// Note that you can instead use [`random()`] to generate an array of random /// data, though this is slower for small elements (smaller than the RNG word /// size). -#[cfg(all(feature = "std", feature = "std_rng", feature = "getrandom"))] +#[cfg(all(feature = "std", feature = "std_rng", feature = "os_rng"))] #[inline] #[track_caller] pub fn fill(dest: &mut T) { @@ -302,7 +302,7 @@ mod test { } #[test] - #[cfg(all(feature = "std", feature = "std_rng", feature = "getrandom"))] + #[cfg(all(feature = "std", feature = "std_rng", feature = "os_rng"))] fn test_random() { let _n: u64 = random(); let _f: f32 = random(); @@ -316,7 +316,7 @@ mod test { } #[test] - #[cfg(all(feature = "std", feature = "std_rng", feature = "getrandom"))] + #[cfg(all(feature = "std", feature = "std_rng", feature = "os_rng"))] fn test_range() { let _n: usize = random_range(42..=43); let _f: f32 = random_range(42.0..43.0); diff --git a/src/prelude.rs b/src/prelude.rs index d41ad6b494..0e15855c92 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -27,7 +27,7 @@ pub use crate::rngs::SmallRng; #[doc(no_inline)] pub use crate::rngs::StdRng; #[doc(no_inline)] -#[cfg(all(feature = "std", feature = "std_rng", feature = "getrandom"))] +#[cfg(all(feature = "std", feature = "std_rng", feature = "os_rng"))] pub use crate::rngs::ThreadRng; #[doc(no_inline)] pub use crate::seq::{IndexedMutRandom, IndexedRandom, IteratorRandom, SliceRandom}; diff --git a/src/rngs/mod.rs b/src/rngs/mod.rs index bfb5bf6e96..32e12d6889 100644 --- a/src/rngs/mod.rs +++ b/src/rngs/mod.rs @@ -95,15 +95,15 @@ mod xoshiro256plusplus; #[cfg(feature = "std_rng")] mod std; -#[cfg(all(feature = "std", feature = "std_rng", feature = "getrandom"))] +#[cfg(all(feature = "std", feature = "std_rng", feature = "os_rng"))] pub(crate) mod thread; #[cfg(feature = "small_rng")] pub use self::small::SmallRng; #[cfg(feature = "std_rng")] pub use self::std::StdRng; -#[cfg(all(feature = "std", feature = "std_rng", feature = "getrandom"))] +#[cfg(all(feature = "std", feature = "std_rng", feature = "os_rng"))] pub use self::thread::ThreadRng; -#[cfg(feature = "getrandom")] +#[cfg(feature = "os_rng")] pub use rand_core::OsRng; diff --git a/src/rngs/std.rs b/src/rngs/std.rs index fd2c24e30a..6e1658e745 100644 --- a/src/rngs/std.rs +++ b/src/rngs/std.rs @@ -10,7 +10,7 @@ use rand_core::{CryptoRng, RngCore, SeedableRng}; -#[cfg(any(test, feature = "getrandom"))] +#[cfg(any(test, feature = "os_rng"))] pub(crate) use rand_chacha::ChaCha12Core as Core; use rand_chacha::ChaCha12Rng as Rng; diff --git a/src/rngs/thread.rs b/src/rngs/thread.rs index 38446759ab..7e5203214a 100644 --- a/src/rngs/thread.rs +++ b/src/rngs/thread.rs @@ -100,7 +100,7 @@ impl ThreadRng { /// Immediately reseed the generator /// /// This discards any remaining random data in the cache. - pub fn reseed(&mut self) -> Result<(), rand_core::getrandom::Error> { + pub fn reseed(&mut self) -> Result<(), rand_core::OsError> { // SAFETY: We must make sure to stop using `rng` before anyone else // creates another mutable reference let rng = unsafe { &mut *self.rng.get() };