1#![allow(unused)]
2#![cfg_attr(feature = "allocator-api", feature(allocator_api))]
3#![cfg_attr(feature = "allocator-api", feature(alloc_layout_extra))]
4#![cfg_attr(feature = "allocator-api", feature(slice_ptr_get))]
5
6extern crate cheap as _;
7extern crate libc;
8extern crate std;
9
10use std::{
11 alloc::GlobalAlloc,
12 alloc::Layout,
13 ptr::NonNull,
14 hint,
15 marker::PhantomPinned
16};
17#[cfg(feature = "allocator-api")]
18use std::alloc::{Allocator, AllocError};
19
20use libc::{size_t, c_void};
21
22extern "C" {
23 fn allocate(size: size_t, align: size_t) -> *mut c_void;
24 fn allocate_zeroed(size: size_t, align: size_t) -> *mut c_void;
25 fn reallocate(ptr: *mut c_void, size: size_t, align: size_t, new_size: size_t) -> *mut c_void;
26 fn deallocate(ptr: *mut c_void, size: size_t, align: size_t);
27}
28
29#[derive(Debug, Clone, PartialEq, Eq, Hash)]
30#[repr(transparent)]
31pub struct Heap {
32 _pinned: PhantomPinned,
33}
34
35impl Heap {
36 pub const fn new() -> Heap {
37 Heap {
38 _pinned: PhantomPinned,
39 }
40 }
41}
42
43unsafe impl Send for Heap {}
44unsafe impl Sync for Heap {}
45
46unsafe impl GlobalAlloc for Heap {
47 unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
48 let size = layout.size() as size_t;
49 let align = layout.align() as size_t;
50 allocate(size, align) as *mut u8
51 }
52 unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
53 let size = layout.size() as size_t;
54 let align = layout.align() as size_t;
55 deallocate(ptr as *mut c_void, size, align)
56 }
57 unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
58 let size = layout.size() as size_t;
59 let align = layout.align() as size_t;
60 reallocate(ptr as *mut c_void, size, align, new_size as size_t) as *mut u8
61 }
62 unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
63 let size = layout.size() as size_t;
64 let align = layout.align() as size_t;
65 allocate_zeroed(size, align) as *mut u8
66 }
67}
68
69#[cfg(feature = "allocator-api")]
70
71impl Heap {
72 #[inline]
73 fn alloc_impl(&self, layout: Layout, zeroed: bool) -> Result<NonNull<[u8]>, AllocError> {
74 match layout.size() {
75 0 => Ok(NonNull::slice_from_raw_parts(layout.dangling(), 0)),
76 size => unsafe {
77 let raw = if zeroed {
78 self.alloc_zeroed(layout)
79 } else {
80 self.alloc(layout)
81 };
82 let ptr = NonNull::new(raw).ok_or(AllocError)?;
83 Ok(NonNull::slice_from_raw_parts(ptr, size))
84 },
85 }
86 }
87 #[inline]
88 unsafe fn grow_impl(&self, ptr: NonNull<u8>, old_layout: Layout, new_layout: Layout, zeroed: bool) -> Result<NonNull<[u8]>, AllocError> {
89 debug_assert!(new_layout.size() >= old_layout.size(), "new_layout.size() must be greater then or equal to old_layout.size()");
90 match old_layout.size() {
91 0 => self.alloc_impl(new_layout, zeroed),
92 old_size if old_layout.align() == new_layout.align() => unsafe {
93 let new_size = new_layout.size();
94 hint::assert_unchecked(new_size >= old_layout.size());
95 let raw = self.realloc(ptr.as_ptr(), old_layout, new_size);
96 let ptr = NonNull::new(raw).ok_or(AllocError)?;
97 if zeroed {
98 raw.add(old_size).write_bytes(0, new_size - old_size);
99 }
100 Ok(NonNull::slice_from_raw_parts(ptr, new_size))
101 },
102 old_size => unsafe {
103 let new = self.alloc_impl(new_layout, zeroed)?;
104 std::ptr::copy_nonoverlapping(ptr.as_ptr(), new.as_mut_ptr(), old_size);
105 self.deallocate(ptr, old_layout);
106 Ok(new)
107 },
108 }
109 }
110}
111
112#[cfg(feature = "allocator-api")]
113unsafe impl Allocator for Heap {
114 #[inline]
115 fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
116 self.alloc_impl(layout, false)
117 }
118 #[inline]
119 fn allocate_zeroed(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
120 self.alloc_impl(layout, true)
121 }
122 #[inline]
123 unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
124 if layout.size() != 0 {
125 unsafe {
126 self.dealloc(ptr.as_ptr(), layout)
127 }
128 }
129 }
130 #[inline]
131 unsafe fn grow(
132 &self,
133 ptr: NonNull<u8>,
134 old_layout: Layout,
135 new_layout: Layout,
136 ) -> Result<NonNull<[u8]>, AllocError> {
137 unsafe {
138 self.grow_impl(ptr, old_layout, new_layout, false)
139 }
140 }
141 #[inline]
142 unsafe fn grow_zeroed(
143 &self,
144 ptr: NonNull<u8>,
145 old_layout: Layout,
146 new_layout: Layout,
147 ) -> Result<NonNull<[u8]>, AllocError> {
148 unsafe {
149 self.grow_impl(ptr, old_layout, new_layout, true)
150 }
151 }
152 #[inline]
153 unsafe fn shrink(
154 &self,
155 ptr: NonNull<u8>,
156 old_layout: Layout,
157 new_layout: Layout,
158 ) -> Result<NonNull<[u8]>, AllocError> {
159 debug_assert!(new_layout.size() <= old_layout.size(), "new_layout.size() must be smaller then or equal to old_layout.size()");
160
161 match new_layout.size() {
162 0 => unsafe {
163 self.deallocate(ptr, old_layout);
164 Ok(NonNull::slice_from_raw_parts(new_layout.dangling(), 0))
165 },
166 new_size if old_layout.align() == new_layout.align() => unsafe {
167 hint::assert_unchecked(new_size <= old_layout.size());
168 let raw = self.realloc(ptr.as_ptr(), old_layout, new_size);
169 let ptr = NonNull::new(raw).ok_or(AllocError)?;
170 Ok(NonNull::slice_from_raw_parts(ptr, new_size))
171 },
172 new_size => unsafe {
173 let new = self.allocate(new_layout)?;
174 std::ptr::copy_nonoverlapping(ptr.as_ptr(), new.as_mut_ptr(), new_size);
175 self.deallocate(ptr, old_layout);
176 Ok(new)
177 },
178 }
179 }
180}
181
182#[cfg(feature = "allocator-api")]
183pub type Vec<T> = std::vec::Vec<T, Heap>;
184#[cfg(feature = "allocator-api")]
185pub type Box<T> = std::boxed::Box<T, Heap>;
186
187