use core::{
alloc::{AllocError, Allocator as ActualAllocator, Layout},
cell::{Cell, UnsafeCell},
pin::{pin, Pin},
ptr::NonNull,
sync::atomic::{AtomicBool, Ordering},
};
use crate::{test::unique_ord_keys, AssocList};
struct TestAllocator<'t> {
used: AtomicBool,
memory: UnsafeCell<Pin<&'t mut [u8]>>,
next: Cell<usize>,
}
impl<'t> TestAllocator<'t> {
#[must_use]
fn new(memory: Pin<&'t mut [u8]>) -> Self {
TestAllocator {
used: AtomicBool::new(false),
memory: UnsafeCell::new(memory),
next: Cell::new(0),
}
}
}
#[allow(unsafe_code)]
unsafe impl ActualAllocator for TestAllocator<'_> {
fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
fn allocate_impl(allocator: &TestAllocator<'_>, layout: Layout) -> Option<NonNull<[u8]>> {
let next_rounded_up = allocator.next.get().checked_next_multiple_of(layout.align())?;
let size = layout.size();
let last_bit = next_rounded_up.checked_add(size)?;
#[allow(unsafe_code)]
if last_bit > unsafe { &*allocator.memory.get() }.len() {
return None;
}
#[allow(unsafe_code)]
let slice: &mut [u8] = unsafe { &mut *allocator.memory.get() };
let non_null = NonNull::new(slice)?;
allocator.next.set(last_bit.saturating_add(1));
Some(non_null)
}
while !self.used.swap(true, Ordering::AcqRel) {}
let ret = allocate_impl(self, layout);
self.used.store(false, Ordering::Release);
ret.ok_or(AllocError)
}
#[allow(unsafe_code)]
unsafe fn deallocate(&self, _ptr: NonNull<u8>, _layout: Layout) {
}
}
#[test]
fn new_in() {
let memory = pin!([0; 0]);
let test_allocator = TestAllocator::new(memory);
let assoc_list: AssocList<usize, f64, _> = AssocList::new_in(test_allocator);
assert!(assoc_list.vec.is_empty());
assert!(unique_ord_keys(assoc_list));
}
#[test]
fn with_capacity_in() {
const CAPACITY: usize = 3;
let memory = pin!([0; 1024]);
let test_allocator = TestAllocator::new(memory);
let assoc_list: AssocList<u16, f32, _> = AssocList::with_capacity_in(CAPACITY, test_allocator);
assert!(assoc_list.vec.is_empty());
assert_eq!(assoc_list.vec.capacity(), CAPACITY);
assert!(unique_ord_keys(assoc_list));
}