use thiserror::Error;
#[derive(Debug, Clone, Copy, Error)]
#[error("operating system failed to provide entropy: {0}")]
#[non_exhaustive]
pub struct RngError(#[from] pub(crate) getrandom::Error);
pub fn fill_bytes(buf: &mut [u8]) -> Result<(), RngError> {
getrandom::fill(buf)?;
Ok(())
}
pub fn random_bytes<const N: usize>() -> Result<[u8; N], RngError> {
let mut out = [0_u8; N];
fill_bytes(&mut out)?;
Ok(out)
}
pub fn random_hex_string<const N: usize>() -> Result<String, RngError> {
let bytes = random_bytes::<N>()?;
Ok(crate::util::hex::encode(bytes))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn random_bytes_distinct() {
let lhs: [u8; 32] = random_bytes().unwrap();
let rhs: [u8; 32] = random_bytes().unwrap();
assert_ne!(lhs, rhs);
}
#[test]
fn random_hex_string_length() {
let value = random_hex_string::<16>().unwrap();
assert_eq!(value.len(), 32);
assert!(value.chars().all(|c| c.is_ascii_hexdigit()));
}
}