1use std::alloc::{GlobalAlloc, Layout, System};
8use std::ffi::c_void;
9use std::mem;
10use std::ptr;
11
12#[allow(non_camel_case_types)]
13pub(crate) type size_t = usize;
14const ALIGN: usize = 8;
15
16#[cfg_attr(not(test), no_mangle)]
19pub unsafe extern "C" fn malloc(size: size_t) -> *mut c_void {
20 let ptr_size = mem::size_of::<*mut usize>();
21 let alloc_size = size + ptr_size;
22 let alloc_layout = Layout::from_size_align_unchecked(alloc_size, ALIGN);
23 let ptr = System.alloc(alloc_layout) as *mut usize;
24 if ptr == ptr::null_mut() {
25 return ptr::null_mut();
26 }
27 ptr::write(ptr, alloc_size);
28 ptr.offset(1) as *mut c_void
29}
30
31#[cfg_attr(not(test), no_mangle)]
32pub unsafe extern "C" fn calloc(n: size_t, size: size_t) -> *mut c_void {
33 let ptr_size = mem::size_of::<*mut usize>();
34 let alloc_size = (n * size) + ptr_size;
35 let alloc_layout = Layout::from_size_align_unchecked(alloc_size, ALIGN);
36 let ptr = System.alloc_zeroed(alloc_layout) as *mut usize;
37 if ptr == ptr::null_mut() {
38 return ptr::null_mut();
39 }
40 ptr::write(ptr, alloc_size);
41 ptr.offset(1) as *mut c_void
42}
43
44#[cfg_attr(not(test), no_mangle)]
45pub unsafe extern "C" fn realloc(ptr: *mut c_void, size: size_t) -> *mut c_void {
46 if ptr == ptr::null_mut() {
47 return malloc(size);
48 } else if size == 0 {
49 free(ptr);
50 return ptr::null_mut();
51 }
52
53 let ptr = (ptr as *mut usize).offset(-1);
54 let ptr_size = mem::size_of::<*mut usize>();
55 let old_alloc_layout = Layout::from_size_align_unchecked(ptr::read(ptr), ALIGN);
56 let new_alloc_size = size + ptr_size;
57
58 let ptr = System.realloc(ptr as _, old_alloc_layout, new_alloc_size) as *mut usize;
59 if ptr == ptr::null_mut() {
60 return ptr::null_mut();
61 }
62
63 ptr::write(ptr, new_alloc_size);
64 ptr.offset(1) as *mut c_void
65}
66
67#[cfg_attr(not(test), no_mangle)]
68pub unsafe extern "C" fn free(ptr: *mut c_void) {
69 if ptr == ptr::null_mut() {
70 return;
71 }
72 let ptr = (ptr as *mut usize).offset(-1);
73 let alloc_layout = Layout::from_size_align_unchecked(ptr::read(ptr), ALIGN);
74 System.dealloc(ptr as *mut u8, alloc_layout);
75}
76
77#[cfg(test)]
78mod tests {
79
80 use super::ALIGN;
82 use std::alloc::Layout;
83 #[test]
84 fn test_layout_unwrap() {
85 let _ = Layout::from_size_align(1, ALIGN).unwrap();
86 let _ = Layout::from_size_align(7, ALIGN).unwrap();
87 let _ = Layout::from_size_align(1025, ALIGN).unwrap();
88 }
89}