use crate::alloc_result::AllocResult;
use std::mem::ManuallyDrop;
use std::ptr::null_mut;
#[repr(C)]
pub struct Memory {
pub status: u32,
pub flags: u32,
pub num_bytes: usize,
pub address: *mut std::ffi::c_void,
}
pub static VERSION: &str = concat!(env!("CARGO_PKG_VERSION"), "\0");
#[no_mangle]
pub unsafe extern "C" fn version() -> *const libc::c_char {
VERSION.as_ptr() as *const libc::c_char
}
#[no_mangle]
pub unsafe extern "C" fn allocate_block(num_bytes: usize, sequential: bool, clear: bool) -> Memory {
match crate::memory::Memory::allocate(num_bytes, sequential, clear) {
Ok(memory) => {
let memory = ManuallyDrop::new(memory);
Memory {
status: AllocResult::Ok as u32,
flags: memory.flags,
num_bytes: memory.num_bytes,
address: memory.address,
}
}
Err(e) => {
let result: AllocResult = e.into();
Memory {
status: result as u32,
flags: 0,
num_bytes: 0,
address: null_mut(),
}
}
}
}
#[no_mangle]
pub unsafe extern "C" fn free_block(memory: Memory) {
let mut wrapped: crate::memory::Memory = memory.into();
wrapped.free();
}
impl From<Memory> for crate::memory::Memory {
fn from(val: Memory) -> Self {
crate::memory::Memory::new(
AllocResult::from(val.status),
val.flags,
val.num_bytes,
val.address,
)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_version() {
unsafe {
let version_ptr = version();
let version_cstr = std::ffi::CStr::from_ptr(version_ptr);
assert_eq!(version_cstr.to_str().unwrap(), env!("CARGO_PKG_VERSION"));
}
}
#[test]
fn test_allocate_block_success() {
unsafe {
let memory = allocate_block(1024, false, false);
assert_eq!(memory.status, AllocResult::Ok as u32);
assert_eq!(memory.num_bytes, 1024);
assert!(!memory.address.is_null());
free_block(memory);
}
}
#[test]
fn test_allocate_block_failure() {
unsafe {
let memory = allocate_block(0, false, false);
assert_ne!(memory.status, AllocResult::Ok as u32);
assert_eq!(memory.num_bytes, 0);
assert!(memory.address.is_null());
}
}
#[test]
fn test_free_block() {
unsafe {
let memory = allocate_block(1024, false, false);
assert_eq!(memory.status, AllocResult::Ok as u32);
assert_eq!(memory.num_bytes, 1024);
assert!(!memory.address.is_null());
free_block(memory);
}
}
}