1#![no_std]
6#![allow(clippy::style)]
7
8extern crate alloc;
9
10pub mod align;
11
12use core::{mem, ptr};
13use core::ffi::c_void;
14use core::convert::TryInto;
15use alloc::alloc::Layout;
16
17pub const DEFAULT_ALIGNMENT: align::Alignment = {
21 #[cfg(any(target_os = "macos", all(windows, target_pointer_width = "64")))]
22 {
23 align::Alignment::new(16)
24 }
25 #[cfg(not(any(target_os = "macos", all(windows, target_pointer_width = "64"))))]
26 {
27 align::Alignment::new(8)
28 }
29};
30
31const LAYOUT_OFFSET: usize = DEFAULT_ALIGNMENT.next(mem::size_of::<usize>());
34
35#[cold]
36#[inline(never)]
37fn unlikely_null() -> *mut c_void {
38 ptr::null_mut()
39}
40
41#[inline(always)]
42unsafe fn get_ptr_size(ptr: *mut c_void) -> usize {
43 let mem = (ptr as *mut u8).offset(-(LAYOUT_OFFSET as isize));
44 let size = ptr::read(mem as *const usize);
45 size.saturating_sub(LAYOUT_OFFSET)
46}
47
48#[inline]
49pub unsafe extern "C" fn rust_malloc(mut size: usize) -> *mut c_void {
53 if size != 0 {
54 size = LAYOUT_OFFSET.saturating_add(DEFAULT_ALIGNMENT.next(size));
55
56 if let Ok(layout) = Layout::from_size_align(size, DEFAULT_ALIGNMENT.into_raw()) {
57 let mem = alloc::alloc::alloc(layout);
58 if !mem.is_null() {
59 ptr::write(mem as *mut usize, size);
60 return mem.add(LAYOUT_OFFSET) as _;
61 }
62 }
63 }
64
65 unlikely_null()
66}
67
68#[inline]
69pub unsafe extern "C" fn generic_rust_malloc<T: Into<usize>>(size: T) -> *mut c_void {
71 rust_malloc(size.into())
72}
73
74#[inline]
75pub unsafe extern "C" fn generic_try_rust_malloc<T: TryInto<usize>>(size: T) -> *mut c_void {
79 if let Ok(size) = size.try_into() {
80 rust_malloc(size)
81 } else {
82 unlikely_null()
83 }
84}
85
86#[inline]
87pub unsafe extern "C" fn rust_realloc(mut old_ptr: *mut c_void, mut new_size: usize) -> *mut c_void {
91 if new_size != 0 {
92 new_size = LAYOUT_OFFSET.saturating_add(DEFAULT_ALIGNMENT.next(new_size));
93
94 old_ptr = (old_ptr as *mut u8).offset(-(LAYOUT_OFFSET as isize)) as _;
95 let size = ptr::read(old_ptr as *const usize);
96 let layout = Layout::from_size_align_unchecked(size, DEFAULT_ALIGNMENT.into_raw());
97 let new_ptr = alloc::alloc::realloc(old_ptr as _, layout, new_size);
98 if !new_ptr.is_null() {
99 ptr::write(new_ptr as *mut usize, new_size);
100 return new_ptr.add(LAYOUT_OFFSET) as _;
101 }
102 }
103
104 unlikely_null()
105}
106
107#[inline]
108pub unsafe extern "C" fn generic_rust_realloc<T: Into<usize>>(mem: *mut c_void, size: T) -> *mut c_void {
110 rust_realloc(mem, size.into())
111}
112
113#[inline]
114pub unsafe extern "C" fn generic_try_rust_realloc<T: TryInto<usize>>(mem: *mut c_void, size: T) -> *mut c_void {
118 if let Ok(size) = size.try_into() {
119 rust_realloc(mem, size)
120 } else {
121 unlikely_null()
122 }
123}
124
125#[inline]
126pub unsafe extern "C" fn rust_calloc(mut size: usize) -> *mut c_void {
130 let ptr = rust_malloc(size);
131 if !ptr.is_null() {
132 size = get_ptr_size(ptr);
133 ptr::write_bytes(ptr as *mut u8, 0, size);
134 ptr
135 } else {
136 unlikely_null()
137 }
138}
139
140#[inline]
141pub unsafe extern "C" fn rust_size(mem: *mut c_void) -> usize {
145 if !mem.is_null() {
146 get_ptr_size(mem)
147 } else {
148 0
149 }
150}
151
152#[inline]
153pub unsafe extern "C" fn rust_free(mem: *mut c_void) {
157 if !mem.is_null() {
158 let mem = (mem as *mut u8).offset(-(LAYOUT_OFFSET as isize));
159 let size = ptr::read(mem as *const usize);
160 let layout = Layout::from_size_align_unchecked(size, DEFAULT_ALIGNMENT.into_raw());
161 alloc::alloc::dealloc(mem, layout);
162 }
163}