我需要消除这段代码中的重复:
pub struct Memory {
layout: MemoryLayout,
rom: Vec<u8>,
ram: Vec<u8>,
}
impl Memory {
pub fn get_mem_vec_ref(&self, address: u32) -> Result<&Vec<u8>, RiscvError> {
// ...
let mem_vec_ref = match address {
addr if (rom_start..rom_end).contains(&addr) => Ok(&self.rom),
addr if (ram_start..ram_end).contains(&addr) => Ok(&self.ram),
addr => Err(RiscvError::MemoryAlignmentError(addr)),
}?;
return Ok(mem_vec_ref);
}
pub fn get_mem_vec_mut_ref(&mut self, address: u32) -> Result<&mut Vec<u8>, RiscvError> {
// ...
let mem_vec_ref = match address {
addr if (rom_start..rom_end).contains(&addr) => Ok(&mut self.rom),
addr if (ram_start..ram_end).contains(&addr) => Ok(&mut self.ram),
addr => Err(RiscvError::MemoryAlignmentError(addr)),
}?;
return Ok(mem_vec_ref);
}
}
如何使用可变与不可变的 self 引用进行抽象?在这种情况下,
Box
或 RefCell
有帮助吗?
由于您在这两种情况下都处理引用,因此您可以定义一个通用函数,其中
T
是 &Vec<u8>
或 &mut Vec<u8>
。所以你可以做这样的事情:
fn get_mem<T>(address: u32, rom: T, ram: T) -> Result<T, RiscvError> {
// ...
match address {
addr if (rom_start..rom_end).contains(&addr) => Ok(rom),
addr if (ram_start..ram_end).contains(&addr) => Ok(ram),
addr => Err(RiscvError::MemoryAlignmentError(addr)),
}
}
impl Memory {
pub fn get_mem_vec_ref(&self, address: u32) -> Result<&Vec<u8>, RiscvError> {
// ...
let mem_vec_ref = get_mem(address, &self.rom, &self.ram)?;
return Ok(mem_vec_ref);
}
pub fn get_mem_vec_mut_ref(&mut self, address: u32) -> Result<&mut Vec<u8>, RiscvError> {
// ...
let mem_vec_ref = get_mem(address, &mut self.rom, &mut self.ram)?;
return Ok(mem_vec_ref);
}
}
现在,显然您需要修改
get_mem()
以考虑 rom_start
、rom_end
、ram_start
、ram_end
。如果您想避免将 100 个字段传递给 get_mem()
,那么可能值得引入一种新类型来处理地址,例如像这样的东西:
struct Addr {
// ...
}
impl Addr {
fn get_mem<T>(&self, rom: T, ram: T) -> Result<T, RiscvError> {
// ...
}
}