-
|
I'm working on learning rust and as a first project decided to work on data type parser (specifically sas7bdat). Right now I'm parsing the header and had a question: #[derive(BinRead, Debug)]
#[br(little)]
struct Properties {
//Capturing magic number here to do custom error check
#[br(count = 32)]
magic_number: Vec<u8>,
//Header Alignment Variable. Corresponds to 64-bit check
#[br(map = |x: u8| if x == 0x33 { 4 } else { 0 })]
a2: usize,
//Creating separate bool for ease of use
#[br(calc = if a2 == 4 { true } else { false })]
adjust64: bool,
//Other Alignment Variable (for padding around timestamps)
#[br(align_before = 35)]
#[br(map = |x: u8| if x == 0x33 { 4 } else { 0 }, pad_after = 1)]
a1: usize,
//Endian Checker. Will use for is_little later on
#[br(map = |x: u8| if x == 1 { false } else { true })]
is_big_end: bool,
//Header Length
#[br(is_big = is_big_end)]
#[br(align_before = 196 + a1)]
hl: u32,
//Page Length
#[br(is_big = is_big_end)]
pl: u32,
}After page length (pl) I'm looking to capture page count which is either an i32 or i64 depending on the value of a2 (if a2 == 4 then i64). What's the best way to do this? I could use the binrw conditional twice but is that the most idiomatic way to do it? Should I just set the type to be isize? (As an aside, I'm realizing hl and pl should be i32 types since they won't be negative). |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 2 replies
-
|
Hi, thanks for your question! Generally, the best way to handle a file format where there are different versions of the same data is to create one “master” format that you expose to application code, write one struct for each different version of the serialised data, and write For a format where data is either 32-bit or 64-bit in a consistent way, you can write a single generic struct Properties {
/* … existing stuff … */
#[br(parse_with = |r, e, a| if a2 == 4 {
Data<u64>::read_options(r, e, a)
} else {
Data<u32>::read_options(r, e, a).map(Data<u64>::from)
}]
data: Data<u64>It’s not correct to use Hopefully this makes sense (and hopefully I didn’t screw anything up, writing advice very late at night :-)). |
Beta Was this translation helpful? Give feedback.
Hi, thanks for your question!
Generally, the best way to handle a file format where there are different versions of the same data is to create one “master” format that you expose to application code, write one struct for each different version of the serialised data, and write
impl From<VariantStruct> for MasterStructimplementations to convert the variant structs to/from the master format.For a format where data is either 32-bit or 64-bit in a consistent way, you can write a single generic
struct Data<T>, useTfor those 32/64 fields, and then parse eitherData<u32>orData<u64>according to the header. It might look something like this: