use crate::ctypes;
use crate::ffi;
#[cfg(not(test))]
use crate::panic;
use core::alloc::{AllocError, Allocator, GlobalAlloc, Layout};
use core::ptr::NonNull;
#[cfg_attr(docsrs, doc(cfg(feature = "global_allocator")))]
#[cfg(feature = "global_allocator")]
#[cfg(not(test))]
#[global_allocator]
pub static ALLOCATOR: EoSDefaultAllocator = EoSDefaultAllocator;
pub struct EoSDefaultAllocator;
unsafe impl GlobalAlloc for EoSDefaultAllocator {
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
ffi::MemAlloc(layout.size() as u32, 0) as *mut u8
}
unsafe fn dealloc(&self, ptr: *mut u8, _layout: Layout) {
ffi::MemFree(ptr as *mut ctypes::c_void);
}
}
unsafe impl Allocator for EoSDefaultAllocator {
fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
unsafe {
let raw_ptr = ffi::MemAlloc(layout.size() as u32, 0) as *mut u8;
let ptr = NonNull::new(raw_ptr).ok_or(AllocError)?;
Ok(NonNull::slice_from_raw_parts(ptr, layout.size()))
}
}
unsafe fn deallocate(&self, ptr: NonNull<u8>, _layout: Layout) {
ffi::MemFree(ptr.as_ptr() as *mut ctypes::c_void);
}
}
pub struct EoSCustomAllocator(*mut ffi::mem_arena);
impl EoSCustomAllocator {
pub const unsafe fn new(arena: *mut ffi::mem_arena) -> Self {
EoSCustomAllocator(arena)
}
}
unsafe impl GlobalAlloc for EoSCustomAllocator {
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
ffi::MemLocateSet(self.0, layout.size() as u32, 0) as *mut u8
}
unsafe fn dealloc(&self, ptr: *mut u8, _layout: Layout) {
ffi::MemLocateUnset(self.0, ptr as *mut ctypes::c_void);
}
}
unsafe impl Allocator for EoSCustomAllocator {
fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
unsafe {
let raw_ptr = ffi::MemLocateSet(self.0, layout.size() as u32, 0) as *mut u8;
let ptr = NonNull::new(raw_ptr).ok_or(AllocError)?;
Ok(NonNull::slice_from_raw_parts(ptr, layout.size()))
}
}
unsafe fn deallocate(&self, ptr: NonNull<u8>, _layout: Layout) {
ffi::MemLocateUnset(self.0, ptr.as_ptr() as *mut ctypes::c_void);
}
}
pub unsafe fn create_mem_arena(mem: *mut ffi::iovec, max_blocks: u32) -> *mut ffi::mem_arena {
ffi::CreateMemArena(mem, max_blocks)
}
#[cfg(not(test))]
#[alloc_error_handler]
pub fn alloc_error_handler(_: Layout) -> ! {
let err = b"[rs] OUT OF MEMORY!\0";
unsafe {
ffi::DebugPrint(2, err.as_ptr() as *const ctypes::c_char);
}
unsafe { panic::WaitForever() }
}