1#![no_std]
2#![feature(allocator_api)]
3#![feature(alloc_layout_extra)]
4#![warn(rust_2018_idioms)]
5
6#[cfg(feature = "alloc")]
7extern crate alloc;
8use core::{
9 alloc::{AllocError, Allocator, Layout},
10 marker::PhantomData,
11 ptr::NonNull,
12};
13
14#[repr(transparent)]
39pub struct NoopAllocator<'a>(PhantomData<&'a ()>);
40
41impl<'a> NoopAllocator<'a> {
42 pub const fn new() -> Self {
44 Self(PhantomData)
45 }
46}
47
48impl<'a> Default for NoopAllocator<'a> {
49 fn default() -> Self {
50 Self::new()
51 }
52}
53
54unsafe impl Allocator for NoopAllocator<'_> {
55 fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
56 if layout.size() == 0 {
57 Ok(NonNull::slice_from_raw_parts(layout.dangling(), 0))
58 } else {
59 Err(AllocError)
60 }
61 }
62
63 unsafe fn deallocate(&self, _ptr: NonNull<u8>, _layout: Layout) {
64 }
66
67 unsafe fn grow(
68 &self,
69 ptr: NonNull<u8>,
70 old_layout: Layout,
71 new_layout: Layout,
72 ) -> Result<NonNull<[u8]>, AllocError> {
73 self.grow_zeroed(ptr, old_layout, new_layout)
74 }
75
76 unsafe fn grow_zeroed(
77 &self,
78 ptr: NonNull<u8>,
79 old_layout: Layout,
80 new_layout: Layout,
81 ) -> Result<NonNull<[u8]>, AllocError> {
82 debug_assert!(
83 new_layout.size() >= old_layout.size(),
84 "`new_layout.size()` must be greater than or equal to `old_layout.size()`"
85 );
86 if new_layout.size() > old_layout.size()
87 || (ptr.as_ptr() as usize & (new_layout.align() - 1) != 0)
88 {
89 return Err(AllocError);
90 }
91
92 let new_ptr = NonNull::slice_from_raw_parts(ptr, new_layout.size());
93
94 Ok(new_ptr)
95 }
96
97 unsafe fn shrink(
98 &self,
99 ptr: NonNull<u8>,
100 old_layout: Layout,
101 new_layout: Layout,
102 ) -> Result<NonNull<[u8]>, AllocError> {
103 debug_assert!(
104 new_layout.size() <= old_layout.size(),
105 "`new_layout.size()` must be smaller than or equal to `old_layout.size()`"
106 );
107
108 if new_layout.size() > old_layout.size()
109 || (ptr.as_ptr() as usize & (new_layout.align() - 1) != 0)
110 {
111 return Err(AllocError);
112 }
113
114 let new_ptr = NonNull::slice_from_raw_parts(ptr, new_layout.size());
115
116 Ok(new_ptr)
117 }
118}
119
120#[cfg(feature = "alloc")]
121pub mod owning_ref;
122#[cfg(feature = "alloc")]
123pub mod owning_slice;