1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
use super::ensure_initialized;
use crate::ffi;
use crate::utils;

pub const SEEDBYTES: usize = ffi::hydro_random_SEEDBYTES as usize;

#[derive(Debug, Clone)]
pub struct Seed([u8; SEEDBYTES]);

#[inline]
pub fn u32() -> u32 {
    ensure_initialized();
    unsafe { ffi::hydro_random_u32() }
}

#[inline]
pub fn uniform(upper_bound: u32) -> u32 {
    ensure_initialized();
    unsafe { ffi::hydro_random_uniform(upper_bound) }
}

#[inline]
pub fn buf_into(out: &mut [u8]) {
    ensure_initialized();
    unsafe {
        ffi::hydro_random_buf(out.as_mut_ptr() as *mut _, out.len());
    }
}

pub fn buf(out_len: usize) -> Vec<u8> {
    let mut out = vec![0u8; out_len];
    buf_into(&mut out);
    out
}

#[inline]
pub fn buf_deterministic_into(out: &mut [u8], seed: &Seed) {
    ensure_initialized();
    unsafe {
        ffi::hydro_random_buf_deterministic(out.as_mut_ptr() as *mut _, out.len(), seed.0.as_ptr())
    }
}

#[inline]
pub fn buf_deterministic(out_len: usize, seed: &Seed) -> Vec<u8> {
    let mut out = vec![0u8; out_len];
    buf_deterministic_into(&mut out, seed);
    out
}

#[inline]
pub fn ratchet() {
    ensure_initialized();
    unsafe {
        ffi::hydro_random_ratchet();
    }
}

#[inline]
pub fn reseed() {
    ensure_initialized();
    unsafe {
        ffi::hydro_random_reseed();
    }
}

impl Drop for Seed {
    fn drop(&mut self) {
        utils::memzero(self)
    }
}

impl From<[u8; SEEDBYTES]> for Seed {
    #[inline]
    fn from(seed: [u8; SEEDBYTES]) -> Seed {
        Seed(seed)
    }
}

impl Into<[u8; SEEDBYTES]> for Seed {
    #[inline]
    fn into(self) -> [u8; SEEDBYTES] {
        self.0
    }
}

impl AsRef<[u8]> for Seed {
    fn as_ref(&self) -> &[u8] {
        &self.0 as &[u8]
    }
}

impl PartialEq for Seed {
    fn eq(&self, other: &Self) -> bool {
        utils::equal(self, other)
    }
}

impl Eq for Seed {}

impl Seed {
    pub fn gen() -> Seed {
        let mut seed_inner = [0u8; SEEDBYTES];
        buf_into(&mut seed_inner);
        Seed(seed_inner)
    }
}

#[cfg(test)]
mod tests {
    use crate::*;

    #[test]
    fn test_randombytes() {
        init().unwrap();
        assert_ne!(random::u32() | random::u32() | random::u32(), 0);

        for _ in 0..100 {
            let max = random::u32();
            assert!(random::uniform(max) < max)
        }

        let len = random::uniform(100) as usize + 1;
        let mut buf = random::buf(len);
        random::buf_into(&mut buf);

        let seed = random::Seed::gen();
        let buf = random::buf_deterministic(len, &seed);
        let mut buf2 = vec![0u8; len];
        random::buf_deterministic_into(&mut buf2, &seed);
        assert_eq!(buf, buf2);

        let seedx: [u8; random::SEEDBYTES] = seed.clone().into();
        let seedy: random::Seed = seedx.into();
        assert_eq!(seed, seedy);

        random::ratchet();

        random::reseed();
    }
}