ialloc/allocator/alloc/
global.rs1use crate::*;
2use crate::meta::*;
3
4use core::alloc::Layout;
5use core::mem::MaybeUninit;
6use core::ptr::NonNull;
7
8
9
10#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] #[repr(transparent)] pub struct Global;
16
17#[cfg(feature = "alloc")] #[cfg(allocator_api = "*")] impl From<Global> for alloc::alloc::Global { fn from(_: Global) -> Self { Self } }
18#[cfg(feature = "alloc")] #[cfg(allocator_api = "*")] impl From<alloc::alloc::Global> for Global { fn from(_: alloc::alloc::Global) -> Self { Self } }
19
20
21
22impl Meta for Global {
25 type Error = ();
26 const MAX_ALIGN : Alignment = Alignment::MAX;
27 const MAX_SIZE : usize = usize::MAX/2;
28 const ZST_SUPPORTED : bool = true;
29}
30
31impl ZstSupported for Global {}
32
33unsafe impl ZstInfalliable for Global {}
35
36unsafe impl Stateless for Global {}
38
39
40
41unsafe impl fat::Alloc for Global {
45 fn alloc_uninit(&self, layout: Layout) -> Result<AllocNN, Self::Error> {
46 match layout.size() {
47 0 => Ok(util::nn::dangling(layout)),
48 n if n > Self::MAX_SIZE => Err(()),
49 _ => {
50 debug_assert!(layout.pad_to_align().size() <= Self::MAX_SIZE, "bug: undefined behavior: Layout when padded to alignment exceeds isize::MAX, which violates Layout's invariants");
51 let alloc = unsafe { alloc::alloc::alloc(layout) };
53 NonNull::new(alloc.cast()).ok_or(())
54 }
55 }
56 }
57
58 fn alloc_zeroed(&self, layout: Layout) -> Result<AllocNN0, Self::Error> {
59 match layout.size() {
60 0 => Ok(util::nn::dangling(layout)),
61 n if n > Self::MAX_SIZE => Err(()),
62 _ => {
63 debug_assert!(layout.pad_to_align().size() <= Self::MAX_SIZE, "bug: undefined behavior: Layout when padded to alignment exceeds isize::MAX, which violates Layout's invariants");
64 let alloc = unsafe { alloc::alloc::alloc_zeroed(layout) };
66 NonNull::new(alloc.cast()).ok_or(())
67 }
68 }
69 }
70}
71
72unsafe impl fat::Free for Global {
74 unsafe fn free(&self, ptr: AllocNN, layout: Layout) {
75 if layout.size() == 0 { return }
76 unsafe { alloc::alloc::dealloc(ptr.as_ptr().cast(), layout) }
78 }
79}
80
81unsafe impl fat::Realloc for Global {
83 unsafe fn realloc_uninit(&self, ptr: AllocNN, old_layout: Layout, new_layout: Layout) -> Result<AllocNN, Self::Error> {
84 if new_layout.size() > Self::MAX_SIZE {
85 Err(())
86 } else if old_layout == new_layout {
87 Ok(ptr)
88 } else if old_layout.align() != new_layout.align() || old_layout.size() == 0 || new_layout.size() == 0 {
89 let alloc = fat::Alloc::alloc_uninit(self, new_layout)?;
90 {
91 #![allow(clippy::undocumented_unsafe_blocks)]
94
95 let old : & [MaybeUninit<u8>] = unsafe { util::slice::from_raw_bytes_layout (ptr, old_layout) };
96 let new : &mut [MaybeUninit<u8>] = unsafe { util::slice::from_raw_bytes_layout_mut(alloc, new_layout) };
97 let n = old.len().min(new.len());
98 new[..n].copy_from_slice(&old[..n]);
99 }
100 unsafe { fat::Free::free(self, ptr, old_layout) };
102 Ok(alloc)
103 } else {
104 let alloc = unsafe { alloc::alloc::realloc(ptr.as_ptr().cast(), old_layout, new_layout.size()) };
110 NonNull::new(alloc.cast()).ok_or(())
111 }
112 }
113
114 }
116
117
118
119#[allow(clippy::undocumented_unsafe_blocks)] unsafe impl core::alloc::GlobalAlloc for Global {
123 unsafe fn alloc(&self, layout: Layout) -> *mut u8 { unsafe { alloc::alloc::alloc(layout) } }
124 unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 { unsafe { alloc::alloc::alloc_zeroed(layout) } }
125 unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { unsafe { alloc::alloc::dealloc(ptr, layout) } }
126 unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 { unsafe { alloc::alloc::realloc(ptr, layout, new_size) } }
127}
128
129#[cfg(allocator_api = "1.50")] unsafe impl core::alloc::Allocator for Global {
168 fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, core::alloc::AllocError> {
169 let data = fat::Alloc::alloc_uninit(self, layout).map_err(|_| core::alloc::AllocError)?;
170 Ok(util::nn::slice_from_raw_parts(data.cast(), layout.size()))
171 }
172
173 fn allocate_zeroed(&self, layout: Layout) -> Result<NonNull<[u8]>, core::alloc::AllocError> {
174 let data = fat::Alloc::alloc_zeroed(self, layout).map_err(|_| core::alloc::AllocError)?;
175 Ok(util::nn::slice_from_raw_parts(data.cast(), layout.size()))
176 }
177
178 unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
179 unsafe { fat::Free::free(self, ptr.cast(), layout) }
180 }
181
182 unsafe fn grow(&self, ptr: NonNull<u8>, old_layout: Layout, new_layout: Layout) -> Result<NonNull<[u8]>, core::alloc::AllocError> {
183 let data = unsafe { fat::Realloc::realloc_uninit(self, ptr.cast(), old_layout, new_layout) }.map_err(|_| core::alloc::AllocError)?;
184 Ok(util::nn::slice_from_raw_parts(data.cast(), new_layout.size()))
185 }
186
187 unsafe fn grow_zeroed(&self, ptr: NonNull<u8>, old_layout: Layout, new_layout: Layout) -> Result<NonNull<[u8]>, core::alloc::AllocError> {
188 let data = unsafe { fat::Realloc::realloc_zeroed(self, ptr.cast(), old_layout, new_layout) }.map_err(|_| core::alloc::AllocError)?;
189 Ok(util::nn::slice_from_raw_parts(data.cast(), new_layout.size()))
190 }
191
192 unsafe fn shrink(&self, ptr: NonNull<u8>, old_layout: Layout, new_layout: Layout) -> Result<NonNull<[u8]>, core::alloc::AllocError> {
193 let data = unsafe { fat::Realloc::realloc_uninit(self, ptr.cast(), old_layout, new_layout) }.map_err(|_| core::alloc::AllocError)?;
194 Ok(util::nn::slice_from_raw_parts(data.cast(), new_layout.size()))
195 }
196}
197
198
199
200#[test] fn fat_alignment() { fat::test::alignment(Global) }
201#[test] fn fat_edge_case_sizes() { fat::test::edge_case_sizes(Global) }
202#[test] fn fat_uninit() { if !cfg!(target_os = "linux") { unsafe { fat::test::uninit_alloc_unsound(Global) } } }
203#[test] fn fat_zeroed() { fat::test::zeroed_alloc(Global) }
204#[test] fn fat_zst_support() { fat::test::zst_supported_accurate(Global) }