#![warn(missing_docs, missing_debug_implementations)]
extern crate libc;
use std::mem;
use libc::{size_t, c_void};
extern {
fn bulletproof_register() -> size_t;
fn bulletproof_load(loc: *const size_t, dst: *mut size_t) -> size_t;
fn bulletproof_store(loc: *const size_t, val: size_t) -> size_t;
fn bulletproof_load_bytes(loc: *const c_void, dst: *mut c_void, size: size_t) -> size_t;
fn bulletproof_store_bytes(loc: *mut c_void, src: *const c_void, size: size_t) -> size_t;
}
#[derive(Debug, Clone, Copy)]
pub struct Bulletproof {}
impl Bulletproof {
#[inline]
pub unsafe fn new() -> Self {
assert_eq!(
bulletproof_register(),
0,
"bulletproof_register() failed",
);
Self {}
}
#[inline]
pub unsafe fn load_usize(self, location: *const usize) -> Result<usize, ()> {
let mut result: usize = mem::uninitialized();
if bulletproof_load(location, &mut result) != 0 {
return Err(());
}
Ok(result)
}
#[inline]
pub unsafe fn load<T>(self, location: *const T) -> Result<T, ()> {
let mut result: T = mem::uninitialized();
let buffer = &mut result as *mut T as *mut c_void;
if bulletproof_load_bytes(
location as *const c_void,
buffer,
mem::size_of::<T>(),
) != 0 {
return Err(());
}
Ok(result)
}
#[inline]
pub unsafe fn store_usize(self, location: *mut usize, val: usize) -> Result<(), ()> {
if bulletproof_store(location, val) != 0 {
return Err(());
}
Ok(())
}
#[inline]
pub unsafe fn store<T>(self, location: *mut T, src: &T) -> Result<(), ()> {
if bulletproof_store_bytes(
location as *mut c_void,
src as *const T as *const c_void,
mem::size_of::<T>(),
) != 0 {
return Err(());
}
Ok(())
}
}
#[cfg(test)]
mod tests {
use std::ptr;
use super::*;
#[test]
fn bulletproof() {
let mut x = 42usize;
let y = 42u8;
unsafe {
let bulletproof = Bulletproof::new();
assert_eq!(bulletproof.load_usize(&x), Ok(42));
assert_eq!(bulletproof.load_usize(ptr::null()), Err(()));
assert_eq!(bulletproof.store_usize(&mut x, 37), Ok(()));
assert_eq!(bulletproof.store_usize(ptr::null_mut(), 37), Err(()));
assert_eq!(bulletproof.load_usize(&x), Ok(37));
assert_eq!(ptr::read(&x), 37);
assert_eq!(bulletproof.load(&y), Ok(42));
assert_eq!(bulletproof.load::<[usize; 32]>(ptr::null()), Err(()));
}
}
}