lunixbochs / struc

Better binary packing for Go
MIT License
576 stars 45 forks source link

bitfield support #7

Open lunixbochs opened 9 years ago

lunixbochs commented 9 years ago
type Example struct {
    Misc int
    Bitfield struct {
        A int `struc:"[0]bit"`
        B int `struc:"[1:3]bit"`
        C int `struc:"[3:9]bit"`
        D int `struc:"[9:15]bit"`
    } `struc:"[16]bits"`
}
pdf commented 9 years ago

This would be really awesome, spent a bunch of time implementing these manually today.

lunixbochs commented 9 years ago

I want to implement this, but I need a good way to represent it.

With the original syntax above, I can't initialize it very easily. The following doesn't work, because the embedded struct needs a type specifier. This StackOverflow question seems to suggest there are no good solutions.

&Example{1, {1, 2, 3, 4}}

I came up with the below, but I'm not very happy with it.

type BitfieldEmbed struct {
    A int `struc:"[0]bit"`
    B int `struc:"[1:3]bit"`
    C int `struc:"[3:9]bit"`
    D int `struc:"[9:15]bit"`
} 

type Bitfield struct {
    Misc     int
    Bitfield BitfieldEmbed `struc:"[16]bits"`
}

var bitfieldRef = &Bitfield{
    1, BitfieldEmbed{1, 2, 3, 4},
}

What about an array-based syntax, maybe something like this? It's much more concise to define, but access isn't named which could be bug-prone :(

type Bitfield struct {
    Bitfield [4]int `struc:"[0:4:8:12:16]bitfield"`
}
pdf commented 9 years ago

I think my preference would be for the embedded bitfield struct, but that would mean enforcing some semantics - struct with bit fields must only contain bit fields, bit totals can't overflow the size defined on the embed. Are you considering using the [n]bits tag as a hint for bitfield processing? Otherwise I'd probably suggest just using standard int types, because you won't be able to represent arbitrary lengths of bits easily (people will try [12]bits).

lunixbochs commented 9 years ago

The only problem I have with using a standard int type is if someone needs a bitfield larger than 64 bits.

pdf commented 9 years ago

[2]uint64, [3]uint32 or similar should handle that?

lunixbochs commented 9 years ago

At that point, why not just [N]byte?

pdf commented 9 years ago

Sure, it's whatever makes most sense to the user if you use int types, or slices of ints. The important thing is that it's not possible to define a size that doesn't align to byte boundaries, because then you've either got to throw another error at runtime or the representation won't match the definition.

lunixbochs commented 8 years ago

this will also be useful for x86 GDT entries

could use bitfield pack/unpacker for float16

m29h commented 1 year ago

Hi, in case anyone here is interested my compile time code generator called struc-gen for struct marshaling now supports bitfields as well (in addition to the regular larger types). It allows you to marshal the following structure:

type Bitfield struct {
    BitArray [211]int `struc:"[211]uint3"`
    BitVal   int      `struc:"uint7"`
}

into exactly 211*3+7=640 bits = 80 bytes