diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index abb18135..cb3766a9 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -37,7 +37,10 @@ jobs: - uses: Swatinem/rust-cache@v2 - run: cargo test # Make sure enabling the std feature doesn't break anything - - run: cargo test --features=std + - run: | + cargo test --features=std + cargo test --features=sys_rng + cargo test --features=std,sys_rng - if: ${{ matrix.toolchain == 'nightly' }} run: cargo test --benches @@ -53,27 +56,27 @@ jobs: with: targets: ${{ matrix.target }} - uses: Swatinem/rust-cache@v2 - - run: cargo test --target=${{ matrix.target }} --features=std + - run: cargo test --target=${{ matrix.target }} --features=std,sys_rng - env: RUSTFLAGS: -Dwarnings --cfg getrandom_backend="linux_getrandom" RUSTDOCFLAGS: -Dwarnings --cfg getrandom_backend="linux_getrandom" - run: cargo test --target=${{ matrix.target }} --features=std + run: cargo test --target=${{ matrix.target }} --features=std,sys_rng - env: RUSTFLAGS: -Dwarnings --cfg getrandom_backend="linux_raw" RUSTDOCFLAGS: -Dwarnings --cfg getrandom_backend="linux_raw" - run: cargo test --target=${{ matrix.target }} --features=std + run: cargo test --target=${{ matrix.target }} --features=std,sys_rng - env: RUSTFLAGS: -Dwarnings --cfg getrandom_test_linux_fallback RUSTDOCFLAGS: -Dwarnings --cfg getrandom_test_linux_fallback - run: cargo test --features=std + run: cargo test --features=std,sys_rng - env: RUSTFLAGS: -Dwarnings --cfg getrandom_test_linux_without_fallback RUSTDOCFLAGS: -Dwarnings --cfg getrandom_test_linux_without_fallback - run: cargo test --features=std + run: cargo test --features=std,sys_rng - env: RUSTFLAGS: -Dwarnings --cfg getrandom_backend="rdrand" RUSTDOCFLAGS: -Dwarnings --cfg getrandom_backend="rdrand" - run: cargo test --features=std + run: cargo test --features=std,sys_rng ios: name: iOS Simulator @@ -123,7 +126,7 @@ jobs: with: toolchain: ${{ matrix.toolchain }} - uses: Swatinem/rust-cache@v2 - - run: cargo test --features=std + - run: cargo test --features=std,sys_rng windows7: name: Windows 7 (on Windows 10) @@ -136,8 +139,8 @@ jobs: toolchain: nightly-2025-09-28 components: rust-src - uses: Swatinem/rust-cache@v2 - - run: cargo test --target=x86_64-win7-windows-msvc -Z build-std --features=std - - run: cargo test --target=i686-win7-windows-msvc -Z build-std --features=std + - run: cargo test --target=x86_64-win7-windows-msvc -Z build-std --features=std,sys_rng + - run: cargo test --target=i686-win7-windows-msvc -Z build-std --features=std,sys_rng sanitizer-linux: name: Sanitizer Linux @@ -216,7 +219,7 @@ jobs: wget -O - $URL | tar -xz -C ~/.cargo/bin cross --version - name: Test - run: cross test --no-fail-fast --target=${{ matrix.target }} --features=std + run: cross test --no-fail-fast --target=${{ matrix.target }} --features=std,sys_rng freebsd: name: FreeBSD VM @@ -273,14 +276,14 @@ jobs: description: Web, version: stable, flags: '-Dwarnings --cfg getrandom_backend="wasm_js"', - args: '--features=std,wasm_js', + args: '--features=std,sys_rng,wasm_js', } - { description: Web with Atomics, version: nightly, components: rust-src, flags: '-Dwarnings --cfg getrandom_backend="wasm_js" -Ctarget-feature=+atomics,+bulk-memory', - args: '--features=std,wasm_js -Zbuild-std=panic_abort,std', + args: '--features=std,sys_rng,wasm_js -Zbuild-std=panic_abort,std', } steps: - uses: actions/checkout@v5 diff --git a/CHANGELOG.md b/CHANGELOG.md index cce685f8..28162ef4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,12 +8,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - `RawOsError` type alias [#739] +- `SysRng` behind new feature `sys_rng` [#751] ### Changed - Use Edition 2024 and MSRV 1.85 [#749] [#739]: https://github.com/rust-random/getrandom/pull/739 [#749]: https://github.com/rust-random/getrandom/pull/749 +[#751]: https://github.com/rust-random/getrandom/pull/751 ## [0.3.4] - 2025-10-14 diff --git a/Cargo.lock b/Cargo.lock index 983abcef..3a0907cf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -38,6 +38,7 @@ dependencies = [ "js-sys", "libc", "r-efi", + "rand_core", "wasip2", "wasm-bindgen", "wasm-bindgen-test", @@ -105,6 +106,12 @@ version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" +[[package]] +name = "rand_core" +version = "0.10.0-rc-2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "104a23e4e8b77312a823b6b5613edbac78397e2f34320bc7ac4277013ec4478e" + [[package]] name = "same-file" version = "1.0.6" diff --git a/Cargo.toml b/Cargo.toml index 0190fbd9..3037a445 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,6 +11,9 @@ repository = "https://github.com/rust-random/getrandom" categories = ["os", "no-std"] exclude = [".*"] +[package.metadata.docs.rs] +features = ["std", "sys_rng"] + [features] # Implement From for std::io::Error and # use std to retrieve OS error descriptions @@ -23,8 +26,12 @@ std = [] # i.e. avoid unconditionally enabling it in library crates. wasm_js = ["dep:wasm-bindgen", "dep:js-sys"] +# Provide SysRng over rand_core +sys_rng = ["dep:rand_core"] + [dependencies] cfg-if = "1" +rand_core = { version = "0.10.0-rc-2", optional = true } # getrandom / linux_android_with_fallback [target.'cfg(all(any(target_os = "linux", target_os = "android"), not(any(all(target_os = "linux", target_env = ""), getrandom_backend = "custom", getrandom_backend = "linux_raw", getrandom_backend = "rdrand", getrandom_backend = "rndr"))))'.dependencies] @@ -85,9 +92,6 @@ check-cfg = [ 'cfg(target_os, values("cygwin"))', # TODO(MSRV 1.86): Remove this. ] -[package.metadata.docs.rs] -features = ["std"] - # workaround for https://github.com/cross-rs/cross/issues/1345 [package.metadata.cross.target.x86_64-unknown-netbsd] pre-build = [ diff --git a/src/lib.rs b/src/lib.rs index befea654..ed69ad23 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -39,6 +39,15 @@ mod util; #[cfg(feature = "std")] mod error_std_impls; +/// `rand_core` adapter +#[cfg(feature = "sys_rng")] +mod sys_rng; + +#[cfg(feature = "sys_rng")] +pub use rand_core; +#[cfg(feature = "sys_rng")] +pub use sys_rng::SysRng; + pub use crate::error::{Error, RawOsError}; /// Fill `dest` with random bytes from the system's preferred random number source. diff --git a/src/sys_rng.rs b/src/sys_rng.rs new file mode 100644 index 00000000..d7c019e1 --- /dev/null +++ b/src/sys_rng.rs @@ -0,0 +1,54 @@ +use crate::Error; +use rand_core::{TryCryptoRng, TryRngCore}; + +/// A [`TryRngCore`] interface over the system's preferred random number source +/// +/// This is a zero-sized struct. It can be freely constructed with just `SysRng`. +/// +/// This struct is also available as [`rand::rngs::SysRng`] when using [rand]. +/// +/// # Usage example +/// +/// `SysRng` implements [`TryRngCore`]: +/// ``` +/// use getrandom::{rand_core::TryRngCore, SysRng}; +/// +/// let mut key = [0u8; 32]; +/// SysRng.try_fill_bytes(&mut key).unwrap(); +/// ``` +/// +/// Using it as an [`RngCore`] is possible using [`TryRngCore::unwrap_err`]: +/// ``` +/// use getrandom::rand_core::{TryRngCore, RngCore}; +/// use getrandom::SysRng; +/// +/// let mut rng = SysRng.unwrap_err(); +/// let random_u64 = rng.next_u64(); +/// ``` +/// +/// [rand]: https://crates.io/crates/rand +/// [`rand::rngs::SysRng`]: https://docs.rs/rand/latest/rand/rngs/struct.SysRng.html +/// [`RngCore`]: rand_core::RngCore +#[derive(Clone, Copy, Debug, Default)] +pub struct SysRng; + +impl TryRngCore for SysRng { + type Error = Error; + + #[inline] + fn try_next_u32(&mut self) -> Result { + crate::u32() + } + + #[inline] + fn try_next_u64(&mut self) -> Result { + crate::u64() + } + + #[inline] + fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> { + crate::fill(dest) + } +} + +impl TryCryptoRng for SysRng {} diff --git a/tests/sys_rng.rs b/tests/sys_rng.rs new file mode 100644 index 00000000..541912d2 --- /dev/null +++ b/tests/sys_rng.rs @@ -0,0 +1,17 @@ +#![cfg(feature = "sys_rng")] + +use getrandom::SysRng; +use getrandom::rand_core::TryRngCore; + +#[test] +fn test_sys_rng() { + let x = SysRng.try_next_u64().unwrap(); + let y = SysRng.try_next_u64().unwrap(); + assert!(x != 0); + assert!(x != y); +} + +#[test] +fn test_construction() { + assert!(SysRng.try_next_u64().unwrap() != 0); +}