binrw icon indicating copy to clipboard operation
binrw copied to clipboard

Referencing fields in `#[brw]` is impossible due to value/ref differences between `BinRead` and `BinWrite`

Open DCNick3 opened this issue 3 years ago • 1 comments

It's tricky (impossible?) to use assert attribute in brw key. For example this code:

#[derive(BinRead, BinWrite)]
#[brw(assert(unused == 0u8))]
struct Hello {
  unused: u8
}

Will give you an error Can't compare &u8 with u8, probably because unused is a &u8. But if you try to dereference it with * you get Type u8 cannot be dereferenced. Really confusing.

Ultimately this is due to br giving you fields by-value and bw - by-reference. So, even when you want to enforce the invariant for both reading and writing, you would need to write two implementations in most cases.

Maybe it's worth making them both provide fields by-reference? :thinking: Not sure what other impact it may have.

It seems there was a mention of brw usability for assert being questionable in #3, but there doesn't seem to be much discussion...

DCNick3 avatar Dec 12 '22 13:12 DCNick3

Hi, I ran into the same issue when trying to use args (and args_raw). If I use the field, it will tell me I'm using a reference when it's expecting a value, and if I dereference it, it just tells me I can't dereference a value. It only happens if I try to use args with the brw macro.

For those wondering that might come by, here is a possible fix (for args at least, but I guess it would be the same kind of fix for assert):

// Before
#[brw(args(value))] // won't compile

// After
#[br(args(value))]
#[bw(args(*value))]

zodiia avatar Apr 04 '24 18:04 zodiia