use crate::{AllocateAll, CallbackRef, Owns, ReallocateInPlace};
use core::{
alloc::{AllocError, AllocRef, Layout},
ptr::NonNull,
};
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Proxy<A, C> {
pub alloc: A,
pub callbacks: C,
}
unsafe impl<A: AllocRef, C: CallbackRef> AllocRef for Proxy<A, C> {
#[track_caller]
fn alloc(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
self.callbacks.before_allocate(layout);
let result = self.alloc.alloc(layout);
self.callbacks.after_allocate(layout, result);
result
}
#[track_caller]
fn alloc_zeroed(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
self.callbacks.before_allocate_zeroed(layout);
let result = self.alloc.alloc_zeroed(layout);
self.callbacks.after_allocate_zeroed(layout, result);
result
}
#[track_caller]
unsafe fn dealloc(&self, ptr: NonNull<u8>, layout: Layout) {
crate::check_dealloc_precondition(ptr, layout);
self.callbacks.before_deallocate(ptr, layout);
self.alloc.dealloc(ptr, layout);
self.callbacks.after_deallocate(ptr, layout);
}
#[track_caller]
unsafe fn grow(
&self,
ptr: NonNull<u8>,
old_layout: Layout,
new_layout: Layout,
) -> Result<NonNull<[u8]>, AllocError> {
crate::check_grow_precondition(ptr, old_layout, new_layout);
self.callbacks.before_grow(ptr, old_layout, new_layout);
let result = self.alloc.grow(ptr, old_layout, new_layout);
self.callbacks
.after_grow(ptr, old_layout, new_layout, result);
result
}
#[track_caller]
unsafe fn grow_zeroed(
&self,
ptr: NonNull<u8>,
old_layout: Layout,
new_layout: Layout,
) -> Result<NonNull<[u8]>, AllocError> {
crate::check_grow_precondition(ptr, old_layout, new_layout);
self.callbacks
.before_grow_zeroed(ptr, old_layout, new_layout);
let result = self.alloc.grow_zeroed(ptr, old_layout, new_layout);
self.callbacks
.after_grow_zeroed(ptr, old_layout, new_layout, result);
result
}
#[track_caller]
unsafe fn shrink(
&self,
ptr: NonNull<u8>,
old_layout: Layout,
new_layout: Layout,
) -> Result<NonNull<[u8]>, AllocError> {
crate::check_shrink_precondition(ptr, old_layout, new_layout);
self.callbacks.before_shrink(ptr, old_layout, new_layout);
let result = self.alloc.shrink(ptr, old_layout, new_layout);
self.callbacks
.after_shrink(ptr, old_layout, new_layout, result);
result
}
}
unsafe impl<A: AllocateAll, C: CallbackRef> AllocateAll for Proxy<A, C> {
#[track_caller]
fn allocate_all(&self) -> Result<NonNull<[u8]>, AllocError> {
self.callbacks.before_allocate_all();
let result = self.alloc.allocate_all();
self.callbacks.after_allocate_all(result);
result
}
#[track_caller]
fn allocate_all_zeroed(&self) -> Result<NonNull<[u8]>, AllocError> {
self.callbacks.before_allocate_all_zeroed();
let result = self.alloc.allocate_all_zeroed();
self.callbacks.after_allocate_all_zeroed(result);
result
}
#[track_caller]
fn deallocate_all(&self) {
self.callbacks.before_deallocate_all();
self.alloc.deallocate_all();
self.callbacks.after_deallocate_all();
}
#[track_caller]
#[inline]
fn capacity(&self) -> usize {
self.alloc.capacity()
}
#[track_caller]
#[inline]
fn capacity_left(&self) -> usize {
self.alloc.capacity_left()
}
#[track_caller]
#[inline]
fn is_empty(&self) -> bool {
self.alloc.is_empty()
}
#[track_caller]
#[inline]
fn is_full(&self) -> bool {
self.alloc.is_full()
}
}
unsafe impl<A: ReallocateInPlace, C: CallbackRef> ReallocateInPlace for Proxy<A, C> {
#[track_caller]
unsafe fn grow_in_place(
&self,
ptr: NonNull<u8>,
old_layout: Layout,
new_layout: Layout,
) -> Result<usize, AllocError> {
crate::check_grow_precondition(ptr, old_layout, new_layout);
self.callbacks
.before_grow_in_place(ptr, old_layout, new_layout);
let result = self.alloc.grow_in_place(ptr, old_layout, new_layout);
self.callbacks
.after_grow_in_place(ptr, old_layout, new_layout, result);
result
}
#[track_caller]
unsafe fn grow_in_place_zeroed(
&self,
ptr: NonNull<u8>,
old_layout: Layout,
new_layout: Layout,
) -> Result<usize, AllocError> {
crate::check_grow_precondition(ptr, old_layout, new_layout);
self.callbacks
.before_grow_in_place_zeroed(ptr, old_layout, new_layout);
let result = self.alloc.grow_in_place_zeroed(ptr, old_layout, new_layout);
self.callbacks
.after_grow_in_place_zeroed(ptr, old_layout, new_layout, result);
result
}
#[track_caller]
unsafe fn shrink_in_place(
&self,
ptr: NonNull<u8>,
old_layout: Layout,
new_layout: Layout,
) -> Result<usize, AllocError> {
crate::check_shrink_precondition(ptr, old_layout, new_layout);
self.callbacks
.before_shrink_in_place(ptr, old_layout, new_layout);
let result = self.alloc.shrink_in_place(ptr, old_layout, new_layout);
self.callbacks
.after_shrink_in_place(ptr, old_layout, new_layout, result);
result
}
}
impl<A: Owns, C: CallbackRef> Owns for Proxy<A, C> {
fn owns(&self, ptr: NonNull<[u8]>) -> bool {
self.callbacks.before_owns();
let owns = self.alloc.owns(ptr);
self.callbacks.after_owns(owns);
owns
}
}