use std::fmt::{self, Debug, Display};
use std::num::ParseIntError;
use std::ops::AddAssign;
use std::str::FromStr;
use crate::pxe::Pfn;
use crate::structs::PageKind;
pub trait Gxa: Sized + Default + Copy + From<u64> {
fn u64(&self) -> u64;
fn offset(&self) -> u64 {
self.u64() & 0xf_ff
}
#[must_use]
fn page_aligned(&self) -> bool {
self.offset() == 0
}
#[must_use]
fn page_align(&self) -> Self {
Self::from(self.u64() & !0xf_ff)
}
#[must_use]
fn next_aligned_page(self) -> Self {
Self::from(
self.page_align()
.u64()
.checked_add(PageKind::Normal.size())
.expect("Cannot overflow"),
)
}
}
#[derive(Debug, Clone, Copy, Eq, Hash, PartialEq, Default, PartialOrd, Ord)]
pub struct Gpa(u64);
impl Gpa {
#[must_use]
pub const fn new(addr: u64) -> Self {
Self(addr)
}
#[must_use]
pub const fn from_pfn(pfn: Pfn) -> Self {
Self(pfn.u64() << (4 * 3))
}
#[must_use]
pub const fn from_pfn_with_offset(pfn: Pfn, offset: u64) -> Self {
let base = pfn.u64() << (4 * 3);
Self(base + offset)
}
#[must_use]
pub const fn pfn(&self) -> u64 {
self.0 >> (4 * 3)
}
}
impl AddAssign for Gpa {
fn add_assign(&mut self, rhs: Self) {
self.0 += rhs.0;
}
}
impl Gxa for Gpa {
fn u64(&self) -> u64 {
self.0
}
}
impl From<u64> for Gpa {
fn from(value: u64) -> Self {
Gpa(value)
}
}
impl From<Gpa> for u64 {
fn from(value: Gpa) -> Self {
value.0
}
}
impl From<&Gpa> for u64 {
fn from(value: &Gpa) -> Self {
value.0
}
}
impl Display for Gpa {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "GPA:{:#x}", self.0)
}
}
impl FromStr for Gpa {
type Err = ParseIntError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let s = s.replace('`', "");
Ok(Gpa::new(u64::from_str_radix(
s.trim_start_matches("0x"),
16,
)?))
}
}
#[derive(Debug, Clone, Copy, Eq, Hash, PartialEq, Default, PartialOrd, Ord)]
pub struct Gva(u64);
impl Gva {
#[must_use]
pub const fn new(addr: u64) -> Self {
Self(addr)
}
#[allow(clippy::erasing_op, clippy::identity_op)]
#[must_use]
pub const fn pte_idx(&self) -> u64 {
(self.0 >> (12 + (9 * 0))) & 0b1_1111_1111
}
#[allow(clippy::identity_op)]
#[must_use]
pub const fn pde_idx(&self) -> u64 {
(self.0 >> (12 + (9 * 1))) & 0b1_1111_1111
}
#[must_use]
pub const fn pdpe_idx(&self) -> u64 {
(self.0 >> (12 + (9 * 2))) & 0b1_1111_1111
}
#[must_use]
pub fn pml4e_idx(&self) -> u64 {
(self.0 >> (12 + (9 * 3))) & 0b1_1111_1111
}
}
impl AddAssign for Gva {
fn add_assign(&mut self, rhs: Self) {
self.0 += rhs.0;
}
}
impl Gxa for Gva {
fn u64(&self) -> u64 {
self.0
}
}
impl From<u64> for Gva {
fn from(value: u64) -> Self {
Gva(value)
}
}
impl From<Gva> for u64 {
fn from(value: Gva) -> Self {
value.0
}
}
impl From<&Gva> for u64 {
fn from(value: &Gva) -> Self {
value.0
}
}
impl Display for Gva {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "Gva:{:#x}", self.0)
}
}