use crate::sizing::Sizing;
use crate::sizing::Sizing128KiB;
use crate::sizing::Sizing16MiB;
use crate::sizing::Sizing4KiB;
use crate::Teaspoon;
use core::alloc::GlobalAlloc;
use core::alloc::Layout;
use core::ops::Deref;
use spin::Lazy;
#[cfg(feature = "allocator-api")]
use core::alloc::AllocError;
#[cfg(feature = "allocator-api")]
use core::alloc::Allocator;
#[cfg(feature = "allocator-api")]
use core::ptr::NonNull;
#[cfg(feature = "lazy")]
pub type LazyTeaspoon128KiB<F = fn() -> Teaspoon<'static, Sizing128KiB>> =
LazyTeaspoon<Sizing128KiB, F>;
#[cfg(feature = "lazy")]
pub type LazyTeaspoon16MiB<F = fn() -> Teaspoon<'static, Sizing16MiB>> =
LazyTeaspoon<Sizing16MiB, F>;
#[cfg(feature = "lazy")]
pub type LazyTeaspoon4KiB<F = fn() -> Teaspoon<'static, Sizing4KiB>> = LazyTeaspoon<Sizing4KiB, F>;
#[derive(Debug)]
pub struct LazyTeaspoon<S: Sizing, F = fn() -> Teaspoon<'static, S>>(Lazy<Teaspoon<'static, S>, F>);
impl<S: Sizing, F> LazyTeaspoon<S, F> {
#[inline]
#[must_use]
pub const fn new(f: F) -> Self {
Self(Lazy::new(f))
}
}
impl<S: Sizing, F: FnOnce() -> Teaspoon<'static, S>> LazyTeaspoon<S, F> {
#[inline]
pub fn get(&self) -> &Teaspoon<'static, S> {
self
}
}
impl<S: Sizing, F: FnOnce() -> Teaspoon<'static, S>> Deref for LazyTeaspoon<S, F> {
type Target = Teaspoon<'static, S>;
#[inline]
fn deref(&self) -> &Teaspoon<'static, S> {
&self.0
}
}
#[cfg(feature = "allocator-api")]
unsafe impl<S: Sizing, F: FnOnce() -> Teaspoon<'static, S>> Allocator for LazyTeaspoon<S, F> {
fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
self.get().allocate(layout)
}
fn allocate_zeroed(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
self.get().allocate_zeroed(layout)
}
unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
self.get().deallocate(ptr, layout)
}
unsafe fn grow(
&self,
ptr: NonNull<u8>,
old_layout: Layout,
new_layout: Layout,
) -> Result<NonNull<[u8]>, AllocError> {
self.get().grow(ptr, old_layout, new_layout)
}
unsafe fn grow_zeroed(
&self,
ptr: NonNull<u8>,
old_layout: Layout,
new_layout: Layout,
) -> Result<NonNull<[u8]>, AllocError> {
self.get().grow_zeroed(ptr, old_layout, new_layout)
}
unsafe fn shrink(
&self,
ptr: NonNull<u8>,
old_layout: Layout,
new_layout: Layout,
) -> Result<NonNull<[u8]>, AllocError> {
self.get().shrink(ptr, old_layout, new_layout)
}
}
unsafe impl<S: Sizing, F: FnOnce() -> Teaspoon<'static, S>> GlobalAlloc for LazyTeaspoon<S, F> {
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
self.get().alloc(layout)
}
unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
self.get().alloc_zeroed(layout)
}
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
self.get().dealloc(ptr, layout)
}
unsafe fn realloc(&self, ptr: *mut u8, old_layout: Layout, new_size: usize) -> *mut u8 {
self.get().realloc(ptr, old_layout, new_size)
}
}