go-restruct / restruct

Rich binary (de)serialization library for Golang
https://restruct.io/
ISC License
360 stars 17 forks source link

Operators don't work for derived types (e.g. `type Flags uint8`) #43

Open joonas-fi opened 3 years ago

joonas-fi commented 3 years ago

This works:

type Item struct {
    Flags         uint8

    FooOptional int `struct:"if=Flags & 1 != 0"` // only present if Flags has 0b1
}

However, this does not:

type ItemFlags uint8

type Item struct {
    Flags         ItemFlags

    FooOptional int `struct:"if=Flags & 1 != 0"`
}

I'll get an error: error: invalid operation: operator & not defined for 0 (uint8) which is somewhat confusing error because the code has and defined for uint8: https://github.com/go-restruct/restruct/blob/5734170a48a1371e880a092c5dd63adfd556cc36/expr/value.go#L803

I realize this has something to do with not type switching on the "root type", but am not smart enough to know where to fix and/or if I fix, are there implications somewhere else..

Test runner to reproduce:

func TestCase(t *testing.T) {
    _, err := restruct.Pack(binary.LittleEndian, Item{})
    assert.Ok(t, err)
}

BTW thanks for the library, it's helped me quite much.. I'm doing something crazy and I'm kinda pushing restruct to its limits by parsing and writing NTFS :D It has somewhat horrible data structures as they're so dynamic and some fields have 64-bit alignment.

jchv commented 3 years ago

Thanks for the bug report. I am a bit busy at times, but I do want to support this library if I can.

This one is definitely a tricky looking one. It looks like my approach with using .Interface() and type switching was not a good idea and will have to be rewritten. The concrete type of a nominal typedef of a primitive is probably not possible to extract with a mere typeswitch alone.

BTW thanks for the library, it's helped me quite much.. I'm doing something crazy and I'm kinda pushing restruct to its limits by parsing and writing NTFS :D It has somewhat horrible data structures as they're so dynamic and some fields have 64-bit alignment.

Wow, that's really cool.