use std::mem::size_of_val;
use rand::Rng;
use byteorder::{ BigEndian, ByteOrder };
pub trait GenNonce {
fn fill(&mut self, nonce: &mut [u8]);
fn gen(&mut self, len: usize) -> Vec<u8> {
let mut output = vec![0; len];
self.fill(&mut output);
output
}
}
impl<T: Rng> GenNonce for T {
#[inline]
fn fill(&mut self, nonce: &mut [u8]) {
self.fill_bytes(nonce)
}
}
#[derive(Debug, Clone)]
pub struct Counter(pub u64);
impl Default for Counter {
fn default() -> Counter {
Counter(0)
}
}
impl GenNonce for Counter {
fn fill(&mut self, nonce: &mut [u8]) {
let nonce_len = nonce.len();
let ctr_len = size_of_val(&self.0);
assert!(nonce_len >= ctr_len);
let (_, ctr) = nonce.split_at_mut(nonce_len - ctr_len);
BigEndian::write_u64(ctr, self.0);
self.0 = self.0.checked_add(1).expect("Counter overflow.");
}
}
#[test]
fn test_counter() {
let mut output = [0; 12];
let mut ctr = Counter::default();
ctr.fill(&mut output);
assert_eq!(BigEndian::read_u64(&output[4..]), 0);
ctr.fill(&mut output);
assert_eq!(BigEndian::read_u64(&output[4..]), 1);
}