use crate::{session::Session, Response};
use std::{io, marker::PhantomData};
#[derive(Debug, Clone)]
pub struct Register<T> {
name: String,
address: usize,
_size_marker: PhantomData<T>,
}
impl<T> Register<T> {
pub fn new<S: ToString>(name: S, address: usize) -> Self {
Register {
name: name.to_string(),
address,
_size_marker: PhantomData,
}
}
pub fn get_name(&self) -> &str {
&self.name
}
pub fn get_address(&self) -> usize {
self.address
}
}
macro_rules! impl_register {
($($type:ty => $read_fn:ident, $write_fn:ident);* $(;)?) => {
$(
impl Register<$type> {
pub async fn read(&self, session: &mut Session) -> io::Result<$type> {
session.$read_fn(self.address).await
}
pub async unsafe fn write(
&mut self,
value: $type,
session: &mut Session,
) -> io::Result<Response> {
session.$write_fn(self.address, value).await
}
}
)*
};
}
impl_register! {
u8 => readb, writeb;
u16 => readw, writew;
u32 => readl, writel;
u64 => readq, writeq;
}
#[macro_export]
macro_rules! register {
($($name:ident, $type:ty);*) => {
$(
#[repr(transparent)]
#[derive(Debug, Clone)]
pub struct $name {
register: $crate::register::Register<$type>,
}
impl $name {
pub fn new(address: usize) -> Self {
Self {
register: $crate::register::Register::new(stringify!($name), address),
}
}
}
impl std::ops::Deref for $name {
type Target = $crate::register::Register<$type>;
fn deref(&self) -> &Self::Target {
&self.register
}
}
impl std::ops::DerefMut for $name {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.register
}
}
)*
};
}