#![no_std]
#![feature(step_trait, const_trait_impl)]

use core::ops::{Deref, DerefMut};

use address::{AsPhysicalAddress, PhysicalAddress};
use kernel_arch_interface::KERNEL_VIRT_OFFSET;

pub mod address;
pub mod device;
pub mod pointer;
pub mod process;
pub mod table;

/// Describes which kind of a page fault occured
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum PageFaultKind {
    TranslationFault { write: bool },
    WriteFault,
    AccessFault,
    Other,
}

/// Wrapper type to represent an object residing within the kernel
#[repr(transparent)]
pub struct KernelImageObject<T> {
    inner: T,
}

// KernelImageObject wrapper for objects inside the kernel

impl<T> KernelImageObject<T> {
    /// Wraps a value in the [KernelImageObject], allowing its physical address calculation.
    ///
    /// # Safety
    ///
    /// The caller must ensure the T is a `static (mut)` binding inside the kernel.
    pub const unsafe fn new(inner: T) -> Self {
        Self { inner }
    }
}

impl<T> AsPhysicalAddress for KernelImageObject<T> {
    unsafe fn as_physical_address(&self) -> PhysicalAddress {
        PhysicalAddress::from_usize(&self.inner as *const _ as usize - KERNEL_VIRT_OFFSET)
    }
}

impl<T> Deref for KernelImageObject<T> {
    type Target = T;

    fn deref(&self) -> &Self::Target {
        &self.inner
    }
}

impl<T> DerefMut for KernelImageObject<T> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.inner
    }
}
