use core::{fmt, marker::PhantomData};
use super::{cfg, raw_cfg, Cfg};
use crate::utils::Init;
#[doc = include_str!("../common.md")]
pub struct Hunk<System: cfg::KernelStatic> {
start: usize,
_phantom: PhantomData<System>,
}
impl<System: cfg::KernelStatic> Init for Hunk<System> {
const INIT: Self = Self::from_offset(0);
}
impl<System: cfg::KernelStatic> fmt::Debug for Hunk<System> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Hunk({:p})", self.as_ptr())
}
}
impl<System: cfg::KernelStatic> Clone for Hunk<System> {
#[inline]
fn clone(&self) -> Self {
*self
}
}
impl<System: cfg::KernelStatic> Copy for Hunk<System> {}
impl<System: cfg::KernelStatic> Hunk<System> {
pub const fn define() -> HunkDefiner<System> {
HunkDefiner::new()
}
#[doc(hidden)]
#[inline]
pub const fn from_offset(start: usize) -> Self {
Self {
start,
_phantom: PhantomData,
}
}
#[inline]
pub const fn offset(self) -> usize {
self.start
}
}
impl<System: cfg::KernelStatic> Hunk<System> {
#[inline]
pub fn as_ptr(self) -> *mut u8 {
System::cfg_hunk_pool_ptr().wrapping_add(self.start)
}
}
#[must_use = "must call `finish()` to complete definition"]
pub struct HunkDefiner<System> {
_phantom: PhantomData<System>,
len: usize,
align: usize,
}
impl<System: cfg::KernelStatic> HunkDefiner<System> {
pub const fn new() -> Self {
Self {
_phantom: PhantomData,
len: 0,
align: 1,
}
}
pub const fn len(self, len: usize) -> Self {
Self { len, ..self }
}
pub const fn align(self, align: usize) -> Self {
Self { align, ..self }
}
}
impl<System: cfg::KernelStatic> HunkDefiner<System> {
pub const fn finish<C: raw_cfg::CfgBase>(self, cfg: &mut Cfg<C>) -> Hunk<System> {
let Self { align, len, .. } = self;
cfg.hunk_pool_len = (cfg.hunk_pool_len + align - 1) / align * align;
let start = cfg.hunk_pool_len;
cfg.hunk_pool_len += len;
if align > cfg.hunk_pool_align {
cfg.hunk_pool_align = align;
}
Hunk::from_offset(start)
}
}