#![cfg_attr(not(test), no_std)]
#![deny(missing_docs)]
use core::alloc::{GlobalAlloc, Layout};
pub use rusty_alloc::{MI_COMPAT_VERSION, VERSION, version};
pub struct RustyAlloc;
pub struct Heap {
hb: *mut rusty_alloc::init::HeapBox,
destroy_on_drop: bool,
}
impl Heap {
pub fn new() -> Heap {
Heap {
hb: rusty_alloc::init::create_heap(0, false, -1),
destroy_on_drop: false,
}
}
pub fn new_destroyable() -> Heap {
Heap {
hb: rusty_alloc::init::create_heap(0, true, -1),
destroy_on_drop: true,
}
}
pub fn alloc(&self, layout: core::alloc::Layout) -> Option<core::ptr::NonNull<u8>> {
let p = unsafe {
if layout.align() <= 8 {
rusty_alloc::alloc::heap_malloc(self.hb, layout.size())
} else {
rusty_alloc::alloc::heap_malloc_aligned_at(
self.hb,
layout.size(),
layout.align(),
0,
)
}
};
core::ptr::NonNull::new(p)
}
pub fn alloc_zeroed(&self, layout: core::alloc::Layout) -> Option<core::ptr::NonNull<u8>> {
let p = unsafe {
if layout.align() <= 8 {
rusty_alloc::alloc::heap_zalloc(self.hb, layout.size())
} else {
rusty_alloc::alloc::heap_zalloc_aligned_at(
self.hb,
layout.size(),
layout.align(),
0,
)
}
};
core::ptr::NonNull::new(p)
}
pub unsafe fn dealloc(&self, p: core::ptr::NonNull<u8>) {
unsafe { rusty_alloc::alloc::free(p.as_ptr()) }
}
pub fn collect(&self) {
unsafe { rusty_alloc::alloc::heap_collect(self.hb, true) }
}
}
impl Default for Heap {
fn default() -> Self {
Self::new()
}
}
impl Drop for Heap {
fn drop(&mut self) {
unsafe {
if self.destroy_on_drop {
rusty_alloc::init::heap_destroy(self.hb);
} else {
rusty_alloc::init::heap_delete(self.hb);
}
}
}
}
unsafe impl GlobalAlloc for RustyAlloc {
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
if layout.align() <= 8 {
rusty_alloc::alloc::malloc(layout.size())
} else {
rusty_alloc::alloc::malloc_aligned(layout.size(), layout.align())
}
}
unsafe fn dealloc(&self, ptr: *mut u8, _layout: Layout) {
unsafe { rusty_alloc::alloc::free(ptr) }
}
unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
if layout.align() <= 8 {
rusty_alloc::alloc::zalloc(layout.size())
} else {
rusty_alloc::alloc::zalloc_aligned(layout.size(), layout.align())
}
}
unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
if layout.align() <= 8 {
unsafe { rusty_alloc::alloc::realloc(ptr, new_size) }
} else {
unsafe {
let new_layout = Layout::from_size_align_unchecked(new_size, layout.align());
let np = GlobalAlloc::alloc(self, new_layout);
if !np.is_null() {
core::ptr::copy_nonoverlapping(ptr, np, layout.size().min(new_size));
GlobalAlloc::dealloc(self, ptr, layout);
}
np
}
}
}
}