use std::sync::Arc;
use zerocopy::{FromBytes, FromZeros, Immutable, IntoBytes};
use crate::error::Result;
use crate::memory::TranslationCache;
use crate::types::{Dtb, VirtAddr};
pub trait MemoryOps<A> {
fn read_bytes(&self, addr: A, buf: &mut [u8]) -> Result<()>;
fn write_bytes(&self, addr: A, buf: &[u8]) -> Result<()>;
fn read_virtual_direct(
&self,
_addr: VirtAddr,
_root: Dtb,
_buf: &mut [u8],
) -> Option<Result<()>> {
None
}
fn translation_cache(&self) -> Option<&TranslationCache> {
None
}
fn read<T: Copy + FromZeros + FromBytes + IntoBytes>(&self, addr: A) -> Result<T> {
let mut obj = T::new_zeroed();
let slice = obj.as_mut_bytes();
self.read_bytes(addr, slice)?;
Ok(obj)
}
fn write<T: Copy + IntoBytes + Immutable>(&self, addr: A, val: &T) -> Result<()> {
let slice = val.as_bytes();
self.write_bytes(addr, slice)
}
}
impl<A, B: MemoryOps<A>> MemoryOps<A> for Arc<B> {
fn read_bytes(&self, addr: A, buf: &mut [u8]) -> Result<()> {
(**self).read_bytes(addr, buf)
}
fn write_bytes(&self, addr: A, buf: &[u8]) -> Result<()> {
(**self).write_bytes(addr, buf)
}
fn read_virtual_direct(&self, addr: VirtAddr, root: Dtb, buf: &mut [u8]) -> Option<Result<()>> {
(**self).read_virtual_direct(addr, root, buf)
}
fn translation_cache(&self) -> Option<&TranslationCache> {
(**self).translation_cache()
}
}