Skip to content

Commit

Permalink
Add getrandom::value function based on zerocopy::FromBytes
Browse files Browse the repository at this point in the history
  • Loading branch information
newpavlov committed Nov 7, 2023
1 parent 4c094c3 commit 76dfd1e
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 0 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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 }
Expand Down
31 changes: 31 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -349,3 +349,34 @@ pub fn getrandom_uninit(dest: &mut [MaybeUninit<u8>]) -> 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<T: zerocopy::FromBytes + Sized>() -> Result<T, Error> {
let mut value = MaybeUninit::<T>::uninit();
// SAFETY: it's safe to cast `&mut MaybeUninit<T>` to `&mut [MaybeUninit<u8>]`
// with slice length equal to `size_of::<T>()`. 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<T> as *mut MaybeUninit<u8>,
core::mem::size_of::<T>(),
);
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() })
}

0 comments on commit 76dfd1e

Please sign in to comment.