1#![allow(unknown_lints)]
48#![warn(clippy::all, clippy::pedantic, clippy::nursery, clippy::multiple_unsafe_ops_per_block)]
49#![allow(
50 clippy::inline_always,
51 clippy::borrow_as_ptr,
52 clippy::module_name_repetitions,
53 clippy::use_self,
54 clippy::question_mark,
55 unused_unsafe
56)]
57#![deny(missing_docs, clippy::undocumented_unsafe_blocks)]
58#![warn(unknown_lints)]
59#![cfg_attr(feature = "dev", warn(rustdoc::broken_intra_doc_links))]
60#![cfg_attr(not(feature = "std"), no_std)]
61#![cfg_attr(nightly, feature(allocator_api))]
63#![cfg_attr(feature = "metadata", feature(ptr_metadata))]
64#![cfg_attr(feature = "sized_hierarchy", feature(sized_hierarchy))]
65
66#[cfg(not(feature = "no_alloc"))] extern crate alloc;
73extern crate core;
74
75macro_rules! tri {
77 (::$err:ident $($fallible:expr)+) => {
78 match $($fallible)+ {
79 Ok(x) => x,
80 Err(e) => return Err(Error::$err(e)),
81 }
82 };
83 (opt $($fallible:expr)+) => {
84 match $($fallible)+ {
85 Some(x) => x,
86 None => return None,
87 }
88 };
89 (do $($fallible:expr)+) => {
90 match $($fallible)+ {
91 Ok(s) => s,
92 Err(e) => return Err(e),
93 }
94 };
95 (cmap($err:expr) from $e:ty, $($fallible:expr)+) => {
96 match $($fallible)+ {
97 Ok(s) => s,
98 Err(_) => return Err(<$e>::from($err)),
99 }
100 };
101}
102
103macro_rules! zalloc {
104 ($self:ident, $alloc:ident, $layout:ident) => {{
105 let res = $self.$alloc($layout);
106 if let Ok(p) = res {
107 unsafe {
109 ptr::write_bytes(p.as_ptr(), 0, $layout.size());
110 }
111 }
112 res
113 }};
114}
115
116pub mod traits;
118pub use traits::*;
119
120pub mod helpers;
122
123pub mod error;
125
126mod layout;
127pub use layout::Layout;
128
129mod ffi;
130
131mod allocs;
132#[allow(unused_imports)] pub use allocs::*;
133
134#[cfg(not(feature = "no_alloc"))]
135pub type StdLayout = alloc::alloc::Layout;
137
138#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
146pub struct DefaultAlloc;
147
148macro_rules! default_alloc_impl {
149 ($ty:ty) => {
150 #[cfg(not(feature = "no_alloc"))]
151 impl crate::Alloc for $ty {
152 type Error = crate::error::Error;
153
154 #[cfg_attr(miri, track_caller)]
155 #[inline(always)]
156 fn alloc(&self, layout: Layout) -> Result<core::ptr::NonNull<u8>, crate::error::Error> {
157 crate::helpers::null_q_dyn_zsl_check(
158 layout,
159 |layout| unsafe { alloc::alloc::alloc(layout.to_stdlib()) }
161 )
162 }
163
164 #[cfg_attr(miri, track_caller)]
165 #[inline(always)]
166 fn zalloc(
167 &self,
168 layout: Layout
169 ) -> Result<core::ptr::NonNull<u8>, crate::error::Error> {
170 crate::helpers::null_q_dyn_zsl_check(
171 layout,
172 |layout| unsafe { alloc::alloc::alloc_zeroed(layout.to_stdlib()) }
174 )
175 }
176 }
177 #[cfg(not(feature = "no_alloc"))]
178 impl crate::Dealloc for $ty {
179 #[cfg_attr(miri, track_caller)]
180 #[inline(always)]
181 unsafe fn dealloc(&self, ptr: core::ptr::NonNull<u8>, layout: Layout) {
182 if layout.is_nonzero_sized() && ptr != layout.dangling() {
183 alloc::alloc::dealloc(ptr.as_ptr(), layout.to_stdlib());
184 }
185 }
186
187 #[cfg_attr(miri, track_caller)]
188 #[inline(always)]
189 unsafe fn try_dealloc(
190 &self,
191 ptr: core::ptr::NonNull<u8>,
192 layout: Layout
193 ) -> Result<(), crate::error::Error> {
194 if layout.is_zero_sized() {
195 Err(crate::error::Error::ZeroSizedLayout)
196 } else if ptr == layout.dangling() {
197 Err(crate::error::Error::DanglingDeallocation)
198 } else {
199 alloc::alloc::dealloc(ptr.as_ptr(), layout.to_stdlib());
200 Ok(())
201 }
202 }
203 }
204 #[cfg(not(feature = "no_alloc"))]
205 impl crate::Grow for $ty {}
206 #[cfg(not(feature = "no_alloc"))]
207 impl crate::Shrink for $ty {}
208 #[cfg(not(feature = "no_alloc"))]
209 impl crate::Realloc for $ty {}
210 };
211}
212
213#[cfg(not(feature = "no_alloc"))]
214unsafe impl alloc::alloc::GlobalAlloc for DefaultAlloc {
216 #[cfg_attr(miri, track_caller)]
217 #[inline]
218 unsafe fn alloc(&self, layout: StdLayout) -> *mut u8 {
219 alloc::alloc::alloc(layout)
220 }
221
222 #[cfg_attr(miri, track_caller)]
223 #[inline]
224 unsafe fn dealloc(&self, ptr: *mut u8, layout: StdLayout) {
225 alloc::alloc::dealloc(ptr, layout);
226 }
227
228 #[cfg_attr(miri, track_caller)]
229 #[inline]
230 unsafe fn alloc_zeroed(&self, layout: StdLayout) -> *mut u8 {
231 alloc::alloc::alloc_zeroed(layout)
232 }
233
234 #[cfg_attr(miri, track_caller)]
235 #[inline]
236 unsafe fn realloc(&self, ptr: *mut u8, layout: StdLayout, new_size: usize) -> *mut u8 {
237 alloc::alloc::realloc(ptr, layout, new_size)
238 }
239}
240
241default_alloc_impl!(DefaultAlloc);
242
243#[cfg(all(nightly, not(feature = "no_alloc")))]
244pub(crate) mod nightly {
246 use {
247 crate::{Layout, StdLayout},
248 alloc::alloc::{AllocError, Allocator, Global},
249 core::ptr::NonNull
250 };
251
252 unsafe impl Allocator for crate::DefaultAlloc {
256 #[cfg_attr(miri, track_caller)]
257 #[inline]
258 fn allocate(&self, layout: StdLayout) -> Result<NonNull<[u8]>, AllocError> {
259 Allocator::allocate(&Global, layout)
260 }
261
262 #[cfg_attr(miri, track_caller)]
263 #[inline]
264 fn allocate_zeroed(&self, layout: StdLayout) -> Result<NonNull<[u8]>, AllocError> {
265 Allocator::allocate_zeroed(&Global, layout)
266 }
267
268 #[cfg_attr(miri, track_caller)]
269 #[inline]
270 unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: StdLayout) {
271 Allocator::deallocate(&Global, ptr.cast(), layout);
272 }
273
274 #[cfg_attr(miri, track_caller)]
275 #[inline]
276 unsafe fn grow(
277 &self,
278 ptr: NonNull<u8>,
279 old_layout: StdLayout,
280 new_layout: StdLayout
281 ) -> Result<NonNull<[u8]>, AllocError> {
282 Allocator::grow(&Global, ptr.cast(), old_layout, new_layout)
283 }
284
285 #[cfg_attr(miri, track_caller)]
286 #[inline]
287 unsafe fn grow_zeroed(
288 &self,
289 ptr: NonNull<u8>,
290 old_layout: StdLayout,
291 new_layout: StdLayout
292 ) -> Result<NonNull<[u8]>, AllocError> {
293 Allocator::grow_zeroed(&Global, ptr.cast(), old_layout, new_layout)
294 }
295
296 #[cfg_attr(miri, track_caller)]
297 #[inline]
298 unsafe fn shrink(
299 &self,
300 ptr: NonNull<u8>,
301 old_layout: StdLayout,
302 new_layout: StdLayout
303 ) -> Result<NonNull<[u8]>, AllocError> {
304 Allocator::shrink(&Global, ptr.cast(), old_layout, new_layout)
305 }
306 }
307
308 default_alloc_impl!(Global);
309
310 }