diff --git a/src/cpu/bus/read.rs b/src/cpu/bus/read.rs index 168e912..2496fe5 100644 --- a/src/cpu/bus/read.rs +++ b/src/cpu/bus/read.rs @@ -10,7 +10,7 @@ use std::{fmt::Debug, slice::SliceIndex}; /// Gets a `&[T]` at [SliceIndex] `I`. /// /// This is similar to the [SliceIndex] method `.get(...)`, however implementing this trait -/// for [u8] will auto-impl [Read]<(i8, u8, i16, u16 ... i128, u128)> +/// for [u8] will auto-impl [ReadWrite]<([i8], [u8], [i16], [u16] ... [i128], [u128])> pub trait Get { /// Gets the slice of Self at [SliceIndex] I fn get(&self, index: I) -> Option<&>::Output> @@ -23,7 +23,7 @@ pub trait Get { I: SliceIndex<[T]>; } -/// Read a T from address `addr` +/// Read or Write a T at address `addr` pub trait ReadWrite: FallibleReadWrite { /// Reads a T from address `addr` /// @@ -42,7 +42,7 @@ pub trait ReadWrite: FallibleReadWrite { /// Read a T from address `addr`, and return the value as a [Result] pub trait FallibleReadWrite: Get { - /// The [Err] type returned by [read_fallible] + /// The [Err] type type Error: Debug; /// Read a T from address `addr`, returning the value as a [Result] fn read_fallible(&self, addr: impl Into) -> Result; @@ -55,45 +55,44 @@ pub trait FallibleReadWrite: Get { /// Relies on inherent methods of Rust numeric types: /// - `Self::from_be_bytes` /// - `Self::to_be_bytes` -macro_rules! impl_rw { - ($($t:ty) ,* $(,)?) => { - $( - impl + FallibleReadWrite<$t>> ReadWrite<$t> for T { - #[inline(always)] - fn read(&self, addr: impl Into) -> $t { - self.read_fallible(addr).ok().unwrap_or_default() - } - #[inline(always)] - fn write(&mut self, addr: impl Into, data: $t) { - self.write_fallible(addr, data).ok(); +macro_rules! impl_rw {($($t:ty) ,* $(,)?) =>{ + $( + #[doc = concat!("Read or Write [", stringify!($t), "] at address `addr`")] + impl + FallibleReadWrite<$t>> ReadWrite<$t> for T { + #[inline(always)] + fn read(&self, addr: impl Into) -> $t { + self.read_fallible(addr).ok().unwrap_or_default() + } + #[inline(always)] + fn write(&mut self, addr: impl Into, data: $t) { + self.write_fallible(addr, data).ok(); + } + } + impl> FallibleReadWrite<$t> for T { + type Error = $crate::error::Error; + #[inline(always)] + fn read_fallible(&self, addr: impl Into) -> $crate::error::Result<$t> { + let addr: usize = addr.into(); + let range = addr..addr + core::mem::size_of::<$t>(); + if let Some(bytes) = self.get(range.clone()) { + // Chip-8 is a big-endian system + Ok(<$t>::from_be_bytes(bytes.try_into()?)) + } else { + Err($crate::error::Error::InvalidAddressRange{range: range.into()}) } } - impl> FallibleReadWrite<$t> for T { - type Error = $crate::error::Error; - #[inline(always)] - fn read_fallible(&self, addr: impl Into) -> $crate::error::Result<$t> { - let addr: usize = addr.into(); - let range = addr..addr + core::mem::size_of::<$t>(); - if let Some(bytes) = self.get(range.clone()) { - // Chip-8 is a big-endian system - Ok(<$t>::from_be_bytes(bytes.try_into()?)) - } else { - Err($crate::error::Error::InvalidAddressRange{range}) - } - } - #[inline(always)] - fn write_fallible(&mut self, addr: impl Into, data: $t) -> std::result::Result<(), Self::Error> { - let addr: usize = addr.into(); - if let Some(slice) = self.get_mut(addr..addr + core::mem::size_of::<$t>()) { - // Chip-8 is a big-endian system - data.to_be_bytes().as_mut().swap_with_slice(slice); - } - Ok(()) + #[inline(always)] + fn write_fallible(&mut self, addr: impl Into, data: $t) -> std::result::Result<(), Self::Error> { + let addr: usize = addr.into(); + if let Some(slice) = self.get_mut(addr..addr + core::mem::size_of::<$t>()) { + // Chip-8 is a big-endian system + data.to_be_bytes().as_mut().swap_with_slice(slice); } + Ok(()) } - )* - }; -} + } + )* +}} impl_rw!(i8, i16, i32, i64, i128); impl_rw!(u8, u16, u32, u64, u128);