Skip to content

Commit

Permalink
docs: Clarify intended usage for Custom RNGs
Browse files Browse the repository at this point in the history
Signed-off-by: Joe Richey <joerichey@google.com>
  • Loading branch information
josephlr committed Sep 9, 2020
1 parent d7c8944 commit c8f40e1
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 37 deletions.
56 changes: 41 additions & 15 deletions src/custom.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,40 +12,66 @@ use core::num::NonZeroU32;

/// Register a function to be invoked by `getrandom` on unsupported targets.
///
/// *This API requires the following Cargo features to be activated: `"custom"`*
/// *This API requires the `"custom"` Cargo feature to be activated*.
///
/// ## Writing your own custom `getrandom` implementation
/// ## Writing a custom `getrandom` implementation
///
/// Users can define custom implementations either in their root crate or in a
/// target specific helper-crate. We will use the helper-crate approach in this
/// example, defining `dummy-getrandom`, an implementation that always fails.
/// 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 dependant crate.
///
/// First, in `dummy-getrandom/Cargo.toml` we depend on `getrandom`:
/// 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 = { version = "0.2", features = ["custom"] }
/// getrandom = "0.2"
/// ```
/// Note that the crate containing this function does **not** need to enable the
/// `"custom"` Cargo feature.
///
/// Next, in `dummy-getrandom/src/lib.rs`, we define our custom implementation and register it:
/// Next, in `failure-getrandom/src/lib.rs`, we define our function:
/// ```rust
/// use core::num::NonZeroU32;
/// use getrandom::{Error, register_custom_getrandom};
/// use getrandom::Error;
///
/// // Some application-specific error code
/// const MY_CUSTOM_ERROR_CODE: u32 = Error::CUSTOM_START + 42;
/// fn always_fail(buf: &mut [u8]) -> Result<(), Error> {
/// 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 `getrandom` in `Cargo.toml`:
/// ```toml
/// [dependencies]
/// 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);
/// ```
/// the registered function must have the same type signature as
/// [`getrandom::getrandom`](crate::getrandom).
///
/// Now any user of `getrandom` (direct or indirect) on this target will use the
/// above custom implementation. See the
/// [usage documentation](index.html#use-a-custom-implementation) for information about
/// _using_ such a custom implementation.
/// registered function. As noted in the
/// [top-level documentation](index.html#use-a-custom-implementation) this
/// registration only has an effect on unsupported targets.
#[macro_export]
macro_rules! register_custom_getrandom {
($path:path) => {
Expand Down
31 changes: 9 additions & 22 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,30 +75,17 @@
//!
//! This feature has no effect on targets other than `wasm32-unknown-unknown`.
//!
//! ### Use a custom implementation
//! ### Custom implementations
//!
//! Some external crates define `getrandom` implementations for specific
//! unsupported targets. If you depend on one of these external crates and you
//! are building for an unsupported target, `getrandom` will use this external
//! implementation instead of failing to compile.
//! 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.
//!
//! Using such an external implementation requires depending on it in your
//! `Cargo.toml` _and_ using it in your binary crate with:
//! ```ignore
//! use some_custom_getrandom_crate;
//! ```
//! (failure to do this will cause linker errors).
//!
//! Other than [dev-dependencies](https://doc.rust-lang.org/stable/rust-by-example/testing/dev_dependencies.html),
//! library crates should **not** depend on external implementation crates.
//! Only binary crates should depend/use such crates. 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.
//!
//! See [`register_custom_getrandom!`] for information about writing your own
//! custom `getrandom` implementation for an unsupported target.
//! Note that registering a custom implementation only has an effect on targets
//! that would otherwise not compile. Any supported targets (including those
//! using `"rdrand"` and `"js"` Cargo features) continue using their normal
//! implementations even if a function is registered.
//!
//! ### Indirect Dependencies
//!
Expand Down

0 comments on commit c8f40e1

Please sign in to comment.