1#[cfg(feature = "alloc")]
9use alloc::vec::Vec;
10
11#[cfg(feature = "alloc")]
17#[must_use]
18pub fn randombytes_buf(len: usize) -> Vec<u8> {
19 let mut r: Vec<u8> = vec![0; len];
20 copy_randombytes(r.as_mut_slice());
21
22 r
23}
24
25pub fn copy_randombytes(dest: &mut [u8]) {
32 fill_from(getrandom::fill, dest)
33}
34
35fn fill_from<E: core::fmt::Debug>(fill: impl FnOnce(&mut [u8]) -> Result<(), E>, dest: &mut [u8]) {
39 fill(dest).expect("failed to fill random bytes");
40}
41
42#[cfg(test)]
43mod tests {
44 use super::*;
45
46 #[test]
47 #[cfg(feature = "alloc")]
48 fn randombytes_buf_returns_requested_length_and_fresh_data() {
49 assert!(randombytes_buf(0).is_empty());
50
51 let first = randombytes_buf(32);
52 let second = randombytes_buf(32);
53 assert_eq!(first.len(), 32);
54 assert_ne!(first, second, "two 32-byte draws collided");
55 }
56
57 #[test]
58 fn copy_randombytes_fills_exactly_the_destination() {
59 let mut buf = [0u8; 64];
60 copy_randombytes(&mut buf[16..48]);
61
62 assert_eq!(&buf[..16], &[0; 16]);
63 assert_eq!(&buf[48..], &[0; 16]);
64 assert_ne!(&buf[16..48], &[0; 32]);
65
66 copy_randombytes(&mut buf[..0]);
67 assert_eq!(&buf[..16], &[0; 16]);
68 }
69
70 #[test]
71 #[should_panic]
72 fn os_rng_failure_panics_instead_of_leaving_zeroes() {
73 let mut dest = [0u8; 8];
74 fill_from(|_: &mut [u8]| Err("no entropy"), &mut dest);
75 }
76}