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