Skip to content

Commit

Permalink
Merge pull request #2 from ilivit/boolean_support
Browse files Browse the repository at this point in the history
Boolean support
  • Loading branch information
eerimoq committed Dec 9, 2015
2 parents 8fdc797 + 6ca7379 commit 32e32ce
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 3 deletions.
18 changes: 16 additions & 2 deletions bitstruct.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@


def _parse_format(fmt):
types = re.findall(r'[a-zA-Z]+', fmt)
types = re.findall(r'[a-zA-Z?]+', fmt)
sizes = map(lambda size: int(size),
re.findall(r'\d+', fmt))
return zip(types, sizes)
Expand All @@ -15,6 +15,10 @@ def _pack_integer(size, arg):
return '{{:0{}b}}'.format(size).format(arg)


def _pack_boolean(size, arg):
return _pack_integer(size, int(arg))


def _pack_float(size, arg):
if size == 32:
value = struct.pack('>f', arg)
Expand All @@ -40,6 +44,11 @@ def _unpack_integer(type, bits):
return value


def _unpack_boolean(bits):
value = _unpack_integer('u', bits)
return bool(value)


def _unpack_float(size, bits):
packed = _unpack_bytearray(size, bits)
if size == 32:
Expand Down Expand Up @@ -71,13 +80,14 @@ def pack(fmt, *args):
:returns: Bytearray of packed values.
`fmt` is a string of type-length pairs. There are five
types; 'u', 's', 'f', 'b' and 'p'. Length is the number of bits to pack
types; 'u', 's', 'f', 'b', '?' and 'p'. Length is the number of bits to pack
the value into.
- 'u' -- unsigned integer
- 's' -- signed integer
- 'f' -- floating point number of 32 or 64 bits
- 'b' -- bytearray
- '?' -- boolean
- 'p' -- padding, ignore
Example format string: 'u1u3p7s16'
Expand All @@ -96,6 +106,8 @@ def pack(fmt, *args):
bits += _pack_float(size, args[i])
elif type == 'b':
bits += _pack_bytearray(size, args[i])
elif type == '?':
bits += _pack_boolean(size, args[i])
else:
raise ValueError("bad type '{}' in format".format(type))
i += 1
Expand Down Expand Up @@ -133,6 +145,8 @@ def unpack(fmt, data):
value = _unpack_float(size, bits[i:i+size])
elif type == 'b':
value = _unpack_bytearray(size, bits[i:i+size])
elif type == '?':
value = _unpack_boolean(bits[i:i+size])
res.append(value)
i += size
return tuple(res)
Expand Down
30 changes: 29 additions & 1 deletion tests/test_bitstruct.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,15 @@ def test_pack(self):
packed = pack('u1s6f32b43', 0, -2, 3.75, bytearray(b'\x00\xff\x00\xff\x00\xff'))
self.assertEqual(packed, bytearray(b'\x7c\x80\xe0\x00\x00\x01\xfe\x01\xfe\x01\xc0'))

packed = pack('?1', True)
self.assertEqual(packed, bytearray(b'\x80'))

packed = pack('?1p6?1', True, True)
self.assertEqual(packed, bytearray(b'\x81'))

packed = pack('u5?2u1', -1, False, 1)
self.assertEqual(packed, bytearray(b'\xf9'))

def test_unpack(self):
'''
Unpack values.
Expand All @@ -53,6 +62,22 @@ def test_unpack(self):
unpacked = unpack('u1s6f32b43', packed)
self.assertEqual(unpacked, (0, -2, 3.75, bytearray(b'\x00\xff\x00\xff\x00\xe0')))

packed = bytearray(b'\x80')
unpacked = unpack('?1', packed)
self.assertEqual(unpacked, (True,))

packed = bytearray(b'\x80')
unpacked = unpack('?1p6?1', packed)
self.assertEqual(unpacked, (True, False))

packed = bytearray(b'\x06')
unpacked = unpack('u5?2u1', packed)
self.assertEqual(unpacked, (0, True, 0))

packed = bytearray(b'\x04')
unpacked = unpack('u5?2u1', packed)
self.assertEqual(unpacked, (0, True, 0))

# bad float size
try:
unpack('f33', bytearray(b'\x00\x00\x00\x00\x00'))
Expand Down Expand Up @@ -84,10 +109,13 @@ def test_calcsize(self):
size = calcsize('u1s6u7u9')
self.assertEqual(size, 23)

size = calcsize('?1s6u7u9')
self.assertEqual(size, 23)

def test_byteswap(self):
'''
Byte swap.
'''
'''
res = bytearray(b'\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a')
ref = bytearray(b'\x01\x03\x02\x04\x08\x07\x06\x05\x0a\x09')
self.assertEqual(byteswap('12142', ref), res)
Expand Down

0 comments on commit 32e32ce

Please sign in to comment.