rune_alloc/alloc/
global.rs
1use core::alloc::Layout;
2
3use crate::alloc::{AllocError, Allocator};
4use crate::ptr::{invalid_mut, NonNull};
5
6#[cfg(feature = "alloc")]
7use ::rust_alloc::alloc::{alloc, alloc_zeroed, dealloc};
8
9pub(crate) const fn dangling<T>(layout: &Layout) -> NonNull<T> {
15 unsafe { NonNull::new_unchecked(invalid_mut::<T>(layout.align())) }
16}
17
18#[derive(Default, Debug, Clone, Copy)]
25pub struct Global;
26
27impl Global {
28 pub(crate) fn release(&self, layout: Layout) {
30 crate::limit::release(layout.size());
31 }
32
33 pub(crate) fn take(&self, layout: Layout) -> Result<(), AllocError> {
35 if !crate::limit::take(layout.size()) {
36 return Err(AllocError { layout });
37 }
38
39 Ok(())
40 }
41
42 #[inline]
43 fn alloc_impl(&self, layout: Layout, zeroed: bool) -> Result<NonNull<[u8]>, AllocError> {
44 self.take(layout)?;
45
46 match layout.size() {
47 0 => Ok(NonNull::slice_from_raw_parts(dangling(&layout), 0)),
48 size => unsafe {
50 let raw_ptr = if zeroed {
51 alloc_zeroed(layout)
52 } else {
53 alloc(layout)
54 };
55
56 let Some(ptr) = NonNull::new(raw_ptr) else {
57 return Err(AllocError { layout });
58 };
59
60 Ok(NonNull::slice_from_raw_parts(ptr, size))
61 },
62 }
63 }
64}
65
66unsafe impl Allocator for Global {
67 #[inline]
68 fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
69 self.alloc_impl(layout, false)
70 }
71
72 #[inline]
73 fn allocate_zeroed(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
74 self.alloc_impl(layout, true)
75 }
76
77 unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
78 if layout.size() != 0 {
79 dealloc(ptr.as_ptr(), layout);
82 self.release(layout);
83 }
84 }
85}