use {
crate::{
error::Error,
layout::Layout,
traits::{
AllocError,
alloc::{Alloc, Dealloc, Grow, Realloc, Shrink},
helpers::{
Bytes,
alloc_mut::{grow_mut, ralloc_mut, shrink_unchecked_mut},
default_dealloc_panic
}
}
},
::core::{
cmp::{Ord, Ordering},
convert::From,
marker::Sized,
ptr::{self, NonNull},
result::Result::{self, Err, Ok}
}
};
pub trait AllocMut: AllocError {
fn alloc_mut(&mut self, layout: Layout) -> Result<NonNull<u8>, <Self as AllocError>::Error>;
#[cfg_attr(miri, track_caller)]
#[inline]
fn zalloc_mut(&mut self, layout: Layout) -> Result<NonNull<u8>, <Self as AllocError>::Error> {
zalloc!(self, alloc_mut, layout)
}
}
pub trait DeallocMut: AllocMut {
#[track_caller]
#[inline]
unsafe fn dealloc_mut(&mut self, ptr: NonNull<u8>, layout: Layout) {
default_dealloc!(self.try_dealloc_mut, ptr, layout);
}
unsafe fn try_dealloc_mut(
&mut self,
ptr: NonNull<u8>,
layout: Layout
) -> Result<(), <Self as AllocError>::Error>;
fn checked_dealloc_mut(
&mut self,
_ptr: NonNull<u8>,
_layout: Layout
) -> Result<(), <Self as AllocError>::Error> {
Err(<Self as AllocError>::Error::from(Error::Unsupported))
}
}
pub trait GrowMut: AllocMut + DeallocMut {
#[cfg_attr(miri, track_caller)]
#[inline]
unsafe fn grow_mut(
&mut self,
ptr: NonNull<u8>,
old_layout: Layout,
new_layout: Layout
) -> Result<NonNull<u8>, <Self as AllocError>::Error> {
grow_mut(self, ptr, old_layout, new_layout, Bytes::Uninitialized)
}
#[cfg_attr(miri, track_caller)]
#[inline]
unsafe fn zgrow_mut(
&mut self,
ptr: NonNull<u8>,
old_layout: Layout,
new_layout: Layout
) -> Result<NonNull<u8>, <Self as AllocError>::Error> {
grow_mut(self, ptr, old_layout, new_layout, Bytes::Zeroed)
}
}
pub trait ShrinkMut: AllocMut + DeallocMut {
#[cfg_attr(miri, track_caller)]
unsafe fn shrink_mut(
&mut self,
ptr: NonNull<u8>,
old_layout: Layout,
new_layout: Layout
) -> Result<NonNull<u8>, <Self as AllocError>::Error> {
default_shrink!(self::shrink_unchecked_mut, ptr, old_layout, new_layout)
}
}
pub trait ReallocMut: GrowMut + ShrinkMut {
#[cfg_attr(miri, track_caller)]
#[inline]
unsafe fn realloc_mut(
&mut self,
ptr: NonNull<u8>,
old_layout: Layout,
new_layout: Layout
) -> Result<NonNull<u8>, <Self as AllocError>::Error> {
ralloc_mut(self, ptr, old_layout, new_layout, Bytes::Uninitialized)
}
#[cfg_attr(miri, track_caller)]
#[inline]
unsafe fn rezalloc_mut(
&mut self,
ptr: NonNull<u8>,
old_layout: Layout,
new_layout: Layout
) -> Result<NonNull<u8>, <Self as AllocError>::Error> {
ralloc_mut(self, ptr, old_layout, new_layout, Bytes::Zeroed)
}
}
pub trait BasicAllocMut: AllocMut + DeallocMut {}
pub trait FullAllocMut: ReallocMut + GrowMut + ShrinkMut + AllocMut + DeallocMut {}
impl<A: AllocMut + DeallocMut> BasicAllocMut for A {}
impl<A: ReallocMut + GrowMut + ShrinkMut + AllocMut + DeallocMut> FullAllocMut for A {}
impl<A: Alloc + ?Sized> AllocMut for A {
#[cfg_attr(miri, track_caller)]
#[inline(always)]
fn alloc_mut(&mut self, layout: Layout) -> Result<NonNull<u8>, <A as AllocError>::Error> {
(*self).alloc(layout)
}
#[cfg_attr(miri, track_caller)]
#[inline(always)]
fn zalloc_mut(&mut self, layout: Layout) -> Result<NonNull<u8>, <A as AllocError>::Error> {
(*self).zalloc(layout)
}
}
impl<A: Dealloc + ?Sized> DeallocMut for A {
#[cfg_attr(miri, track_caller)]
#[inline(always)]
unsafe fn dealloc_mut(&mut self, ptr: NonNull<u8>, layout: Layout) {
(*self).dealloc(ptr, layout);
}
#[cfg_attr(miri, track_caller)]
#[inline(always)]
unsafe fn try_dealloc_mut(
&mut self,
ptr: NonNull<u8>,
layout: Layout
) -> Result<(), <A as AllocError>::Error> {
(*self).try_dealloc(ptr, layout)
}
}
impl<A: Grow + ?Sized> GrowMut for A {
#[cfg_attr(miri, track_caller)]
#[inline(always)]
unsafe fn grow_mut(
&mut self,
ptr: NonNull<u8>,
old_layout: Layout,
new_layout: Layout
) -> Result<NonNull<u8>, <A as AllocError>::Error> {
(*self).grow(ptr, old_layout, new_layout)
}
#[cfg_attr(miri, track_caller)]
#[inline(always)]
unsafe fn zgrow_mut(
&mut self,
ptr: NonNull<u8>,
old_layout: Layout,
new_layout: Layout
) -> Result<NonNull<u8>, <A as AllocError>::Error> {
(*self).zgrow(ptr, old_layout, new_layout)
}
}
impl<A: Shrink + ?Sized> ShrinkMut for A {
#[cfg_attr(miri, track_caller)]
#[inline(always)]
unsafe fn shrink_mut(
&mut self,
ptr: NonNull<u8>,
old_layout: Layout,
new_layout: Layout
) -> Result<NonNull<u8>, <A as AllocError>::Error> {
(*self).shrink(ptr, old_layout, new_layout)
}
}
impl<A: Realloc + ?Sized> ReallocMut for A {
#[cfg_attr(miri, track_caller)]
#[inline(always)]
unsafe fn realloc_mut(
&mut self,
ptr: NonNull<u8>,
old_layout: Layout,
new_layout: Layout
) -> Result<NonNull<u8>, <A as AllocError>::Error> {
(*self).realloc(ptr, old_layout, new_layout)
}
#[cfg_attr(miri, track_caller)]
#[inline(always)]
unsafe fn rezalloc_mut(
&mut self,
ptr: NonNull<u8>,
old_layout: Layout,
new_layout: Layout
) -> Result<NonNull<u8>, <A as AllocError>::Error> {
(*self).rezalloc(ptr, old_layout, new_layout)
}
}
const LOCK_ERR: Error = Error::Other("lock_failed");
macro_rules! impl_alloc_for_sync_mutalloc {
($t:ty, $borrow_call:ident) => {
impl<A: AllocError + ?Sized> AllocError for $t {
type Error = A::Error;
}
impl<A: AllocMut + ?Sized> Alloc for $t {
#[cfg_attr(miri, track_caller)]
fn alloc(
&self,
layout: Layout
) -> Result<NonNull<u8>, <$t as AllocError>::Error> {
tri!(cmap(LOCK_ERR) from <Self as AllocError>::Error, self.$borrow_call())
.alloc_mut(layout)
}
#[cfg_attr(miri, track_caller)]
fn zalloc(
&self,
layout: Layout
) -> Result<NonNull<u8>, <$t as AllocError>::Error> {
tri!(cmap(LOCK_ERR) from <Self as AllocError>::Error, self.$borrow_call())
.zalloc_mut(layout)
}
}
impl<A: DeallocMut + ?Sized> Dealloc for $t {
#[track_caller]
unsafe fn dealloc(&self, ptr: NonNull<u8>, layout: Layout) {
match self.$borrow_call() {
Ok(mut guard) => guard.dealloc_mut(ptr, layout),
Err(_) => default_dealloc_panic(ptr, layout, LOCK_ERR),
}
}
#[cfg_attr(miri, track_caller)]
unsafe fn try_dealloc(
&self,
ptr: NonNull<u8>,
layout: Layout
) -> Result<(), <$t as AllocError>::Error> {
tri!(cmap(LOCK_ERR) from <Self as AllocError>::Error, self.$borrow_call())
.try_dealloc_mut(ptr, layout)
}
}
impl<A: GrowMut + ?Sized> Grow for $t {
#[cfg_attr(miri, track_caller)]
unsafe fn grow(
&self,
ptr: NonNull<u8>,
old_layout: Layout,
new_layout: Layout,
) -> Result<NonNull<u8>, <$t as AllocError>::Error> {
tri!(cmap(LOCK_ERR) from <Self as AllocError>::Error, self.$borrow_call())
.grow_mut(ptr, old_layout, new_layout)
}
#[cfg_attr(miri, track_caller)]
unsafe fn zgrow(
&self,
ptr: NonNull<u8>,
old_layout: Layout,
new_layout: Layout,
) -> Result<NonNull<u8>, <$t as AllocError>::Error> {
tri!(cmap(LOCK_ERR) from <Self as AllocError>::Error, self.$borrow_call())
.zgrow_mut(ptr, old_layout, new_layout)
}
}
impl<A: ShrinkMut + ?Sized> Shrink for $t {
#[cfg_attr(miri, track_caller)]
unsafe fn shrink(
&self,
ptr: NonNull<u8>,
old_layout: Layout,
new_layout: Layout,
) -> Result<NonNull<u8>, <$t as AllocError>::Error> {
tri!(cmap(LOCK_ERR) from <Self as AllocError>::Error, self.$borrow_call())
.shrink_mut(ptr, old_layout, new_layout)
}
}
impl<A: ReallocMut + ?Sized> Realloc for $t {
#[cfg_attr(miri, track_caller)]
unsafe fn realloc(
&self,
ptr: NonNull<u8>,
old_layout: Layout,
new_layout: Layout,
) -> Result<NonNull<u8>, <$t as AllocError>::Error> {
tri!(cmap(LOCK_ERR) from <Self as AllocError>::Error, self.$borrow_call())
.realloc_mut(ptr, old_layout, new_layout)
}
#[cfg_attr(miri, track_caller)]
unsafe fn rezalloc(
&self,
ptr: NonNull<u8>,
old_layout: Layout,
new_layout: Layout,
) -> Result<NonNull<u8>, <$t as AllocError>::Error> {
tri!(cmap(LOCK_ERR) from <Self as AllocError>::Error, self.$borrow_call())
.rezalloc_mut(ptr, old_layout, new_layout)
}
}
};
}
#[cfg(feature = "std")]
impl_alloc_for_sync_mutalloc! {
::std::sync::Mutex<A>, lock
}
#[cfg(feature = "std")]
impl_alloc_for_sync_mutalloc! {
::std::sync::RwLock<A>, write
}
impl_alloc_for_sync_mutalloc! {
::core::cell::RefCell<A>, try_borrow_mut
}