diff --git a/CHANGELOG.md b/CHANGELOG.md index b781ac15..196350e2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Breaking Changes - Update MSRV to 1.60 [#472] - Remove support of the `wasm32-wasi` target (use `wasm32-wasip1` or `wasm32-wasip2` instead) [#499] +- Remove `impl From for Error` and `Error::code` method [#507] ### Changed - Switch to `futex` on Linux and to `nanosleep`-based wait loop on other targets @@ -16,10 +17,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - `wasm32-wasip1` and `wasm32-wasip2` support [#499] +- `Error::new_custom` method [#507] [#472]: https://github.com/rust-random/getrandom/pull/472 [#490]: https://github.com/rust-random/getrandom/pull/490 [#499]: https://github.com/rust-random/getrandom/pull/499 +[#507]: https://github.com/rust-random/getrandom/pull/507 ## [0.2.15] - 2024-05-06 ### Added diff --git a/src/custom.rs b/src/custom.rs index 923b1cf8..fc216e08 100644 --- a/src/custom.rs +++ b/src/custom.rs @@ -1,14 +1,10 @@ //! An implementation which calls out to an externally defined function. use crate::Error; -use core::{mem::MaybeUninit, num::NonZeroU32}; +use core::mem::MaybeUninit; pub fn getrandom_inner(dest: &mut [MaybeUninit]) -> Result<(), Error> { extern "Rust" { - fn __getrandom_custom(dest: *mut u8, len: usize) -> u32; - } - let ret = unsafe { __getrandom_custom(dest.as_mut_ptr().cast(), dest.len()) }; - match NonZeroU32::new(ret) { - None => Ok(()), - Some(code) => Err(Error::from(code)), + fn __getrandom_custom(dest: *mut u8, len: usize) -> Result<(), Error>; } + unsafe { __getrandom_custom(dest.as_mut_ptr().cast(), dest.len()) } } diff --git a/src/error.rs b/src/error.rs index 5eff99eb..1c158439 100644 --- a/src/error.rs +++ b/src/error.rs @@ -20,44 +20,38 @@ use core::{fmt, num::NonZeroU32}; #[derive(Copy, Clone, Eq, PartialEq)] pub struct Error(NonZeroU32); -const fn internal_error(n: u16) -> Error { - // SAFETY: code > 0 as INTERNAL_START > 0 and adding n won't overflow a u32. - let code = Error::INTERNAL_START + (n as u32); - Error(unsafe { NonZeroU32::new_unchecked(code) }) -} - impl Error { /// This target/platform is not supported by `getrandom`. - pub const UNSUPPORTED: Error = internal_error(0); + pub const UNSUPPORTED: Error = Self::new_internal(0); /// The platform-specific `errno` returned a non-positive value. - pub const ERRNO_NOT_POSITIVE: Error = internal_error(1); + pub const ERRNO_NOT_POSITIVE: Error = Self::new_internal(1); /// Encountered an unexpected situation which should not happen in practice. - pub const UNEXPECTED: Error = internal_error(2); + pub const UNEXPECTED: Error = Self::new_internal(2); /// Call to [`CCRandomGenerateBytes`](https://opensource.apple.com/source/CommonCrypto/CommonCrypto-60074/include/CommonRandom.h.auto.html) failed /// on iOS, tvOS, or waatchOS. // TODO: Update this constant name in the next breaking release. - pub const IOS_SEC_RANDOM: Error = internal_error(3); + pub const IOS_SEC_RANDOM: Error = Self::new_internal(3); /// Call to Windows [`RtlGenRandom`](https://docs.microsoft.com/en-us/windows/win32/api/ntsecapi/nf-ntsecapi-rtlgenrandom) failed. - pub const WINDOWS_RTL_GEN_RANDOM: Error = internal_error(4); + pub const WINDOWS_RTL_GEN_RANDOM: Error = Self::new_internal(4); /// RDRAND instruction failed due to a hardware issue. - pub const FAILED_RDRAND: Error = internal_error(5); + pub const FAILED_RDRAND: Error = Self::new_internal(5); /// RDRAND instruction unsupported on this target. - pub const NO_RDRAND: Error = internal_error(6); + pub const NO_RDRAND: Error = Self::new_internal(6); /// The environment does not support the Web Crypto API. - pub const WEB_CRYPTO: Error = internal_error(7); + pub const WEB_CRYPTO: Error = Self::new_internal(7); /// Calling Web Crypto API `crypto.getRandomValues` failed. - pub const WEB_GET_RANDOM_VALUES: Error = internal_error(8); + pub const WEB_GET_RANDOM_VALUES: Error = Self::new_internal(8); /// On VxWorks, call to `randSecure` failed (random number generator is not yet initialized). - pub const VXWORKS_RAND_SECURE: Error = internal_error(11); + pub const VXWORKS_RAND_SECURE: Error = Self::new_internal(11); /// Node.js does not have the `crypto` CommonJS module. - pub const NODE_CRYPTO: Error = internal_error(12); + pub const NODE_CRYPTO: Error = Self::new_internal(12); /// Calling Node.js function `crypto.randomFillSync` failed. - pub const NODE_RANDOM_FILL_SYNC: Error = internal_error(13); + pub const NODE_RANDOM_FILL_SYNC: Error = Self::new_internal(13); /// Called from an ES module on Node.js. This is unsupported, see: /// . - pub const NODE_ES_MODULE: Error = internal_error(14); + pub const NODE_ES_MODULE: Error = Self::new_internal(14); /// Calling Windows ProcessPrng failed. - pub const WINDOWS_PROCESS_PRNG: Error = internal_error(15); + pub const WINDOWS_PROCESS_PRNG: Error = Self::new_internal(15); /// Codes below this point represent OS Errors (i.e. positive i32 values). /// Codes at or above this point, but below [`Error::CUSTOM_START`] are @@ -108,13 +102,18 @@ impl Error { } } - /// Extract the bare error code. - /// - /// This code can either come from the underlying OS, or be a custom error. - /// Use [`Error::raw_os_error()`] to disambiguate. - #[inline] - pub const fn code(self) -> NonZeroU32 { - self.0 + /// Creates a new instance of an `Error` from a particular custom error code. + pub const fn new_custom(n: u16) -> Error { + // SAFETY: code > 0 as CUSTOM_START > 0 and adding n won't overflow a u32. + let code = Error::CUSTOM_START + (n as u32); + Error(unsafe { NonZeroU32::new_unchecked(code) }) + } + + /// Creates a new instance of an `Error` from a particular internal error code. + const fn new_internal(n: u16) -> Error { + // SAFETY: code > 0 as INTERNAL_START > 0 and adding n won't overflow a u32. + let code = Error::INTERNAL_START + (n as u32); + Error(unsafe { NonZeroU32::new_unchecked(code) }) } } @@ -153,12 +152,6 @@ impl fmt::Display for Error { } } -impl From for Error { - fn from(code: NonZeroU32) -> Self { - Self(code) - } -} - fn internal_desc(error: Error) -> Option<&'static str> { match error { Error::UNSUPPORTED => Some("getrandom: this target is not supported"), diff --git a/src/lib.rs b/src/lib.rs index 62c2dab3..cab0c69e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -105,8 +105,10 @@ //! signature: //! //! ``` +//! use getrandom::Error; +//! //! #[no_mangle] -//! unsafe fn __getrandom_custom(dest: *mut u8, len: usize) -> u32 { +//! unsafe extern "Rust" fn __getrandom_custom(dest: *mut u8, len: usize) -> Result<(), Error> { //! todo!() //! } //! ``` @@ -126,9 +128,11 @@ //! it gets pulled nevertheless by one of your dependencies, then you can //! use the following custom backend which always returns "unsupported" error: //! ``` +//! use getrandom::Error; +//! //! #[no_mangle] -//! unsafe fn __getrandom_custom(dest: *mut u8, len: usize) -> u32 { -//! getrandom::Error::UNSUPPORTED.code().get() +//! unsafe extern "Rust" fn __getrandom_custom(dest: *mut u8, len: usize) -> Result<(), Error> { +//! Err(Error::UNSUPPORTED) //! } //! ``` //! diff --git a/tests/mod.rs b/tests/mod.rs index 951b65dc..33083df5 100644 --- a/tests/mod.rs +++ b/tests/mod.rs @@ -160,6 +160,8 @@ fn test_multithreading() { #[cfg(getrandom_backend = "custom")] mod custom { + use getrandom::Error; + struct Xoshiro128PlusPlus { s: [u32; 4], } @@ -204,13 +206,13 @@ mod custom { // // WARNING: this custom implementation is for testing purposes ONLY! #[no_mangle] - unsafe fn __getrandom_custom(dest: *mut u8, len: usize) -> u32 { + unsafe extern "Rust" fn __getrandom_custom(dest: *mut u8, len: usize) -> Result<(), Error> { use std::time::{SystemTime, UNIX_EPOCH}; assert_ne!(len, 0); if len == 142 { - return getrandom::Error::CUSTOM_START + 142; + return Err(Error::new_custom(142)); } let dest_u32 = dest.cast::(); @@ -227,7 +229,7 @@ mod custom { core::ptr::write_unaligned(dest.add(i), val as u8); } } - 0 + Ok(()) } // Test that enabling the custom feature indeed uses the custom implementation