use core::ffi::c_void;
use crate::default_alloc;
use crate::{Alignment, AllocatorVTable, StdAllocator};
pub(crate) fn default_allocator_free(_: *mut c_void, buf: &mut [u8], _: Alignment, _: usize) {
unsafe { default_alloc::free(buf.as_mut_ptr().cast()) }
}
pub(crate) struct DefaultAllocator;
impl DefaultAllocator {
fn aligned_alloc(len: usize, alignment: Alignment) -> *mut u8 {
let ptr: *mut c_void = default_alloc::malloc_aligned(len, alignment.to_byte_units());
#[cfg(debug_assertions)]
{
if !ptr.is_null() {
let usable = unsafe { default_alloc::usable_size(ptr) };
if usable < len && !ptr.is_null() {
panic!(
"default allocator: allocated size is too small: {} < {}",
usable, len
);
}
}
}
ptr.cast::<u8>()
}
fn alloc_with_default_allocator(
_: *mut c_void,
len: usize,
alignment: Alignment,
_: usize,
) -> *mut u8 {
Self::aligned_alloc(len, alignment)
}
pub(crate) fn resize_with_default_allocator(
_: *mut c_void,
buf: &mut [u8],
_: Alignment,
new_len: usize,
_: usize,
) -> bool {
let _ = (buf, new_len);
false
}
pub(crate) fn remap_with_default_allocator(
_: *mut c_void,
buf: &mut [u8],
alignment: Alignment,
new_len: usize,
_: usize,
) -> *mut u8 {
unsafe {
default_alloc::realloc_aligned(
buf.as_mut_ptr().cast(),
new_len,
alignment.to_byte_units(),
)
.cast::<u8>()
}
}
const FREE_WITH_DEFAULT_ALLOCATOR: fn(*mut c_void, &mut [u8], Alignment, usize) =
default_allocator_free;
}
pub static C_ALLOCATOR: StdAllocator = StdAllocator {
ptr: memory_allocator_tags::DEFAULT_ALLOCATOR_TAG_PTR,
vtable: C_ALLOCATOR_VTABLE,
};
static C_ALLOCATOR_VTABLE: &AllocatorVTable = &AllocatorVTable {
alloc: DefaultAllocator::alloc_with_default_allocator,
resize: DefaultAllocator::resize_with_default_allocator,
remap: DefaultAllocator::remap_with_default_allocator,
free: DefaultAllocator::FREE_WITH_DEFAULT_ALLOCATOR,
};
pub(crate) struct ZAllocator;
impl ZAllocator {
fn aligned_alloc(len: usize, alignment: Alignment) -> *mut u8 {
let ptr: *mut c_void = default_alloc::zalloc_aligned(len, alignment.to_byte_units());
#[cfg(debug_assertions)]
{
if !ptr.is_null() {
let usable = unsafe { default_alloc::usable_size(ptr) };
if usable < len {
panic!(
"default allocator: allocated size is too small: {} < {}",
usable, len
);
}
}
}
ptr.cast::<u8>()
}
fn aligned_alloc_size(ptr: *mut u8) -> usize {
unsafe { default_alloc::usable_size(ptr.cast()) }
}
fn alloc_with_z_allocator(
_: *mut c_void,
len: usize,
alignment: Alignment,
_: usize,
) -> *mut u8 {
Self::aligned_alloc(len, alignment)
}
fn resize_with_z_allocator(
_: *mut c_void,
buf: &mut [u8],
_: Alignment,
new_len: usize,
_: usize,
) -> bool {
if new_len <= buf.len() {
return true;
}
let full_len = Self::aligned_alloc_size(buf.as_mut_ptr());
if new_len <= full_len {
return true;
}
false
}
const FREE_WITH_Z_ALLOCATOR: fn(*mut c_void, &mut [u8], Alignment, usize) =
default_allocator_free;
}
pub(crate) mod memory_allocator_tags {
use core::ffi::c_void;
const DEFAULT_ALLOCATOR_TAG: usize = 0xBEEFA110C; pub(crate) const DEFAULT_ALLOCATOR_TAG_PTR: *mut c_void = DEFAULT_ALLOCATOR_TAG as *mut c_void;
const Z_ALLOCATOR_TAG: usize = 0x2a11043470123; pub(crate) const Z_ALLOCATOR_TAG_PTR: *mut c_void = Z_ALLOCATOR_TAG as *mut c_void;
}
pub static Z_ALLOCATOR: StdAllocator = StdAllocator {
ptr: memory_allocator_tags::Z_ALLOCATOR_TAG_PTR,
vtable: &Z_ALLOCATOR_VTABLE,
};
static Z_ALLOCATOR_VTABLE: AllocatorVTable = AllocatorVTable {
alloc: ZAllocator::alloc_with_z_allocator,
resize: ZAllocator::resize_with_z_allocator,
remap: AllocatorVTable::NO_REMAP,
free: ZAllocator::FREE_WITH_Z_ALLOCATOR,
};