#![feature(asm)]
use std::rand::Rng;
use std::result::Result;
struct PrivateInner;
pub struct RdRand(PrivateInner);
#[deriving(Copy)]
#[stable]
pub enum Error {
UnsupportedProcessor
}
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
fn is_supported() -> bool {
const FLAG : u32 = 1 << 30;
let (mut b, mut c, mut d) : (u32, u32, u32);
unsafe {
asm!("
mov eax, 0;
cpuid;
mov $0, ebx;
mov $1, ecx;
mov $2, edx;
"
: "=r"(b), "=r"(c), "=r"(d)
:
: "eax", "ebx", "ecx", "edx"
: "intel");
}
if b != 0x756E6547 || d != 0x49656e69 || c != 0x6C65746E {
return false;
}
unsafe {
asm!("
mov eax, 1;
mov ecx, 0;
cpuid;
mov $0, ecx;
"
: "=r"(c)
:
: "eax", "ebx", "ecx", "edx"
: "intel");
}
return c & FLAG == FLAG
}
impl RdRand {
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
pub fn new() -> Result<RdRand, Error> {
if is_supported() {
return Ok(RdRand(PrivateInner));
} else {
return Err(Error::UnsupportedProcessor);
}
}
#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
pub fn new() -> Result<RdRand, Error> {
Err(Error::UnsupportedProcessor)
}
#[inline]
fn gen_value<T>(&self) -> T {
let mut 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()
}
}