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