]> git.proxmox.com Git - rustc.git/blame - vendor/getrandom/src/custom.rs
Merge tag 'debian/1.52.1+dfsg1-1_exp2' into proxmox/buster
[rustc.git] / vendor / getrandom / src / custom.rs
CommitLineData
f20569fa
XL
1// Copyright 2018 Developers of the Rand project.
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
6// option. This file may not be copied, modified, or distributed
7// except according to those terms.
8
9//! An implementation which calls out to an externally defined function.
10use crate::Error;
11use core::num::NonZeroU32;
12
13/// Register a function to be invoked by `getrandom` on unsupported targets.
14///
15/// *This API requires the `"custom"` Cargo feature to be activated*.
16///
17/// ## Writing a custom `getrandom` implementation
18///
19/// The function to register must have the same signature as
20/// [`getrandom::getrandom`](crate::getrandom). The function can be defined
21/// wherever you want, either in root crate or a dependant crate.
22///
23/// For example, if we wanted a `failure-getrandom` crate containing an
24/// implementation that always fails, we would first depend on `getrandom`
25/// (for the [`Error`] type) in `failure-getrandom/Cargo.toml`:
26/// ```toml
27/// [dependencies]
28/// getrandom = "0.2"
29/// ```
30/// Note that the crate containing this function does **not** need to enable the
31/// `"custom"` Cargo feature.
32///
33/// Next, in `failure-getrandom/src/lib.rs`, we define our function:
34/// ```rust
35/// use core::num::NonZeroU32;
36/// use getrandom::Error;
37///
38/// // Some application-specific error code
39/// const MY_CUSTOM_ERROR_CODE: u32 = Error::CUSTOM_START + 42;
40/// pub fn always_fail(buf: &mut [u8]) -> Result<(), Error> {
41/// let code = NonZeroU32::new(MY_CUSTOM_ERROR_CODE).unwrap();
42/// Err(Error::from(code))
43/// }
44/// ```
45///
46/// ## Registering a custom `getrandom` implementation
47///
48/// Functions can only be registered in the root binary crate. Attempting to
49/// register a function in a non-root crate will result in a linker error.
50/// This is similar to
51/// [`#[panic_handler]`](https://doc.rust-lang.org/nomicon/panic-handler.html) or
52/// [`#[global_allocator]`](https://doc.rust-lang.org/edition-guide/rust-2018/platform-and-target-support/global-allocators.html),
53/// where helper crates define handlers/allocators but only the binary crate
54/// actually _uses_ the functionality.
55///
56/// To register the function, we first depend on `failure-getrandom` _and_
57/// `getrandom` in `Cargo.toml`:
58/// ```toml
59/// [dependencies]
60/// failure-getrandom = "0.1"
61/// getrandom = { version = "0.2", features = ["custom"] }
62/// ```
63///
64/// Then, we register the function in `src/main.rs`:
65/// ```rust
66/// # mod failure_getrandom { pub fn always_fail(_: &mut [u8]) -> Result<(), getrandom::Error> { unimplemented!() } }
67/// use failure_getrandom::always_fail;
68/// use getrandom::register_custom_getrandom;
69///
70/// register_custom_getrandom!(always_fail);
71/// ```
72///
73/// Now any user of `getrandom` (direct or indirect) on this target will use the
74/// registered function. As noted in the
75/// [top-level documentation](index.html#use-a-custom-implementation) this
76/// registration only has an effect on unsupported targets.
77#[macro_export]
78macro_rules! register_custom_getrandom {
79 ($path:path) => {
80 // We use an extern "C" function to get the guarantees of a stable ABI.
81 #[no_mangle]
82 extern "C" fn __getrandom_custom(dest: *mut u8, len: usize) -> u32 {
83 let f: fn(&mut [u8]) -> Result<(), ::getrandom::Error> = $path;
84 let slice = unsafe { ::core::slice::from_raw_parts_mut(dest, len) };
85 match f(slice) {
86 Ok(()) => 0,
87 Err(e) => e.code().get(),
88 }
89 }
90 };
91}
92
93#[allow(dead_code)]
94pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> {
95 extern "C" {
96 fn __getrandom_custom(dest: *mut u8, len: usize) -> u32;
97 }
98 let ret = unsafe { __getrandom_custom(dest.as_mut_ptr(), dest.len()) };
99 match NonZeroU32::new(ret) {
100 None => Ok(()),
101 Some(code) => Err(Error::from(code)),
102 }
103}