use core::{mem::size_of, ptr::NonNull};
use crate::{base::tag::Tag, node::Node, ptr_utils};
#[inline]
pub(crate) fn is_chunk_size(base: *mut u8, end: *mut u8) -> bool {
end as usize - base as usize >= CHUNK_UNIT
}
#[inline]
pub(crate) const fn required_chunk_size(size: usize) -> usize {
(size + size_of::<Tag>() + (CHUNK_UNIT - 1)) & !(CHUNK_UNIT - 1)
}
#[inline]
pub(crate) unsafe fn alloc_to_end(base: *mut u8, size: usize) -> *mut u8 {
base.wrapping_add(required_chunk_size(size))
}
pub const CHUNK_UNIT: usize = size_of::<usize>() * 4;
const GAP_NODE_OFFSET: usize = 0;
const GAP_BIN_OFFSET: usize = size_of::<usize>() * 2;
const GAP_LOW_SIZE_OFFSET: usize = size_of::<usize>() * 3;
const GAP_HIGH_SIZE_OFFSET: usize = size_of::<usize>();
pub const END_FLAG: usize = Tag::HEAP_END_FLAG as usize;
#[inline]
pub(crate) unsafe fn gap_base_to_node(base: *mut u8) -> *mut Node {
base.add(GAP_NODE_OFFSET).cast()
}
#[inline]
pub(crate) unsafe fn gap_base_to_bin(base: *mut u8) -> *mut u32 {
base.add(GAP_BIN_OFFSET).cast()
}
#[inline]
pub(crate) unsafe fn gap_base_to_size(base: *mut u8) -> *mut usize {
base.add(GAP_LOW_SIZE_OFFSET).cast()
}
#[inline]
pub(crate) unsafe fn gap_end_to_size_and_flag(end: *mut u8) -> *mut usize {
end.sub(GAP_HIGH_SIZE_OFFSET).cast()
}
#[inline]
pub(crate) unsafe fn gap_node_to_base(node: NonNull<Node>) -> *mut u8 {
node.as_ptr().cast::<u8>().sub(GAP_NODE_OFFSET).cast()
}
#[inline]
pub(crate) unsafe fn gap_node_to_size(node: NonNull<Node>) -> *mut usize {
node.as_ptr().cast::<u8>().sub(GAP_NODE_OFFSET).add(GAP_LOW_SIZE_OFFSET).cast()
}
#[inline]
pub(crate) unsafe fn end_to_tag(end: *mut u8) -> *mut Tag {
end.sub(size_of::<Tag>()).cast()
}
#[inline]
pub(crate) fn align_up(ptr: *mut u8) -> *mut u8 {
ptr_utils::align_up_by(ptr, CHUNK_UNIT)
}
#[inline]
pub(crate) fn align_down(ptr: *mut u8) -> *mut u8 {
ptr_utils::align_down_by(ptr, CHUNK_UNIT)
}