#![feature(asm)]
extern crate rand;
use rand::Rng;
use std::result::Result;
mod util;
#[derive(Copy, Clone, Debug)]
pub enum Error {
UnsupportedProcessor
}
impl ::std::error::Error for Error {
fn description(&self) -> &str {
match self {
&Error::UnsupportedProcessor => "processor does not support the instruction",
}
}
}
impl ::std::fmt::Display for Error {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
match self {
&Error::UnsupportedProcessor => write!(f, "processor does not support the instruction")
}
}
}
impl From<Error> for ::std::io::Error {
fn from(e: Error) -> ::std::io::Error {
::std::io::Error::new(::std::io::ErrorKind::Other, format!("{}", e))
}
}
#[allow(missing_copy_implementations)]
#[derive(Clone)]
pub struct RdRand(());
impl RdRand {
pub fn new() -> Result<RdRand, Error> {
if util::is_intel() && util::has_rdrand() {
return Ok(RdRand(()));
} else {
return Err(Error::UnsupportedProcessor);
}
}
#[inline]
fn gen_value<T>(&self) -> T {
let var;
unsafe {
asm!("1: rdrand $0; jnc 1b;" : "=r"(var));
}
var
}
pub fn next_u16(&self) -> u16 {
self.gen_value()
}
}
impl Rng for RdRand {
fn next_u32(&mut self) -> u32 {
self.gen_value()
}
fn next_u64(&mut self) -> u64 {
self.gen_value()
}
}
#[allow(missing_copy_implementations)]
#[derive(Clone)]
pub struct RdSeed(());
impl RdSeed {
pub fn new() -> Result<RdSeed, Error> {
if util::is_intel() && util::has_rdseed() {
return Ok(RdSeed(()));
} else {
return Err(Error::UnsupportedProcessor);
}
}
#[inline]
fn gen_value<T>(&self) -> T {
let var;
unsafe {
asm!("1: rdseed $0; jnc 1b;" : "=r"(var));
}
var
}
pub fn next_u16(&self) -> u16 {
self.gen_value()
}
}
impl Rng for RdSeed {
fn next_u32(&mut self) -> u32 {
self.gen_value()
}
fn next_u64(&mut self) -> u64 {
self.gen_value()
}
}
#[test]
fn rdrand_works() {
let _ = RdRand::new().map(|mut r| {
r.next_u32();
r.next_u64();
});
}
#[test]
fn rdseed_works() {
let _ = RdSeed::new().map(|mut r| {
r.next_u32();
r.next_u64();
});
}