From 76dfd1eaad966571dd28a6bd99942335dc64b80d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D1=80=D1=82=D1=91=D0=BC=20=D0=9F=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=BE=D0=B2=20=5BArtyom=20Pavlov=5D?= Date: Tue, 7 Nov 2023 08:23:56 +0300 Subject: [PATCH 1/9] Add `getrandom::value` function based on `zerocopy::FromBytes` --- Cargo.toml | 1 + src/lib.rs | 31 +++++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index 790fa2fa..cd6e7088 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,6 +12,7 @@ exclude = [".*"] [dependencies] cfg-if = "1" +zerocopy = { version = "0.7", optional = true, default-features = false } # When built as part of libstd compiler_builtins = { version = "0.1", optional = true } diff --git a/src/lib.rs b/src/lib.rs index 6336098b..572abc19 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -349,3 +349,34 @@ pub fn getrandom_uninit(dest: &mut [MaybeUninit]) -> Result<&mut [u8], Error // since it returned `Ok`. Ok(unsafe { slice_assume_init_mut(dest) }) } + +/// Generate a random value of type `T` implementing the [`zerocopy::FromBytes`] trait. +/// +/// # Examples +/// ``` +/// # fn main() -> Result<(), getrandom::Error> { +/// let key: [u8; 16] = getrandom::value()?; +/// let keys: [[u8; 16]; 64] = getrandom::value()?; +/// let random_u32: u32 = getrandom::value()?; +/// let random_u64s: [u64; 100] = getrandom::getrandom_value()?; +/// # Ok(()) } +/// ``` +#[cfg(feature = "zerocopy")] +#[inline] +pub fn value() -> Result { + let mut value = MaybeUninit::::uninit(); + // SAFETY: it's safe to cast `&mut MaybeUninit` to `&mut [MaybeUninit]` + // with slice length equal to `size_of::()`. The compiler will ensure that + // `T` isn't too large. + unsafe { + let as_bytes_mut = core::slice::from_raw_parts_mut( + &mut value as *mut MaybeUninit as *mut MaybeUninit, + core::mem::size_of::(), + ); + getrandom_uninit(as_bytes_mut)?; + }; + // SAFETY: when `getrandom_uninit` returns `Ok` all bytes in `as_bytes_mut` + // (and thus in `value`) are properly initialized. Any bit-sequence is valid + // for `T: FromBytes`, so we can safely execute `assume_init` on `value`. + Ok(unsafe { value.assume_init() }) +} From 3d5e3c12e2489ee6ed1c641e11b329662320660c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D1=80=D1=82=D1=91=D0=BC=20=D0=9F=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=BE=D0=B2=20=5BArtyom=20Pavlov=5D?= Date: Tue, 7 Nov 2023 09:14:23 +0300 Subject: [PATCH 2/9] Add MSRV note for zeroize and enable it for docs.rs --- Cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/Cargo.toml b/Cargo.toml index cd6e7088..6663f2ad 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,6 +12,7 @@ exclude = [".*"] [dependencies] cfg-if = "1" +# WARNING: Enabling this dependency bumps MSRV to 1.60 zerocopy = { version = "0.7", optional = true, default-features = false } # When built as part of libstd From 8f0dafd91150b40a1a1c1ae085bbb63daaff8bff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D1=80=D1=82=D1=91=D0=BC=20=D0=9F=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=BE=D0=B2=20=5BArtyom=20Pavlov=5D?= Date: Tue, 7 Nov 2023 09:15:07 +0300 Subject: [PATCH 3/9] Add doc(cfg(..)) for `value` fn --- src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/lib.rs b/src/lib.rs index 572abc19..f404bb44 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -362,6 +362,7 @@ pub fn getrandom_uninit(dest: &mut [MaybeUninit]) -> Result<&mut [u8], Error /// # Ok(()) } /// ``` #[cfg(feature = "zerocopy")] +#[cfg_attr(docsrs, doc(cfg(feature = "zerocopy")))] #[inline] pub fn value() -> Result { let mut value = MaybeUninit::::uninit(); From fb4cdc19a777742db77ba7edae05af1fa6d73f31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D1=80=D1=82=D1=91=D0=BC=20=D0=9F=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=BE=D0=B2=20=5BArtyom=20Pavlov=5D?= Date: Tue, 7 Nov 2023 09:20:53 +0300 Subject: [PATCH 4/9] Migrate to `doc_auto_cfg` --- Cargo.toml | 2 +- src/custom.rs | 1 - src/error_impls.rs | 1 - src/lib.rs | 3 +-- 4 files changed, 2 insertions(+), 5 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 6663f2ad..0e9b09ac 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -51,7 +51,7 @@ rustc-dep-of-std = [ test-in-browser = [] [package.metadata.docs.rs] -features = ["std", "custom"] +features = ["std", "custom", "zeroize"] rustdoc-args = ["--cfg", "docsrs"] # workaround for https://github.com/cross-rs/cross/issues/1345 diff --git a/src/custom.rs b/src/custom.rs index 66e4256f..222477aa 100644 --- a/src/custom.rs +++ b/src/custom.rs @@ -73,7 +73,6 @@ use core::{mem::MaybeUninit, num::NonZeroU32}; /// [top-level documentation](index.html#custom-implementations) this /// registration only has an effect on unsupported targets. #[macro_export] -#[cfg_attr(docsrs, doc(cfg(feature = "custom")))] macro_rules! register_custom_getrandom { ($path:path) => { // TODO(MSRV 1.37): change to unnamed block diff --git a/src/error_impls.rs b/src/error_impls.rs index 61f46d22..5cb88405 100644 --- a/src/error_impls.rs +++ b/src/error_impls.rs @@ -5,7 +5,6 @@ // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. -#![cfg_attr(docsrs, doc(cfg(feature = "std")))] extern crate std; use crate::Error; diff --git a/src/lib.rs b/src/lib.rs index f404bb44..e79e1ad0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -191,7 +191,7 @@ )] #![no_std] #![warn(rust_2018_idioms, unused_lifetimes, missing_docs)] -#![cfg_attr(docsrs, feature(doc_cfg))] +#![cfg_attr(docsrs, feature(doc_auto_cfg))] #[macro_use] extern crate cfg_if; @@ -362,7 +362,6 @@ pub fn getrandom_uninit(dest: &mut [MaybeUninit]) -> Result<&mut [u8], Error /// # Ok(()) } /// ``` #[cfg(feature = "zerocopy")] -#[cfg_attr(docsrs, doc(cfg(feature = "zerocopy")))] #[inline] pub fn value() -> Result { let mut value = MaybeUninit::::uninit(); From 0d47de62de4195622f2f691b6abc1719e7aad5c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D1=80=D1=82=D1=91=D0=BC=20=D0=9F=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=BE=D0=B2=20=5BArtyom=20Pavlov=5D?= Date: Tue, 7 Nov 2023 09:24:55 +0300 Subject: [PATCH 5/9] Re-export zerocopy --- src/lib.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index e79e1ad0..07d0ba3d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -196,6 +196,9 @@ #[macro_use] extern crate cfg_if; +#[cfg(feature = "zerocopy")] +pub use zerocopy; + use crate::util::{slice_as_uninit_mut, slice_assume_init_mut}; use core::mem::MaybeUninit; From 5c60db90f37f6bdb079b6cd62871b4c37c65bb42 Mon Sep 17 00:00:00 2001 From: Artyom Pavlov Date: Wed, 17 Jan 2024 18:13:06 +0300 Subject: [PATCH 6/9] fix typo --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 21873552..4e7cfb6f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -51,7 +51,7 @@ rustc-dep-of-std = [ test-in-browser = [] [package.metadata.docs.rs] -features = ["std", "custom", "zeroize"] +features = ["std", "custom", "zerocopy"] rustdoc-args = ["--cfg", "docsrs"] # workaround for https://github.com/cross-rs/cross/issues/1345 From 51045c367d403bc06128f1ac53050ec28ce9304a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D1=80=D1=82=D1=91=D0=BC=20=D0=9F=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=BE=D0=B2=20=5BArtyom=20Pavlov=5D?= Date: Fri, 19 Jan 2024 19:47:25 +0300 Subject: [PATCH 7/9] Revert doc_auto_cfg chanes --- src/custom.rs | 1 + src/error_impls.rs | 1 + src/lib.rs | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/custom.rs b/src/custom.rs index 79be7fc2..8dc9cb79 100644 --- a/src/custom.rs +++ b/src/custom.rs @@ -65,6 +65,7 @@ use core::{mem::MaybeUninit, num::NonZeroU32}; /// [top-level documentation](index.html#custom-implementations) this /// registration only has an effect on unsupported targets. #[macro_export] +#[cfg_attr(docsrs, doc(cfg(feature = "custom")))] macro_rules! register_custom_getrandom { ($path:path) => { // TODO(MSRV 1.37): change to unnamed block diff --git a/src/error_impls.rs b/src/error_impls.rs index 7f176cc6..a7bffb89 100644 --- a/src/error_impls.rs +++ b/src/error_impls.rs @@ -1,3 +1,4 @@ +#![cfg_attr(docsrs, doc(cfg(feature = "std")))] extern crate std; use crate::Error; diff --git a/src/lib.rs b/src/lib.rs index da733a3e..5d7e2289 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -190,7 +190,7 @@ )] #![no_std] #![warn(rust_2018_idioms, unused_lifetimes, missing_docs)] -#![cfg_attr(docsrs, feature(doc_auto_cfg))] +#![cfg_attr(docsrs, feature(doc_cfg))] #[macro_use] extern crate cfg_if; From 6d929c0048114537e7e4d0dc2b1404c36d34d5f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D1=80=D1=82=D1=91=D0=BC=20=D0=9F=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=BE=D0=B2=20=5BArtyom=20Pavlov=5D?= Date: Wed, 24 Jan 2024 16:16:15 +0300 Subject: [PATCH 8/9] minor code tweaks --- src/lib.rs | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 5d7e2289..ec393d0d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -362,7 +362,7 @@ pub fn getrandom_uninit(dest: &mut [MaybeUninit]) -> Result<&mut [u8], Error /// let key: [u8; 16] = getrandom::value()?; /// let keys: [[u8; 16]; 64] = getrandom::value()?; /// let random_u32: u32 = getrandom::value()?; -/// let random_u64s: [u64; 100] = getrandom::getrandom_value()?; +/// let random_u64s: [u64; 100] = getrandom::value()?; /// # Ok(()) } /// ``` #[cfg(feature = "zerocopy")] @@ -373,13 +373,12 @@ pub fn value() -> Result { // with slice length equal to `size_of::()`. The compiler will ensure that // `T` isn't too large. unsafe { - let as_bytes_mut = core::slice::from_raw_parts_mut( - &mut value as *mut MaybeUninit as *mut MaybeUninit, - core::mem::size_of::(), - ); - getrandom_uninit(as_bytes_mut)?; + let ptr: *mut MaybeUninit = value.as_mut_ptr().cast(); + let size = core::mem::size_of::(); + let uninit_bytes = core::slice::from_raw_parts_mut(ptr, size); + getrandom_uninit(uninit_bytes)?; }; - // SAFETY: when `getrandom_uninit` returns `Ok` all bytes in `as_bytes_mut` + // SAFETY: when `getrandom_uninit` returns `Ok` all bytes in `uninit_bytes` // (and thus in `value`) are properly initialized. Any bit-sequence is valid // for `T: FromBytes`, so we can safely execute `assume_init` on `value`. Ok(unsafe { value.assume_init() }) From 8d66541c1b8303fed3e0214a2c85473053d60f42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D1=80=D1=82=D1=91=D0=BC=20=D0=9F=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=BE=D0=B2=20=5BArtyom=20Pavlov=5D?= Date: Wed, 24 Jan 2024 16:19:43 +0300 Subject: [PATCH 9/9] Test zerocopy feature in CI --- .github/workflows/tests.yml | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index e3c9bbe6..2b6023e1 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -33,10 +33,10 @@ jobs: - name: Generate Docs env: RUSTDOCFLAGS: --cfg docsrs - run: cargo deadlinks -- --features=custom,std + run: cargo deadlinks -- --features=custom,std,zerocopy - run: | cargo generate-lockfile -Z minimal-versions - cargo test --features=custom,std + cargo test --features=custom,std,zerocopy # TODO: add aarch64-based macOS runner when it's supported by Github Actions main-tests: @@ -80,7 +80,7 @@ jobs: - name: Install multilib run: sudo apt-get update && sudo apt-get install gcc-multilib - uses: Swatinem/rust-cache@v2 - - run: cargo test --target=${{ matrix.target }} --features=std + - run: cargo test --target=${{ matrix.target }} --features=std,zerocopy ios-tests: name: iOS Simulator Test @@ -128,7 +128,7 @@ jobs: with: toolchain: ${{ matrix.toolchain }} - uses: Swatinem/rust-cache@v2 - - run: cargo test --features=std + - run: cargo test --features=std,zerocopy cross-tests: name: Cross Test @@ -152,7 +152,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,zerocopy macos-link: name: macOS ARM64 Build/Link @@ -164,9 +164,9 @@ jobs: targets: aarch64-apple-darwin, aarch64-apple-ios components: rust-src - uses: Swatinem/rust-cache@v2 - - run: cargo test --no-run --target=aarch64-apple-darwin --features=std - - run: cargo test --no-run --target=aarch64-apple-ios --features=std - - run: cargo test --no-run --target=aarch64-apple-watchos-sim -Zbuild-std --features=std + - run: cargo test --no-run --target=aarch64-apple-darwin --features=std,zerocopy + - run: cargo test --no-run --target=aarch64-apple-ios --features=std,zerocopy + - run: cargo test --no-run --target=aarch64-apple-watchos-sim -Zbuild-std --features=std,zerocopy cross-link: name: Cross Build/Link @@ -188,7 +188,7 @@ jobs: wget -O - $URL | tar -xz -C ~/.cargo/bin cross --version - name: Build Tests - run: cross test --no-run --target=${{ matrix.target }} --features=std + run: cross test --no-run --target=${{ matrix.target }} --features=std,zerocopy web-tests: name: Web Test @@ -284,7 +284,7 @@ jobs: targets: ${{ matrix.target }} - uses: Swatinem/rust-cache@v2 - name: Build - run: cargo build --target=${{ matrix.target }} --features=std + run: cargo build --target=${{ matrix.target }} --features=std,zerocopy build-tier3: name: Tier 3 Build @@ -348,6 +348,6 @@ jobs: components: rustfmt, clippy - uses: Swatinem/rust-cache@v2 - name: clippy - run: cargo clippy --all --features=custom,std + run: cargo clippy --all --features=custom,std,zerocopy - name: fmt run: cargo fmt --all -- --check