use crate::ArenaAllocator;
use allocator_api2::alloc::{AllocError, Allocator};
use core::{alloc::Layout, ptr::NonNull};
pub struct Cond<A, F> {
alloc: A,
pred: F,
}
impl<A, F> Cond<A, F> {
#[inline]
pub fn new(alloc: A, pred: F) -> Self {
Self { alloc, pred }
}
}
unsafe impl<A, F> Allocator for Cond<A, F>
where
A: Allocator,
F: Fn(Layout) -> bool,
{
fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
if (self.pred)(layout) {
self.alloc.allocate(layout)
} else {
Err(AllocError)
}
}
#[inline]
unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
self.alloc.deallocate(ptr, layout)
}
}
impl<A, F> ArenaAllocator for Cond<A, F>
where
A: ArenaAllocator,
F: Fn(Layout) -> bool,
{
#[inline]
fn contains(&self, ptr: NonNull<u8>, layout: Layout) -> bool {
self.alloc.contains(ptr, layout)
}
}
pub struct Fallback<P, S> {
primary: P,
secondary: S,
}
impl<P, S> Fallback<P, S> {
#[inline]
pub fn new(primary: P, secondary: S) -> Self {
Self { primary, secondary }
}
#[inline]
pub fn primary(&self) -> &P {
&self.primary
}
#[inline]
pub fn secondary(&self) -> &S {
&self.secondary
}
}
unsafe impl<P, S> Allocator for Fallback<P, S>
where
P: ArenaAllocator,
S: Allocator,
{
fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
self.primary
.allocate(layout)
.or_else(|_| self.secondary.allocate(layout))
}
unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
if self.primary.contains(ptr, layout) {
self.primary.deallocate(ptr, layout)
} else {
self.secondary.deallocate(ptr, layout)
}
}
}
impl<P, S> ArenaAllocator for Fallback<P, S>
where
P: ArenaAllocator,
S: ArenaAllocator,
{
#[inline]
fn contains(&self, ptr: NonNull<u8>, layout: Layout) -> bool {
self.primary.contains(ptr, layout) || self.secondary.contains(ptr, layout)
}
}