rune_alloc/alloc/
global.rsuse core::alloc::Layout;
use crate::alloc::{AllocError, Allocator};
use crate::ptr::{invalid_mut, NonNull};
#[cfg(feature = "alloc")]
use ::rust_alloc::alloc::{alloc, alloc_zeroed, dealloc};
pub(crate) const fn dangling<T>(layout: &Layout) -> NonNull<T> {
unsafe { NonNull::new_unchecked(invalid_mut::<T>(layout.align())) }
}
#[derive(Default, Debug, Clone, Copy)]
pub struct Global;
impl Global {
pub(crate) fn release(&self, layout: Layout) {
crate::limit::release(layout.size());
}
pub(crate) fn take(&self, layout: Layout) -> Result<(), AllocError> {
if !crate::limit::take(layout.size()) {
return Err(AllocError { layout });
}
Ok(())
}
#[inline]
fn alloc_impl(&self, layout: Layout, zeroed: bool) -> Result<NonNull<[u8]>, AllocError> {
self.take(layout)?;
match layout.size() {
0 => Ok(NonNull::slice_from_raw_parts(dangling(&layout), 0)),
size => unsafe {
let raw_ptr = if zeroed {
alloc_zeroed(layout)
} else {
alloc(layout)
};
let Some(ptr) = NonNull::new(raw_ptr) else {
return Err(AllocError { layout });
};
Ok(NonNull::slice_from_raw_parts(ptr, size))
},
}
}
}
unsafe impl Allocator for Global {
#[inline]
fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
self.alloc_impl(layout, false)
}
#[inline]
fn allocate_zeroed(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
self.alloc_impl(layout, true)
}
unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
if layout.size() != 0 {
dealloc(ptr.as_ptr(), layout);
self.release(layout);
}
}
}