use crate::Unspecified;
use std::cell::RefCell;
use vitaminc_random::{Generatable, SafeRand};
pub struct Nonce<const N: usize>([u8; N]);
impl<const N: usize> AsRef<[u8]> for Nonce<N> {
fn as_ref(&self) -> &[u8] {
&self.0
}
}
impl<const N: usize> Nonce<N> {
pub(crate) fn new(inner: [u8; N]) -> Self {
Self(inner)
}
pub fn into_inner(self) -> [u8; N] {
self.0
}
}
pub trait NonceGenerator<const N: usize> {
fn init() -> Result<Self, Unspecified>
where
Self: Sized;
fn generate(&self) -> Result<Nonce<N>, Unspecified>;
}
pub struct RandomNonceGenerator<const N: usize>(RefCell<SafeRand>);
impl<const N: usize> NonceGenerator<N> for RandomNonceGenerator<N> {
fn init() -> Result<Self, Unspecified> {
let rng = SafeRand::from_entropy().map_err(|_| Unspecified)?;
Ok(Self(RefCell::new(rng)))
}
fn generate(&self) -> Result<Nonce<N>, Unspecified> {
let mut rng = self.0.borrow_mut();
Generatable::random(&mut rng)
.map_err(|_| Unspecified)
.map(Nonce::new)
}
}