//
// hardened-malloc: Global allocator using GrapheneOS allocator
// src/lib.rs: Global allocator definition
//
// Copyright (c) 2025, 2026 Ali Polatel <alip@chesswob.org>
// Based in part upon hardened_malloc-rs/src/lib.rs which is
//   Copyright (c) strawberry <strawberry@puppygock.gay>
//   SPDX-License-Identifier: Apache-2.0 OR MIT
//
// SPDX-License-Identifier: MIT

#![no_std]

use core::{
    alloc::{GlobalAlloc, Layout},
    ffi::c_void,
};

// POSIX
pub use hardened_malloc_sys::posix_memalign;
// C standard
pub use hardened_malloc_sys::{aligned_alloc, calloc, free, malloc, realloc};
// hardened_malloc extensions
pub use hardened_malloc_sys::{free_sized, malloc_object_size, malloc_object_size_fast};

pub struct HardenedMalloc;

unsafe impl GlobalAlloc for HardenedMalloc {
    #[inline]
    unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
        malloc(layout.size()) as *mut u8
    }

    #[inline]
    unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
        calloc(layout.size(), 1) as *mut u8
    }

    #[inline]
    unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
        // Deallocate memory using free_sized.
        // Pass the size of the allocation to ensure proper sized deallocation.
        free_sized(ptr as *mut c_void, layout.size());
    }

    #[inline]
    unsafe fn realloc(&self, ptr: *mut u8, _layout: Layout, size: usize) -> *mut u8 {
        realloc(ptr as *mut c_void, size) as *mut u8
    }
}
