use crate::alloc_result::AllocationError;
use ::core::ptr;
use ::std::alloc;
pub fn alloc_aligned(
num_bytes: usize,
alignment: usize,
clear: bool,
) -> Result<ptr::NonNull<std::ffi::c_void>, AllocationError> {
if num_bytes == 0 {
return Err(AllocationError::EmptyAllocation);
}
let layout = match alloc::Layout::from_size_align(num_bytes, alignment) {
Err(e) => return Err(AllocationError::InvalidAlignment(e)),
Ok(layout) => layout,
};
let address = ptr::NonNull::new(unsafe {
if clear {
alloc::alloc_zeroed(layout)
} else {
alloc::alloc(layout)
}
})
.expect("ptr is null")
.cast::<std::ffi::c_void>();
Ok(address)
}
pub unsafe fn free_aligned(
ptr: Option<ptr::NonNull<std::ffi::c_void>>,
num_bytes: usize,
alignment: usize,
) {
let ptr = if let Some(ptr) = ptr {
ptr
} else {
return;
};
let layout = match alloc::Layout::from_size_align(num_bytes, alignment) {
Ok(layout) => layout,
Err(_) => {
return;
}
};
alloc::dealloc(ptr.cast::<u8>().as_ptr(), layout);
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
#[allow(useless_ptr_null_checks)]
fn test_alloc_aligned() {
let num_bytes = 1024;
let alignment = 16;
let clear = true;
let ptr = alloc_aligned(num_bytes, alignment, clear).expect("Allocation failed");
assert!(!ptr.as_ptr().is_null());
unsafe {
free_aligned(Some(ptr), num_bytes, alignment);
}
}
#[test]
fn test_alloc_aligned_invalid_alignment() {
let num_bytes = 1024;
let alignment = 3; let clear = true;
let result = alloc_aligned(num_bytes, alignment, clear);
assert!(result.is_err());
}
#[test]
fn test_alloc_aligned_zero_bytes() {
let num_bytes = 0;
let alignment = 16;
let clear = true;
let result = alloc_aligned(num_bytes, alignment, clear);
assert!(result.is_err());
}
#[test]
fn test_free_aligned_null_pointer() {
let num_bytes = 1024;
let alignment = 16;
unsafe {
free_aligned(None, num_bytes, alignment);
}
}
}