Могу ли я предоставить группу связанных типов с одним параметром типа в Rust? - PullRequest
4 голосов
/ 21 апреля 2019

Я разрабатываю библиотеку, которая работает с файлами PE для 32- и 64-разрядных архитектур. Некоторые структуры будут ссылаться как на виртуальные адреса (VA, например, ImageBase), так и на относительные виртуальные адреса (RVA, например, смещение секции), например:

type VA32 = u32;
type RVA32 = i32;

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

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

При работе с 32-битными файлами PE виртуальный компьютер должен быть 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 { /* ... */ };

1 Ответ

6 голосов
/ 21 апреля 2019

Вы можете сделать что-то похожее на ваш составной синтаксис, используя черты со связанными типами и структурами нулевого размера в качестве маркеров.

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>,
}

детская площадка

...