jam1garner / binrw

A Rust crate for helping parse and rebuild binary data using ✨macro magic✨.
https://binrw.rs
MIT License
545 stars 35 forks source link

Allow validation of data with arbitrary located validation bit #254

Closed Ruhrpottpatriot closed 2 months ago

Ruhrpottpatriot commented 3 months ago

I have an array of bytes over the network that I want to parse into a structure. This parsing does work flawlessly, iff the data is well-formed. However, the message might contain garbage. Whether or not this is the case is indicated by a single bit at a pre specified location at the end of the message. If the bit is 1, then the message data is valid. I tried adding a boolean field to the struct and then using seek_before and restore_position, however this crate does not support booleans.

What makes this even more complicated is the fact that between data and validation bit there is additional data, also with validation bits, so a message might have the following format:

000..255: id data
256..767: user data

...

892: id data validation bit
893: user data validation bit

How would I solve this? The idea is to use Some(data) if the validation bit is 1 and None otherwise.

kitlith commented 2 months ago

One idea would be to unconditionally read the data and valid bytes as a temp, then calc the final fields. Something like:

#[binread]
struct Data {
    #[br(temp)]
    raw_id: [u8; 8],
    // ...
    #[br(temp)]
    valid_fields: u8,

    #[br(calc = if (valid_fields & 1) != 0 { Some(raw_id) } else { None })]
    id: Option<[u8; 8]>
}

You'd need to do the reverse for writing, pulling the options back out into bytes to write.

Another idea would be to have it as a separate accessor method, which would let you inspect data marked as invalid if you needed to. Depends on your usecase.