我需要消除以下代码中的重复:

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);
    }
}

如何使用mutable和immutable对self进行抽象?BoxRefCell对你有帮助吗?

推荐答案

因为在这两种情况下都要处理引用,所以可以定义一个泛型函数,其中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_startrom_endram_startram_end.如果您希望避免将get_mem()个字段传递给get_mem()个,那么引入一个新类型来处理地址可能是值得的,例如:

struct Addr {
    // ...
}

impl Addr {
    fn get_mem<T>(&self, rom: T, ram: T) -> Result<T, RiscvError> {
        // ...
    }
}

Rust相关问答推荐

Arrow RecordBatch as Polars DataFrame

为什么我可以跟踪以前borrow 过的变量?房主在哪里?

这个规则关于或模式到底是什么意思?如果表达片段的类型与p_i|q_i...&q;不一致,就会形成

使用Box优化可选的已知长度数组的内存分配

如何用Axum/Tower压缩Html内容?

如何定义实现同名但返回类型不同的 struct 的函数

零拷贝按步骤引用一段字节

如何防止Cargo 单据和Cargo 出口发布( crate )项目

习语选项<;T>;到选项<;U>;当T->;U用From定义

为什么rustc会自动降级其版本?

为什么在 Allocator API 中 allocate() 使用 `[u8]` 而 deallocate 使用 `u8` ?

为什么 js_sys Promise::new 需要 FnMut?

将多维数组转换为切片

注释闭包参数强调使用高阶排定特征界限

Rust 程序中的内存泄漏

pyO3 和 Panics

如何在 Emacs Elisp 中获得类似格式化的 LSP?

将一片字节复制到一个大小不匹配的数组中

通用类型,不同于输入类型,作为函数的返回值

为什么我不能将元素写入 Rust 数组中移动的位置,但我可以在元组中完成