1use core::{
2 alloc::Layout,
3 ptr::{self, NonNull},
4};
5
6use allocator_api2_03::alloc::{AllocError, Allocator};
7
8#[cfg(feature = "alloc")]
9use allocator_api2_03::{alloc::Global, boxed::Box};
10
11use crate::{
12 BaseAllocator, Bump, BumpAllocatorExt, BumpScope, MinimumAlignment, SupportedMinimumAlignment, WithoutDealloc,
13 WithoutShrink,
14 alloc::{AllocError as CrateAllocError, Allocator as CrateAllocator},
15};
16
17#[cfg(feature = "alloc")]
18use crate::alloc::{BoxLike, box_like};
19
20#[cfg(feature = "alloc")]
21unsafe impl CrateAllocator for Global {
22 #[inline(always)]
23 fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, CrateAllocError> {
24 <Self as Allocator>::allocate(self, layout).map_err(Into::into)
25 }
26
27 #[inline(always)]
28 unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
29 unsafe { <Self as Allocator>::deallocate(self, ptr, layout) };
30 }
31
32 #[inline(always)]
33 fn allocate_zeroed(&self, layout: Layout) -> Result<NonNull<[u8]>, CrateAllocError> {
34 <Self as Allocator>::allocate_zeroed(self, layout).map_err(Into::into)
35 }
36
37 #[inline(always)]
38 unsafe fn grow(
39 &self,
40 ptr: NonNull<u8>,
41 old_layout: Layout,
42 new_layout: Layout,
43 ) -> Result<NonNull<[u8]>, CrateAllocError> {
44 unsafe { <Self as Allocator>::grow(self, ptr, old_layout, new_layout).map_err(Into::into) }
45 }
46
47 #[inline(always)]
48 unsafe fn grow_zeroed(
49 &self,
50 ptr: NonNull<u8>,
51 old_layout: Layout,
52 new_layout: Layout,
53 ) -> Result<NonNull<[u8]>, CrateAllocError> {
54 unsafe { <Self as Allocator>::grow_zeroed(self, ptr, old_layout, new_layout).map_err(Into::into) }
55 }
56
57 #[inline(always)]
58 unsafe fn shrink(
59 &self,
60 ptr: NonNull<u8>,
61 old_layout: Layout,
62 new_layout: Layout,
63 ) -> Result<NonNull<[u8]>, CrateAllocError> {
64 unsafe { <Self as Allocator>::shrink(self, ptr, old_layout, new_layout).map_err(Into::into) }
65 }
66
67 #[inline(always)]
68 fn by_ref(&self) -> &Self
69 where
70 Self: Sized,
71 {
72 self
73 }
74}
75
76#[repr(transparent)]
109#[derive(Debug, Default, Clone)]
110pub struct AllocatorApi2V03Compat<A: ?Sized>(pub A);
111
112impl<A: ?Sized> AllocatorApi2V03Compat<A> {
113 #[inline(always)]
114 #[allow(missing_docs)]
115 pub fn from_ref(allocator: &A) -> &Self {
116 unsafe { &*(ptr::from_ref(allocator) as *const Self) }
117 }
118
119 #[inline(always)]
120 #[allow(missing_docs)]
121 pub fn from_mut(allocator: &mut A) -> &mut Self {
122 unsafe { &mut *(ptr::from_mut(allocator) as *mut Self) }
123 }
124}
125
126unsafe impl<A: ?Sized + Allocator> CrateAllocator for AllocatorApi2V03Compat<A> {
127 #[inline(always)]
128 fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, CrateAllocError> {
129 <A as Allocator>::allocate(&self.0, layout).map_err(Into::into)
130 }
131
132 #[inline(always)]
133 unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
134 unsafe { <A as Allocator>::deallocate(&self.0, ptr, layout) };
135 }
136
137 #[inline(always)]
138 fn allocate_zeroed(&self, layout: Layout) -> Result<NonNull<[u8]>, CrateAllocError> {
139 <A as Allocator>::allocate_zeroed(&self.0, layout).map_err(Into::into)
140 }
141
142 #[inline(always)]
143 unsafe fn grow(
144 &self,
145 ptr: NonNull<u8>,
146 old_layout: Layout,
147 new_layout: Layout,
148 ) -> Result<NonNull<[u8]>, CrateAllocError> {
149 unsafe { <A as Allocator>::grow(&self.0, ptr, old_layout, new_layout).map_err(Into::into) }
150 }
151
152 #[inline(always)]
153 unsafe fn grow_zeroed(
154 &self,
155 ptr: NonNull<u8>,
156 old_layout: Layout,
157 new_layout: Layout,
158 ) -> Result<NonNull<[u8]>, CrateAllocError> {
159 unsafe { <A as Allocator>::grow_zeroed(&self.0, ptr, old_layout, new_layout).map_err(Into::into) }
160 }
161
162 #[inline(always)]
163 unsafe fn shrink(
164 &self,
165 ptr: NonNull<u8>,
166 old_layout: Layout,
167 new_layout: Layout,
168 ) -> Result<NonNull<[u8]>, CrateAllocError> {
169 unsafe { <A as Allocator>::shrink(&self.0, ptr, old_layout, new_layout).map_err(Into::into) }
170 }
171
172 #[inline(always)]
173 fn by_ref(&self) -> &Self
174 where
175 Self: Sized,
176 {
177 self
178 }
179}
180
181unsafe impl<A: ?Sized + CrateAllocator> Allocator for AllocatorApi2V03Compat<A> {
182 #[inline(always)]
183 fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
184 <A as CrateAllocator>::allocate(&self.0, layout).map_err(Into::into)
185 }
186
187 #[inline(always)]
188 unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
189 unsafe { <A as CrateAllocator>::deallocate(&self.0, ptr, layout) };
190 }
191
192 #[inline(always)]
193 fn allocate_zeroed(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
194 <A as CrateAllocator>::allocate_zeroed(&self.0, layout).map_err(Into::into)
195 }
196
197 #[inline(always)]
198 unsafe fn grow(&self, ptr: NonNull<u8>, old_layout: Layout, new_layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
199 unsafe { <A as CrateAllocator>::grow(&self.0, ptr, old_layout, new_layout).map_err(Into::into) }
200 }
201
202 #[inline(always)]
203 unsafe fn grow_zeroed(
204 &self,
205 ptr: NonNull<u8>,
206 old_layout: Layout,
207 new_layout: Layout,
208 ) -> Result<NonNull<[u8]>, AllocError> {
209 unsafe { <A as CrateAllocator>::grow_zeroed(&self.0, ptr, old_layout, new_layout).map_err(Into::into) }
210 }
211
212 #[inline(always)]
213 unsafe fn shrink(&self, ptr: NonNull<u8>, old_layout: Layout, new_layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
214 unsafe { <A as CrateAllocator>::shrink(&self.0, ptr, old_layout, new_layout).map_err(Into::into) }
215 }
216
217 #[inline(always)]
218 fn by_ref(&self) -> &Self
219 where
220 Self: Sized,
221 {
222 self
223 }
224}
225
226impl From<AllocError> for CrateAllocError {
227 #[inline(always)]
228 fn from(_: AllocError) -> Self {
229 CrateAllocError
230 }
231}
232
233impl From<CrateAllocError> for AllocError {
234 #[inline(always)]
235 fn from(_: CrateAllocError) -> Self {
236 AllocError
237 }
238}
239
240unsafe impl<A, const MIN_ALIGN: usize, const UP: bool, const GUARANTEED_ALLOCATED: bool, const DEALLOCATES: bool> Allocator
241 for BumpScope<'_, A, MIN_ALIGN, UP, GUARANTEED_ALLOCATED, DEALLOCATES>
242where
243 MinimumAlignment<MIN_ALIGN>: SupportedMinimumAlignment,
244 A: BaseAllocator<GUARANTEED_ALLOCATED>,
245{
246 #[inline(always)]
247 fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
248 <Self as CrateAllocator>::allocate(self, layout).map_err(Into::into)
249 }
250
251 #[inline(always)]
252 unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
253 unsafe { <Self as CrateAllocator>::deallocate(self, ptr, layout) };
254 }
255
256 #[inline(always)]
257 unsafe fn grow(&self, ptr: NonNull<u8>, old_layout: Layout, new_layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
258 unsafe { <Self as CrateAllocator>::grow(self, ptr, old_layout, new_layout).map_err(Into::into) }
259 }
260
261 #[inline(always)]
262 unsafe fn grow_zeroed(
263 &self,
264 ptr: NonNull<u8>,
265 old_layout: Layout,
266 new_layout: Layout,
267 ) -> Result<NonNull<[u8]>, AllocError> {
268 unsafe { <Self as CrateAllocator>::grow_zeroed(self, ptr, old_layout, new_layout).map_err(Into::into) }
269 }
270
271 #[inline(always)]
272 unsafe fn shrink(&self, ptr: NonNull<u8>, old_layout: Layout, new_layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
273 unsafe { <Self as CrateAllocator>::shrink(self, ptr, old_layout, new_layout).map_err(Into::into) }
274 }
275}
276
277unsafe impl<A, const MIN_ALIGN: usize, const UP: bool, const GUARANTEED_ALLOCATED: bool, const DEALLOCATES: bool> Allocator
278 for &mut BumpScope<'_, A, MIN_ALIGN, UP, GUARANTEED_ALLOCATED, DEALLOCATES>
279where
280 MinimumAlignment<MIN_ALIGN>: SupportedMinimumAlignment,
281 A: BaseAllocator<GUARANTEED_ALLOCATED>,
282{
283 #[inline(always)]
284 fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
285 <Self as CrateAllocator>::allocate(self, layout).map_err(Into::into)
286 }
287
288 #[inline(always)]
289 unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
290 unsafe { <Self as CrateAllocator>::deallocate(self, ptr, layout) };
291 }
292
293 #[inline(always)]
294 unsafe fn grow(&self, ptr: NonNull<u8>, old_layout: Layout, new_layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
295 unsafe { <Self as CrateAllocator>::grow(self, ptr, old_layout, new_layout).map_err(Into::into) }
296 }
297
298 #[inline(always)]
299 unsafe fn grow_zeroed(
300 &self,
301 ptr: NonNull<u8>,
302 old_layout: Layout,
303 new_layout: Layout,
304 ) -> Result<NonNull<[u8]>, AllocError> {
305 unsafe { <Self as CrateAllocator>::grow_zeroed(self, ptr, old_layout, new_layout).map_err(Into::into) }
306 }
307
308 #[inline(always)]
309 unsafe fn shrink(&self, ptr: NonNull<u8>, old_layout: Layout, new_layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
310 unsafe { <Self as CrateAllocator>::shrink(self, ptr, old_layout, new_layout).map_err(Into::into) }
311 }
312}
313
314unsafe impl<A, const MIN_ALIGN: usize, const UP: bool, const GUARANTEED_ALLOCATED: bool, const DEALLOCATES: bool> Allocator
315 for Bump<A, MIN_ALIGN, UP, GUARANTEED_ALLOCATED, DEALLOCATES>
316where
317 MinimumAlignment<MIN_ALIGN>: SupportedMinimumAlignment,
318 A: BaseAllocator<GUARANTEED_ALLOCATED>,
319{
320 #[inline(always)]
321 fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
322 <Self as CrateAllocator>::allocate(self, layout).map_err(Into::into)
323 }
324
325 #[inline(always)]
326 unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
327 unsafe { <Self as CrateAllocator>::deallocate(self, ptr, layout) };
328 }
329
330 #[inline(always)]
331 unsafe fn grow(&self, ptr: NonNull<u8>, old_layout: Layout, new_layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
332 unsafe { <Self as CrateAllocator>::grow(self, ptr, old_layout, new_layout).map_err(Into::into) }
333 }
334
335 #[inline(always)]
336 unsafe fn grow_zeroed(
337 &self,
338 ptr: NonNull<u8>,
339 old_layout: Layout,
340 new_layout: Layout,
341 ) -> Result<NonNull<[u8]>, AllocError> {
342 unsafe { <Self as CrateAllocator>::grow_zeroed(self, ptr, old_layout, new_layout).map_err(Into::into) }
343 }
344
345 #[inline(always)]
346 unsafe fn shrink(&self, ptr: NonNull<u8>, old_layout: Layout, new_layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
347 unsafe { <Self as CrateAllocator>::shrink(self, ptr, old_layout, new_layout).map_err(Into::into) }
348 }
349}
350
351unsafe impl<A, const MIN_ALIGN: usize, const UP: bool, const GUARANTEED_ALLOCATED: bool, const DEALLOCATES: bool> Allocator
352 for &mut Bump<A, MIN_ALIGN, UP, GUARANTEED_ALLOCATED, DEALLOCATES>
353where
354 MinimumAlignment<MIN_ALIGN>: SupportedMinimumAlignment,
355 A: BaseAllocator<GUARANTEED_ALLOCATED>,
356{
357 #[inline(always)]
358 fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
359 <Self as CrateAllocator>::allocate(self, layout).map_err(Into::into)
360 }
361
362 #[inline(always)]
363 unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
364 unsafe { <Self as CrateAllocator>::deallocate(self, ptr, layout) };
365 }
366
367 #[inline(always)]
368 unsafe fn grow(&self, ptr: NonNull<u8>, old_layout: Layout, new_layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
369 unsafe { <Self as CrateAllocator>::grow(self, ptr, old_layout, new_layout).map_err(Into::into) }
370 }
371
372 #[inline(always)]
373 unsafe fn grow_zeroed(
374 &self,
375 ptr: NonNull<u8>,
376 old_layout: Layout,
377 new_layout: Layout,
378 ) -> Result<NonNull<[u8]>, AllocError> {
379 unsafe { <Self as CrateAllocator>::grow_zeroed(self, ptr, old_layout, new_layout).map_err(Into::into) }
380 }
381
382 #[inline(always)]
383 unsafe fn shrink(&self, ptr: NonNull<u8>, old_layout: Layout, new_layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
384 unsafe { <Self as CrateAllocator>::shrink(self, ptr, old_layout, new_layout).map_err(Into::into) }
385 }
386}
387
388unsafe impl<A: BumpAllocatorExt> Allocator for WithoutShrink<A> {
389 #[inline(always)]
390 fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
391 <Self as CrateAllocator>::allocate(self, layout).map_err(Into::into)
392 }
393
394 #[inline(always)]
395 unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
396 unsafe { <Self as CrateAllocator>::deallocate(self, ptr, layout) };
397 }
398
399 #[inline(always)]
400 unsafe fn grow(&self, ptr: NonNull<u8>, old_layout: Layout, new_layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
401 unsafe { <Self as CrateAllocator>::grow(self, ptr, old_layout, new_layout).map_err(Into::into) }
402 }
403
404 #[inline(always)]
405 unsafe fn grow_zeroed(
406 &self,
407 ptr: NonNull<u8>,
408 old_layout: Layout,
409 new_layout: Layout,
410 ) -> Result<NonNull<[u8]>, AllocError> {
411 unsafe { <Self as CrateAllocator>::grow_zeroed(self, ptr, old_layout, new_layout).map_err(Into::into) }
412 }
413
414 #[inline(always)]
415 unsafe fn shrink(&self, ptr: NonNull<u8>, old_layout: Layout, new_layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
416 unsafe { <Self as CrateAllocator>::shrink(self, ptr, old_layout, new_layout).map_err(Into::into) }
417 }
418}
419
420unsafe impl<A: BumpAllocatorExt> Allocator for WithoutDealloc<A> {
421 #[inline(always)]
422 fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
423 <Self as CrateAllocator>::allocate(self, layout).map_err(Into::into)
424 }
425
426 #[inline(always)]
427 unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
428 unsafe { <Self as CrateAllocator>::deallocate(self, ptr, layout) };
429 }
430
431 #[inline(always)]
432 unsafe fn grow(&self, ptr: NonNull<u8>, old_layout: Layout, new_layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
433 unsafe { <Self as CrateAllocator>::grow(self, ptr, old_layout, new_layout).map_err(Into::into) }
434 }
435
436 #[inline(always)]
437 unsafe fn grow_zeroed(
438 &self,
439 ptr: NonNull<u8>,
440 old_layout: Layout,
441 new_layout: Layout,
442 ) -> Result<NonNull<[u8]>, AllocError> {
443 unsafe { <Self as CrateAllocator>::grow_zeroed(self, ptr, old_layout, new_layout).map_err(Into::into) }
444 }
445
446 #[inline(always)]
447 unsafe fn shrink(&self, ptr: NonNull<u8>, old_layout: Layout, new_layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
448 unsafe { <Self as CrateAllocator>::shrink(self, ptr, old_layout, new_layout).map_err(Into::into) }
449 }
450}
451
452#[cfg(feature = "alloc")]
453impl<T: ?Sized, A: Allocator> box_like::Sealed for Box<T, A> {
454 type T = T;
455 type A = A;
456
457 #[inline(always)]
458 unsafe fn from_raw_in(ptr: *mut Self::T, allocator: Self::A) -> Self {
459 unsafe { Box::from_raw_in(ptr, allocator) }
460 }
461}
462
463#[cfg(feature = "alloc")]
464impl<T: ?Sized, A: Allocator> BoxLike for Box<T, A> {}
465
466#[test]
467fn test_compat() {
468 fn is_base_allocator<T: BaseAllocator>(_: T) {}
469
470 #[derive(Clone)]
471 struct TestAllocator;
472
473 unsafe impl Allocator for TestAllocator {
474 fn allocate(&self, _: Layout) -> Result<NonNull<[u8]>, AllocError> {
475 unimplemented!()
476 }
477
478 unsafe fn deallocate(&self, _: NonNull<u8>, _: Layout) {
479 unimplemented!()
480 }
481 }
482
483 #[cfg(feature = "alloc")]
484 is_base_allocator(Global);
485 is_base_allocator(AllocatorApi2V03Compat(TestAllocator));
486 is_base_allocator(AllocatorApi2V03Compat::from_ref(&TestAllocator));
487}