Polish and test int packer
This commit is contained in:
parent
10c089debc
commit
6240dd36e5
45
tests/int_packer_test.py
Normal file
45
tests/int_packer_test.py
Normal file
|
@ -0,0 +1,45 @@
|
|||
from twnet_parser.packer import *
|
||||
|
||||
def test_pack_small_positive_ints():
|
||||
assert pack_int(1) == b'\x01'
|
||||
assert pack_int(2) == b'\x02'
|
||||
assert pack_int(3) == b'\x03'
|
||||
|
||||
assert pack_int(44) == b'\x2C'
|
||||
assert pack_int(45) == b'\x2D'
|
||||
assert pack_int(46) == b'\x2E'
|
||||
|
||||
def test_pack_multi_byte_positive_ints():
|
||||
assert pack_int(63) == b'\x3F'
|
||||
assert pack_int(64) == b'\x80\x01'
|
||||
assert pack_int(65) == b'\x81\x01'
|
||||
|
||||
def test_pack_small_negative_ints():
|
||||
assert pack_int(-1) == b'\x40'
|
||||
assert pack_int(-2) == b'\x41'
|
||||
assert pack_int(-3) == b'\x42'
|
||||
|
||||
assert pack_int(-44) == b'\x6B'
|
||||
assert pack_int(-45) == b'\x6C'
|
||||
assert pack_int(-46) == b'\x6D'
|
||||
|
||||
def test_pack_multi_byte_negative_ints():
|
||||
assert pack_int(-63) == b'\x7E'
|
||||
assert pack_int(-64) == b'\x7F'
|
||||
assert pack_int(-65) == b'\xC0\x01'
|
||||
|
||||
def test_pack_multi_byte_positive_and_negative():
|
||||
assert pack_int(-66663) == b'\xe6\x91\x08'
|
||||
assert pack_int(66663) == b'\xa7\x91\x08'
|
||||
|
||||
assert pack_int(-8866663) == b'\xe6\xad\xba\x08'
|
||||
assert pack_int(8866663) == b'\xa7\xad\xba\x08'
|
||||
|
||||
# TODO: should we just pack numbers bigger than 4 bytes?
|
||||
# since the official tw client and server are written in C++
|
||||
# they do not support such big numbers
|
||||
# we could also throw an error here instead
|
||||
def test_pack_too_big_positive_and_negative():
|
||||
assert pack_int(-98866996963) == b'\xe2\x9b\xf5\xce\xe0\x05'
|
||||
assert pack_int(98866996963) == b'\xa3\x9b\xf5\xce\xe0\x05'
|
||||
|
|
@ -1,45 +1,20 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
from textwrap import wrap
|
||||
|
||||
def dbg(raw: bytearray) -> None:
|
||||
bits_str = ''
|
||||
annotation_str = ''
|
||||
for byte in raw:
|
||||
bits_str += ' '.join(wrap(f"{byte:08b} ", 2))
|
||||
annotation_str += 'ES DD DD DD '
|
||||
print(f" {bits_str} {bytes(raw)!r}")
|
||||
print(f" {annotation_str}")
|
||||
|
||||
# TODO: optimize performance and benchmark in tests
|
||||
def pack_int(num: int) -> bytes:
|
||||
print(f"packing {num}")
|
||||
res: bytearray = bytearray(b'\x00')
|
||||
if num < 0:
|
||||
res[0] |= 0x40 # set sign bit
|
||||
print(f"num={num}")
|
||||
num = ~num
|
||||
# print(f"num num={num}")
|
||||
|
||||
# print("--- signed:")
|
||||
# dbg(res)
|
||||
|
||||
res[0] |= num & 0x3F # pack 6bit into res
|
||||
num >>= 6 # discard 6 bits
|
||||
|
||||
print("--- pack 6 bit:")
|
||||
dbg(res)
|
||||
|
||||
i = 0
|
||||
while num != 0:
|
||||
res[i] |= 0x80 # set extend bit
|
||||
i += 1
|
||||
res.extend(bytes([num & 0x7F])) # pack 7 bit
|
||||
num >>= 7 # discard 7 bits
|
||||
print(num)
|
||||
|
||||
return bytes(res)
|
||||
|
||||
print(pack_int(63))
|
||||
print(pack_int(64))
|
||||
print(pack_int(65))
|
||||
|
||||
|
|
Loading…
Reference in a new issue