首页 > 解决方案 > 我可以在 Rust 中为一组相关类型提供一个类型参数吗?

问题描述

我正在开发一个适用于 32 位和 64 位架构的 PE 文件的库。一些结构会同时引用虚拟地址(VA,例如ImageBase)和相对虚拟地址(RVA,例如节偏移),例如:

type VA32 = u32;
type RVA32 = i32;

struct Header32 {
    image_base: VA32,
    section_offsets: Vec<RVA32>,
}

let hdr = Header32 { /* ... */ };

在处理 32 位 PE 文件时,VA 应该是 32 位且无符号的,而 RVA 应该是 32 位且有符号的。对于 64 位 PE 文件,两种类型都应为 64 位。

我希望我的结构为这些类型使用适当的宽度,可能是通过使它们通用:

struct Header<VA, RVA> {
    image_base: VA,
    section_offsets: Vec<RVA>,
}

type VA32 = u32;
type RVA32 = i32;

let hdr: Header<VA32, RVA32> = Header { /* ... */ };

VA32只有永远存在RVA32,也VA64应该永远被提供RVA64。有没有一种惯用的方式可以表达这一点?

使用完全组成的语法,我希望执行以下操作:

struct Header<Arch> {
    image_base: arch.VA,
    section_offsets: Vec<arch.RVA>,
}

type Arch32 = { VA: u32, RVA: i32 }

let hdr: Header<Arch32> = Header { /* ... */ };

标签: genericstypesrust

解决方案


您可以使用具有关联类型和零大小结构的特征作为标记来执行类似于您的组合语法的操作。

trait Arch {
    type VA;
    type RVA;
}

#[derive(Debug)]
struct Arch32;
impl Arch for Arch32 {
    type VA = u32;
    type RVA = i32;
}

#[derive(Debug)]
struct Arch64;
impl Arch for Arch64 {
    type VA = u64;
    type RVA = i64;
}

#[derive(Debug)]
struct Header<T: Arch> {
    image_base: T::VA,
    section_offsets: Vec<T::RVA>,
}

操场


推荐阅读