Files

96 lines
2.5 KiB
Python

import struct
class UnknownArgumentType(Exception):
pass
class PacketMissingArgument(Exception):
pass
def decode_args(types, data):
args = []
for argtype in types:
if argtype == "I":
elem, data = data[:4], data[4:]
result = struct.unpack(">I", elem)[0]
elif argtype == "S":
length = struct.unpack(">H", data[:2])[0]
result = data[2:2 + length].decode("utf-8", "ignore")
data = data[2 + length:]
elif argtype == "B":
length = struct.unpack(">H", data[:2])[0]
result = data[2:2 + length]
data = data[2 + length:]
elif argtype == "G":
result, data = data[:5], data[5:]
# Convert result (5 bytes) to a long. Can't use
# struct.unpack(">Q", "\x00"*3 + result), since we
# can't rely on "long long" being available.
high, low = struct.unpack(">BI", result)
result = (high << 32) + low
elif argtype == "i":
length = struct.unpack(">H", data[:2])[0]
result = struct.unpack(">%sI" % length, data[2:2 + 4 * length])
data = data[2 + 4 * length:]
elif argtype == "s":
length = struct.unpack(">H", data[:2])[0]
data = data[2:]
result = []
while length:
slength = struct.unpack(">H", data[:2])[0]
result.append(data[2:2 + slength].decode("utf-8"))
data = data[2 + slength:]
length -= 1
else:
raise UnknownArgumentType(argtype)
args.append(result)
return args
def encode_args(types, args):
data = b""
for argtype in types:
if not args:
raise PacketMissingArgument
it = args[0]
del args[0]
if argtype == "I":
data += struct.pack(">I", it)
elif argtype == "S":
encoded = it.encode("utf-8")
data += struct.pack(">H", len(encoded))
data += encoded
elif argtype == "G":
data += struct.pack(">BI", it >> 32, it & 0xffffffff)
elif argtype == "s":
data += struct.pack(">H", len(it))
for it_elem in it:
encoded = it_elem.encode("utf-8")
data += struct.pack(">H", len(encoded))
data += encoded
else:
raise UnknownArgumentType(argtype)
return data
class Packet:
pass