2018-11-14 06:47:52 +11:00
|
|
|
//! Things that I wish were in core, but aren't.
|
|
|
|
|
2018-11-15 14:14:36 +11:00
|
|
|
/// A simple wrapper for any `*mut T` to adjust the basic operations.
|
2018-11-14 06:47:52 +11:00
|
|
|
///
|
2018-11-15 14:14:36 +11:00
|
|
|
/// Read and Write are made to be volatile. Offset is made to be
|
|
|
|
/// wrapping_offset. This makes it much easier to correctly work with IO
|
|
|
|
/// Registers and all display related memory on the GBA.
|
|
|
|
///
|
|
|
|
/// As a bonus, use of this type is mostly `cargo test` safe. Reads will return
|
|
|
|
/// a `zeroed()` value instead, and writes will do nothing.
|
2018-11-14 06:47:52 +11:00
|
|
|
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
|
|
|
|
#[repr(transparent)]
|
|
|
|
pub struct VolatilePtr<T>(pub *mut T);
|
|
|
|
|
|
|
|
impl<T> core::fmt::Pointer for VolatilePtr<T> {
|
|
|
|
/// Formats exactly like the inner `*mut T`.
|
|
|
|
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
|
|
|
|
write!(f, "{:p}", self.0)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T> VolatilePtr<T> {
|
|
|
|
/// Performs a volatile read.
|
|
|
|
///
|
|
|
|
/// # Safety
|
|
|
|
///
|
|
|
|
/// This method adds absolutely no additional safety, so all safety concerns
|
|
|
|
/// for a normal raw pointer volatile read apply.
|
|
|
|
pub unsafe fn read(&self) -> T {
|
2018-11-15 13:47:56 +11:00
|
|
|
#[cfg(not(test))]
|
|
|
|
{
|
|
|
|
core::ptr::read_volatile(self.0)
|
|
|
|
}
|
|
|
|
#[cfg(test)]
|
|
|
|
{
|
|
|
|
core::mem::zeroed::<T>()
|
|
|
|
}
|
2018-11-14 06:47:52 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Performs a volatile write.
|
|
|
|
///
|
|
|
|
/// # Safety
|
|
|
|
///
|
|
|
|
/// This method adds absolutely no additional safety, so all safety concerns
|
|
|
|
/// for a normal raw pointer volatile write apply.
|
|
|
|
pub unsafe fn write(&self, data: T) {
|
2018-11-15 13:47:56 +11:00
|
|
|
#[cfg(not(test))]
|
|
|
|
{
|
|
|
|
core::ptr::write_volatile(self.0, data);
|
|
|
|
}
|
|
|
|
#[cfg(test)]
|
|
|
|
{
|
|
|
|
drop(data)
|
|
|
|
}
|
2018-11-14 06:47:52 +11:00
|
|
|
}
|
|
|
|
|
2018-11-15 14:14:36 +11:00
|
|
|
/// Performs a wrapping_offset by the number of slots given to a new position.
|
2018-11-14 06:47:52 +11:00
|
|
|
///
|
|
|
|
/// # Safety
|
|
|
|
///
|
2018-11-15 14:14:36 +11:00
|
|
|
/// This is a wrapping_offset, so all safety concerns of a normal raw pointer
|
|
|
|
/// wrapping_offset apply.
|
2018-11-14 06:47:52 +11:00
|
|
|
pub unsafe fn offset(self, count: isize) -> Self {
|
2018-11-15 14:14:36 +11:00
|
|
|
VolatilePtr(self.0.wrapping_offset(count))
|
2018-11-14 06:47:52 +11:00
|
|
|
}
|
|
|
|
}
|