use crate::*;
use crate::error::ExcessiveAlignmentRequestedError;
use crate::meta::*;
use core::alloc::Layout;
use core::mem::MaybeUninit;
use core::ptr::NonNull;
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] #[repr(transparent)] pub struct AllocZst<A>(pub A);
impl<A> core::ops::Deref for AllocZst<A> { fn deref(&self) -> &Self::Target { &self.0 } type Target = A; }
impl<A: Meta> AllocZst<A> {
fn fix_thin_size(size: usize) -> usize {
if A::ZST_SUPPORTED { size }
else { size.max(1) }
}
fn fix_layout(layout: Layout) -> Result<Layout, A::Error> {
if A::ZST_SUPPORTED || layout.size() != 0 {
Ok(layout)
} else {
const ALIGN_HALF_MAX : Alignment = Alignment::constant(Alignment::MAX.as_usize()/2);
Layout::from_size_align(1, layout.align()).map_err(|_| ExcessiveAlignmentRequestedError {
requested: Alignment::from(layout),
supported: ALIGN_HALF_MAX, }.into())
}
}
}
impl<A: Meta> Meta for AllocZst<A> {
type Error = A::Error;
const MAX_ALIGN : Alignment = A::MAX_ALIGN;
const MAX_SIZE : usize = A::MAX_SIZE;
const ZST_SUPPORTED : bool = true;
}
impl<A: Meta> ZstSupported for AllocZst<A> {}
unsafe impl<A: Stateless> Stateless for AllocZst<A> {}
#[allow(clippy::undocumented_unsafe_blocks)] unsafe impl<A: thin::Alloc> thin::Alloc for AllocZst<A> {
fn alloc_uninit(&self, size: usize) -> Result<NonNull<MaybeUninit<u8>>, Self::Error> {
let size = Self::fix_thin_size(size);
self.0.alloc_uninit(size)
}
fn alloc_zeroed(&self, size: usize) -> Result<AllocNN0, Self::Error> {
let size = Self::fix_thin_size(size);
self.0.alloc_zeroed(size)
}
}
#[allow(clippy::undocumented_unsafe_blocks)] unsafe impl<A: thin::Free> thin::Free for AllocZst<A> {
unsafe fn free(&self, ptr: NonNull<MaybeUninit<u8>>) { unsafe { self.0.free(ptr) } }
unsafe fn free_nullable(&self, ptr: *mut MaybeUninit<u8>) { unsafe { self.0.free_nullable(ptr) } }
}
#[allow(clippy::undocumented_unsafe_blocks)] unsafe impl<A: thin::Realloc> thin::Realloc for AllocZst<A> {
const CAN_REALLOC_ZEROED : bool = A::CAN_REALLOC_ZEROED;
unsafe fn realloc_uninit(&self, ptr: NonNull<MaybeUninit<u8>>, new_size: usize) -> Result<NonNull<MaybeUninit<u8>>, Self::Error> {
let new_size = Self::fix_thin_size(new_size);
unsafe { self.0.realloc_uninit(ptr, new_size) }
}
unsafe fn realloc_zeroed(&self, ptr: NonNull<MaybeUninit<u8>>, new_size: usize) -> Result<NonNull<MaybeUninit<u8>>, Self::Error> {
let new_size = Self::fix_thin_size(new_size);
unsafe { self.0.realloc_zeroed(ptr, new_size) }
}
}
unsafe impl<A: thin::SizeOf> thin::SizeOf for AllocZst<A> {
unsafe fn size_of(&self, ptr: NonNull<MaybeUninit<u8>>) -> usize {
unsafe { self.0.size_of(ptr) }
}
}
unsafe impl<A: thin::SizeOfDebug> thin::SizeOfDebug for AllocZst<A> {
unsafe fn size_of_debug(&self, ptr: NonNull<MaybeUninit<u8>>) -> Option<usize> {
unsafe { self.0.size_of_debug(ptr) }
}
}
#[allow(clippy::undocumented_unsafe_blocks)] unsafe impl<A: fat::Alloc> fat::Alloc for AllocZst<A> {
fn alloc_uninit(&self, layout: Layout) -> Result<NonNull<MaybeUninit<u8>>, Self::Error> {
let layout = Self::fix_layout(layout)?;
self.0.alloc_uninit(layout)
}
fn alloc_zeroed(&self, layout: Layout) -> Result<NonNull<u8>, Self::Error> {
let layout = Self::fix_layout(layout)?;
self.0.alloc_zeroed(layout)
}
}
#[allow(clippy::undocumented_unsafe_blocks)] unsafe impl<A: fat::Free> fat::Free for AllocZst<A> {
unsafe fn free(&self, ptr: NonNull<MaybeUninit<u8>>, layout: Layout) {
let layout = Self::fix_layout(layout).expect("bug: undefined behavior: invalid old_layout");
unsafe { self.0.free(ptr, layout) }
}
}
#[allow(clippy::undocumented_unsafe_blocks)] unsafe impl<A: fat::Realloc> fat::Realloc for AllocZst<A> {
unsafe fn realloc_uninit(&self, ptr: NonNull<MaybeUninit<u8>>, old_layout: Layout, new_layout: Layout) -> Result<NonNull<MaybeUninit<u8>>, Self::Error> {
let old_layout = Self::fix_layout(old_layout).expect("bug: undefined behavior: invalid old_layout");
let new_layout = Self::fix_layout(new_layout)?;
unsafe { self.0.realloc_uninit(ptr, old_layout, new_layout) }
}
unsafe fn realloc_zeroed(&self, ptr: NonNull<MaybeUninit<u8>>, old_layout: Layout, new_layout: Layout) -> Result<NonNull<MaybeUninit<u8>>, Self::Error> {
let old_layout = Self::fix_layout(old_layout).expect("bug: undefined behavior: invalid old_layout");
let new_layout = Self::fix_layout(new_layout)?;
unsafe { self.0.realloc_zeroed(ptr, old_layout, new_layout) }
}
}
#[no_implicit_prelude] mod cleanroom {
#[allow(unused_imports)] use super::{impls, fat, AllocZst};
impls! {
unsafe impl[A: ::core::alloc::GlobalAlloc ] core::alloc::GlobalAlloc for AllocZst<A> => core::ops::Deref;
}
#[cfg(allocator_api = "1.50")] impls! {
unsafe impl[A: fat::Realloc ] core::alloc::Allocator(unstable 1.50) for AllocZst<A> => ialloc::fat::Realloc;
}
}