use std::ops::Deref;
use crate::guest_ptr::GuestReadFail;
use crate::prelude::*;
use crate::GuestType;
use super::{find_per_cpu_address, symbol_addr_from_name};
pub trait OsiType: Sized {
type MethodDispatcher;
fn osi_read(cpu: &mut CPUState, base_ptr: target_ptr_t) -> Result<Self, GuestReadFail>;
}
#[doc(hidden)]
pub struct EmptyMethodDelegator(&'static str, bool);
impl EmptyMethodDelegator {
pub const fn new(_: &'static str, _: bool) -> Self {
Self("", false)
}
}
impl<T: GuestType> OsiType for T {
type MethodDispatcher = EmptyMethodDelegator;
fn osi_read(cpu: &mut CPUState, base_ptr: target_ptr_t) -> Result<Self, GuestReadFail> {
T::read_from_guest(cpu, base_ptr)
}
}
#[doc(hidden)]
pub struct PerCpu<T: OsiType>(pub &'static str, pub T::MethodDispatcher);
impl<T: OsiType> PerCpu<T> {
pub fn read(&self, cpu: &mut CPUState) -> Result<T, GuestReadFail> {
let ptr = find_per_cpu_address(cpu, self.0)?;
T::osi_read(cpu, ptr)
}
}
impl<T: OsiType> Deref for PerCpu<T> {
type Target = T::MethodDispatcher;
fn deref(&self) -> &Self::Target {
&self.1
}
}
#[doc(hidden)]
pub struct OsiGlobal<T: OsiType>(pub &'static str, pub T::MethodDispatcher);
impl<T: OsiType> OsiGlobal<T> {
pub fn read(&self, cpu: &mut CPUState) -> Result<T, GuestReadFail> {
let ptr = symbol_addr_from_name(self.0);
T::osi_read(cpu, ptr)
}
}
impl<T: OsiType> Deref for OsiGlobal<T> {
type Target = T::MethodDispatcher;
fn deref(&self) -> &Self::Target {
&self.1
}
}