I'm trying to design a system to react to different binary flags.
0 = Error
1 = Okay
2 = Logging
3 = Number
The sequence of this data represents a unique ID to reference the work, the flag and the number. Everything works, except the number flag. This is what I get...
>>> import struct
>>> data = (1234, 3, 12345678)
>>> bin = struct.pack('QHL', *data)
>>> print(bin)
b'\xd2\x04\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00Na\xbc\x00\x00\x00\x00\x00'
>>> result = struct.unpack_from('QH', bin, 0)
>>> print(result)
(1234, 3)
>>> offset = struct.calcsize('QH')
>>> result += struct.unpack_from('L', bin, offset)
>>> print(result)
(1234, 3, 7011541669862440960)
A long should be plenty big to represent the number 12345678, but why is it incorrectly unpacked?
Edit:
When I try to pack them separately, it looks like struct is adding too many null bytes between the flag and the long.
>>> import struct
>>> struct.pack('QH', 1234, 3)
b'\xd2\x04\x00\x00\x00\x00\x00\x00\x03\x00'
>>> struct.pack('L', 12345678)
b'Na\xbc\x00\x00\x00\x00\x00'
I can reproduce this error by adding padding before the long.
>>> struct.unpack('L', struct.pack('L', 12345678))
(12345678,)
>>> struct.unpack('xL', struct.pack('xL', 12345678))
(12345678,)
>>> struct.pack('xL', 12345678)
b'\x00\x00\x00\x00\x00\x00\x00\x00Na\xbc\x00\x00\x00\x00\x00'
Potential fix?
When I use little-endian order, the problem seems to correct itself and make the binary string shorter. Since this is destined for a SSL wrapped TCP socket, that's a win win, right? Keeping bandwidth low is generally good, yes?
>>> import struct
>>> data = (1234, 3, 12345678)
>>> bin = struct.pack('<QHL', *data)
>>> print(bin)
b'\xd2\x04\x00\x00\x00\x00\x00\x00\x03\x00Na\xbc\x00'
>>> result = struct.unpack_from('<QH', bin, 0)
>>> print(result)
(1234, 3)
>>> offset = struct.calcsize('<QH')
>>> result += struct.unpack_from('<L', bin, offset)
>>> print(result)
(1234, 3, 12345678)
Why does this happen? I am perplexed.
hex(12345678)is0xbc614e, which looks quite different thanNa\xbc\x00\x00\x00\x00\x00. Why is that? What's the meaning ofNa?struct.pack('L', 65536*1024)gives\x00\x00\x00\x04\x00\x00\x00\x00, correctly (same order of magnitude as 12345678)bin()is a builtin function, which you hide by overwriting it.hex()returns an integer, whilestructreturns a byte string. If you take the bytes from0x00bc614eand align them in the proper way (=reversed) in a byte string like so:b'\x4e\x61\xbc\x00'then you get backb'Na\xbc\x00'. TheNais simply the ASCII-rendered version of\x4e\x61.