在 Rust 中抽象可变/不可变引用

问题描述 投票:0回答:1

我需要消除这段代码中的重复:

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
有帮助吗?

rust reference mutable
1个回答
0
投票

由于您在这两种情况下都处理引用,因此您可以定义一个通用函数,其中

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> {
        // ...
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.