diff --git a/src/custom.rs b/src/custom.rs index 79be7fc2..923b1cf8 100644 --- a/src/custom.rs +++ b/src/custom.rs @@ -1,103 +1,12 @@ //! An implementation which calls out to an externally defined function. -use crate::{util::uninit_slice_fill_zero, Error}; +use crate::Error; use core::{mem::MaybeUninit, num::NonZeroU32}; -/// Register a function to be invoked by `getrandom` on unsupported targets. -/// -/// ## Writing a custom `getrandom` implementation -/// -/// The function to register must have the same signature as -/// [`getrandom::getrandom`](crate::getrandom). The function can be defined -/// wherever you want, either in root crate or a dependent crate. -/// -/// For example, if we wanted a `failure-getrandom` crate containing an -/// implementation that always fails, we would first depend on `getrandom` -/// (for the [`Error`] type) in `failure-getrandom/Cargo.toml`: -/// ```toml -/// [dependencies] -/// getrandom = "0.2" -/// ``` -/// Note that the crate containing this function does **not** need to enable the -/// `"custom"` Cargo feature. -/// -/// Next, in `failure-getrandom/src/lib.rs`, we define our function: -/// ```rust -/// use core::num::NonZeroU32; -/// use getrandom::Error; -/// -/// // Some application-specific error code -/// const MY_CUSTOM_ERROR_CODE: u32 = Error::CUSTOM_START + 42; -/// pub fn always_fail(buf: &mut [u8]) -> Result<(), Error> { -/// let code = NonZeroU32::new(MY_CUSTOM_ERROR_CODE).unwrap(); -/// Err(Error::from(code)) -/// } -/// ``` -/// -/// ## Registering a custom `getrandom` implementation -/// -/// Functions can only be registered in the root binary crate. Attempting to -/// register a function in a non-root crate will result in a linker error. -/// This is similar to -/// [`#[panic_handler]`](https://doc.rust-lang.org/nomicon/panic-handler.html) or -/// [`#[global_allocator]`](https://doc.rust-lang.org/edition-guide/rust-2018/platform-and-target-support/global-allocators.html), -/// where helper crates define handlers/allocators but only the binary crate -/// actually _uses_ the functionality. -/// -/// To register the function, we first depend on `failure-getrandom` _and_ -/// `getrandom` in `Cargo.toml`: -/// ```toml -/// [dependencies] -/// failure-getrandom = "0.1" -/// getrandom = { version = "0.2", features = ["custom"] } -/// ``` -/// -/// Then, we register the function in `src/main.rs`: -/// ```rust -/// # mod failure_getrandom { pub fn always_fail(_: &mut [u8]) -> Result<(), getrandom::Error> { unimplemented!() } } -/// use failure_getrandom::always_fail; -/// use getrandom::register_custom_getrandom; -/// -/// register_custom_getrandom!(always_fail); -/// ``` -/// -/// Now any user of `getrandom` (direct or indirect) on this target will use the -/// registered function. As noted in the -/// [top-level documentation](index.html#custom-implementations) this -/// registration only has an effect on unsupported targets. -#[macro_export] -macro_rules! register_custom_getrandom { - ($path:path) => { - // TODO(MSRV 1.37): change to unnamed block - const __GETRANDOM_INTERNAL: () = { - // We use Rust ABI to be safe against potential panics in the passed function. - #[no_mangle] - unsafe fn __getrandom_custom(dest: *mut u8, len: usize) -> u32 { - // Make sure the passed function has the type of getrandom::getrandom - type F = fn(&mut [u8]) -> ::core::result::Result<(), $crate::Error>; - let _: F = $crate::getrandom; - let f: F = $path; - let slice = ::core::slice::from_raw_parts_mut(dest, len); - match f(slice) { - Ok(()) => 0, - Err(e) => e.code().get(), - } - } - }; - }; -} - -#[allow(dead_code)] pub fn getrandom_inner(dest: &mut [MaybeUninit]) -> Result<(), Error> { extern "Rust" { fn __getrandom_custom(dest: *mut u8, len: usize) -> u32; } - // Previously we always passed a valid, initialized slice to - // `__getrandom_custom`. Ensure `dest` has been initialized for backward - // compatibility with implementations that rely on that (e.g. Rust - // implementations that construct a `&mut [u8]` slice from `dest` and - // `len`). - let dest = uninit_slice_fill_zero(dest); - let ret = unsafe { __getrandom_custom(dest.as_mut_ptr(), dest.len()) }; + let ret = unsafe { __getrandom_custom(dest.as_mut_ptr().cast(), dest.len()) }; match NonZeroU32::new(ret) { None => Ok(()), Some(code) => Err(Error::from(code)), diff --git a/src/lib.rs b/src/lib.rs index 37e57f80..0a9cbfac 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -124,7 +124,7 @@ //! //! ### Custom implementations //! -//! The [`register_custom_getrandom!`] macro allows a user to mark their own +//! The `register_custom_getrandom!` macro allows a user to mark their own //! function as the backing implementation for [`getrandom`]. See the macro's //! documentation for more information about writing and registering your own //! custom implementations.