use crate::{Align, Alloc, Allocator, Brand, Error, Layout};
use core::ptr::NonNull;
unsafe extern "C" {
fn aligned_alloc(align: usize, size: usize) -> *mut core::ffi::c_void;
fn free(ptr: *mut core::ffi::c_void);
}
pub struct PlatformAllocator(Brand);
impl PlatformAllocator {
pub const fn new() -> Self {
Self(unsafe { crate::Brand::platform() })
}
}
impl Default for PlatformAllocator {
fn default() -> Self { Self::new() }
}
unsafe impl Allocator for PlatformAllocator {
fn brand(&self) -> &Brand {
&self.0
}
fn alloc_bytes(&self, layout: Layout) -> Result<Alloc<'_, u8>, Error> {
let align = layout.align.align();
if layout.size == 0 {
return Ok(unsafe {
Alloc::new(NonNull::new(align as *mut u8).unwrap(), layout, self)
});
}
let size = layout.size.div_ceil(align) * align;
let Some(ptr) = NonNull::new(unsafe { aligned_alloc(align, size) }) else {
return Err(Error::PlatformError);
};
Ok(unsafe { Alloc::new(ptr.cast(), layout, self) })
}
fn dealloc_bytes<'this>(&'this self, alloc: Alloc<'this, u8>) {
if alloc.allocator().brand() != &self.0 || alloc.layout().size == 0 {
return;
}
unsafe { free(alloc.as_ptr().cast()) };
}
fn dangling(&self, align: Align) -> Alloc<'_, u8> {
let layout = Layout { size: 0, align };
unsafe { Alloc::new(NonNull::new(align.align() as *mut u8).unwrap(), layout, self) }
}
}