The snippet has a few missing items, but the question will hopefully be clear.
Context
-
The problem involves binary file type with two Header versions.
-
One idea was to use
struct Header<B,C>, with the concrete impls:impl Header<u16, u32>impl Header<u32, u64>
-
Most methods in
Headerneed the concrete number type for comparisons so I can not implement a genericimpl<A,B> Header<A,B>.- For example in
e_machine:
match v { a@4 => {...} }the type of
vmust be defined, so I can not just indicate thatais, say,num_traits:Unsignedwhich I tried. - For example in
-
However, this way I get a lot of repetition (although at least I save 1 struct since my is generic at the moment
Header<S,L>).
Example snippet
// my own simple buffer reader
use crate::buf_reader::BufferReader;
#[allow(dead_code)] // or it complains
#[derive(Debug)]
pub struct ElfHeader<S, L> {
// --snip--
e_machine: NameValueMeaning<S>,
e_version: NameValueMeaning<L>,
e_entry: L
}
impl ElfHeader<u16, u32> {
pub fn from_buf(buf: &mut BufferReader) -> Self {
let e_machine = Self::e_machine(buf.read_t()).unwrap();
let e_version = Self::version(buf.read_t());
let e_entry = buf.read_t();
Self {
e_machine,
e_version,
e_entry,
}
}
pub fn e_machine(val: u16) -> Result<NameValueMeaning<u16>, u16> {
// this has 200 matches, and must be repeated for `<u32>`
// in place of the `<u16>`
match val {
a@0 => Ok(NameValueMeaning{name:"...".to_owned(), value:a , meaning:"...".to_owned()}),
a@1 => Ok(NameValueMeaning{name:"...".to_owned(), value:a , meaning:"...".to_owned()}),
j=> {eprint!("Not a recognised format"); Err(j)}
}
}
pub fn version(val: u32) -> NameValueMeaning<u32> {
match val {
0 => NameValueMeaning { /* ... */ },
j => NameValueMeaning { /*...*/ },
}
}
}
impl ElfHeader<u32, u64> {
// similar, just replacing u16->u32
// u32 -> u64
pub fn e_machine(val: u32) -> Result<NameValueMeaning<u32>, u32> {
// same code inside !
}
}