我正在开发一个与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 { /* ... */ };
您可以使用具有关联类型的特征和零大小的结构作为标记来执行与您编写的语法类似的操作。
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>,
}