use alloc::borrow::Cow;
use alloc::vec;
use alloc::vec::Vec;
use super::DecoyStrategy;
use crate::Result;
use crate::error::Error;
use crate::fetcher::RawKey;
#[derive(Debug, Default, Clone, Copy)]
pub struct RandomDecoy;
impl DecoyStrategy for RandomDecoy {
fn generate(&self, _key: &RawKey, output_len: usize) -> Result<Vec<u8>> {
if output_len == 0 {
return Ok(Vec::new());
}
let mut buf = vec![0u8; output_len];
getrandom::getrandom(&mut buf).map_err(|_| Error::Internal("OS RNG failed"))?;
Ok(buf)
}
fn describe(&self) -> Cow<'_, str> {
Cow::Borrowed("random")
}
}
#[cfg(test)]
#[allow(
clippy::unwrap_used,
clippy::expect_used,
clippy::cast_possible_truncation,
clippy::cast_sign_loss
)]
mod tests {
use super::*;
fn raw(bytes: &[u8]) -> RawKey {
RawKey::new(bytes.to_vec())
}
#[test]
fn produces_requested_length() {
let key = raw(b"anything");
for n in [0usize, 1, 7, 32, 256, 4096] {
let out = RandomDecoy.generate(&key, n).unwrap();
assert_eq!(out.len(), n, "wrong length for n = {n}");
}
}
#[test]
fn two_calls_produce_different_bytes() {
let key = raw(b"k");
let a = RandomDecoy.generate(&key, 64).unwrap();
let b = RandomDecoy.generate(&key, 64).unwrap();
assert_ne!(a, b);
}
#[test]
fn describe_returns_random() {
assert_eq!(RandomDecoy.describe(), "random");
}
}