use core::{alloc::Layout, ptr::NonNull};

use crate::Arena;

// Always implement allocator_api2::alloc::Allocator (the polyfill crate).
#[cfg(feature = "allocator-api2")]
unsafe impl allocator_api2::alloc::Allocator for Arena {
    #[inline]
    fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, allocator_api2::alloc::AllocError> {
        self.try_alloc_layout(layout)
            .map_err(|_| allocator_api2::alloc::AllocError)
    }

    #[inline]
    unsafe fn deallocate(&self, _ptr: NonNull<u8>, _layout: Layout) {
        // Individual allocations are never freed.
    }
}

// On nightly, also implement std::alloc::Allocator so that
// std collections (HashMap, HashSet, etc.) can use the arena.
#[cfg(nightly)]
unsafe impl core_alloc::alloc::Allocator for Arena {
    #[inline]
    fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, core_alloc::alloc::AllocError> {
        self.try_alloc_layout(layout)
            .map_err(|_| core_alloc::alloc::AllocError)
    }

    #[inline]
    unsafe fn deallocate(&self, _ptr: NonNull<u8>, _layout: Layout) {
        // Individual allocations are never freed.
    }
}
