1use thiserror::Error;
4
5#[derive(Debug, Error)]
11#[error("entropy source failed: {0}")]
12pub struct EntropyError(pub String);
13
14pub trait Entropy {
21 fn fill(&mut self, buf: &mut [u8]) -> Result<(), EntropyError>;
23}
24
25impl<F> Entropy for F
26where
27 F: FnMut(&mut [u8]) -> Result<(), EntropyError>,
28{
29 fn fill(&mut self, buf: &mut [u8]) -> Result<(), EntropyError> {
30 self(buf)
31 }
32}
33
34#[cfg(test)]
35mod tests {
36 use super::*;
37
38 #[test]
39 fn closures_are_entropy_sources() {
40 let mut calls = 0usize;
41 let mut src = |buf: &mut [u8]| {
42 calls += 1;
43 buf.fill(0xA5);
44 Ok(())
45 };
46 let mut buf = [0u8; 4];
47 src.fill(&mut buf).unwrap();
48 assert_eq!(buf, [0xA5; 4]);
49 assert_eq!(calls, 1);
50 }
51
52 #[test]
53 fn failures_propagate() {
54 let mut src = |_: &mut [u8]| Err(EntropyError("no randomness today".into()));
55 let mut buf = [0u8; 1];
56 let err = src.fill(&mut buf).unwrap_err();
57 assert!(err.to_string().contains("no randomness"));
58 }
59}