python-suitcase icon indicating copy to clipboard operation
python-suitcase copied to clipboard

BitField fails to work with more than 8 bytes

Open djmoreho opened this issue 10 years ago • 1 comments

BitField can handle up to 8 bytes (64 bits) but cannot handle 9 bytes (72 bits)

>>> from suitcase.structure import Structure
>>> from suitcase.fields import BitField, BitNum
>>> class Working(Structure):
...     data = BitField(8*8, a=BitNum(8*8))
... 
>>> class NotWorking(Structure):
...     data = BitField(9*8, b=BitNum(9*8))
... 
>>> w = Working.from_data("12345678")
>>> w
Working (
  data=BitField(
    a=3544952156018063160L,
  ),
)
>>> n = NotWorking.from_data("123456789")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Library/Python/2.7/site-packages/suitcase/structure.py", line 246, in from_data
    m = cls()
  File "/Library/Python/2.7/site-packages/suitcase/structure.py", line 260, in __init__
    field = field_placeholder.create_instance(self)
  File "/Library/Python/2.7/site-packages/suitcase/fields.py", line 39, in create_instance
    instance = self.cls(*self.args, **self.kwargs)
  File "/Library/Python/2.7/site-packages/suitcase/fields.py", line 1313, in __init__
    }[self.number_bytes]()
KeyError: 9
>>> 

The reason is obvious, in the BitField code there is only a dictionary for up to 8 bytes, no more

self.number_bits = number_bits
self.number_bytes = number_bits // 8
self.bytes_required = self.number_bytes
if field is None:
    field = {
        1: UBInt8,
        2: UBInt16,
        3: UBInt24,
        4: UBInt32,
        5: UBInt40,
        6: UBInt48,
        7: UBInt56,
        8: UBInt64,
    }[self.number_bytes]()

number_bytes only has a corresponding key up to 8 bytes.

Probably can fix this using a FieldArray?

djmoreho avatar Dec 29 '15 14:12 djmoreho

Yeah, feel free to put together a PR for this and we will take a look.

posborne avatar Dec 30 '15 08:12 posborne