Construct parsing for unaligned int field?

800 views Asked by At

I am using this nice little package "construct" for binary data parsing. However, I ran into a case where the format is defined as:

31     24 23              0
+-------------------------+
| status |  an int number |
+-------------------------+

Basically, the higher 8 bits are used for status, and 3 bytes left for integer: an int type with higher bits masked off. I am a bit lost on what is the proper way of defining the format:

  • The brute force way is to define it as ULInt32 and do bit masking myself
  • Is there anyway I can use BitStruct to save the trouble?

Edit

Assuming Little Endian and based on jterrace's example and swapped=True suggestion, I think this is what will work in my case:

sample = "\xff\x01\x01\x01"
c = BitStruct("foo", BitField("i", 24, swapped=True), BitField("status", 8))
c.parse(sample)
Container({'i': 66047, 'status': 1})

Thanks

Oliver

2

There are 2 answers

4
jterrace On BEST ANSWER

This would be easy if construct contained Int24 types, but it doesn't. Instead, you can specify the bit lengths yourself like this:

>>> from construct import BitStruct, BitField
>>> sample = "\xff\x01\x01\x01"
>>> c = BitStruct("foo", BitField("status", 8), BitField("i", 24))
>>> c.parse(sample)
Container({'status': 255, 'i': 65793})

Note: The value \x01\x01\x01 is 65536 + 256 + 1 = 65793

4
Ricardo Cárdenes On
BitStruct("foo",
          BitField("status", 8),
          BitField("number", 24))