diff --git a/osuRepy/frame.py b/osuRepy/frame.py index 5cd790b..8529c9b 100644 --- a/osuRepy/frame.py +++ b/osuRepy/frame.py @@ -35,6 +35,6 @@ class ReplayFrame: self._float_convert(self.x), self._float_convert(self.y), self.buttons) - + def __bytes__(self): return str(self).encode() diff --git a/osuRepy/helpers/typeSerializer.py b/osuRepy/helpers/typeSerializer.py index 1d5e199..709ab08 100644 --- a/osuRepy/helpers/typeSerializer.py +++ b/osuRepy/helpers/typeSerializer.py @@ -1,20 +1,21 @@ import struct -TYPE_CHAR = b"b" -TYPE_BYTE = b"B" -TYPE_BOOL = b"?" -TYPE_SHORT = b"h" -TYPE_USHORT = b"H" -TYPE_INT = b"i" -TYPE_UINT = b"I" -TYPE_LONG = b"l" -TYPE_ULONG = b"L" -TYPE_LLONG = b"q" -TYPE_ULLONG = b"Q" -TYPE_FLOAT = b"f" -TYPE_DOUBLE = b"d" -TYPE_STRING = b"B%ds" -TYPE_BYTESTREAM = b"%ds" +TYPE_CHAR = b"b", 1 +TYPE_BYTE = b"B", 1 +TYPE_BOOL = b"?", 1 +TYPE_SHORT = b"h", 2 +TYPE_USHORT = b"H", 2 +TYPE_INT = b"i", 4 +TYPE_UINT = b"I", 4 +TYPE_LONG = b"l", 4 +TYPE_ULONG = b"L", 4 +TYPE_LLONG = b"q", 8 +TYPE_ULLONG = b"Q", 8 +TYPE_FLOAT = b"f", 4 +TYPE_DOUBLE = b"d", 8 +TYPE_STRING = b"s", 1 + +TYPE_ULEB = 1 # Just so we have the enum type~ish BYTEORDER_NATIVE = b"@" BYTEORDER_LITTLE = b"<" @@ -22,7 +23,6 @@ BYTEORDER_BIG = b">" def encode_uleb(val): data = b"" - pos = 0 while val != 0: b = val & 0x7f val >>= 7 @@ -73,10 +73,18 @@ def guess_type(value): raise Exception("Unable to guess type") -class Serializable: - post_serialized = None +def read(value_type, stream): + #if value_type == TYPE_STRING: + # read() - def __init__(self, value, type = None, post = None): + struct.unpack(value_type[0], stream[:value_type[1]]) + +class Serializable: + length = None + prefix = b"" + pre_serialized = None + + def __init__(self, value, type = None, length = None, prefix = b"", pre = None): self.value = value if type is not None: @@ -84,29 +92,37 @@ class Serializable: else: self.type = guess_type(type) - self.post_serialized = post + self.length = length + self.prefix = prefix + self.pre_serialized = pre def get_struct_fmt(self): - if self.type in [TYPE_STRING, TYPE_BYTESTREAM]: - return self.type % len(self.get_value()[-1]) - return self.type + if self.length is not None: + return b"%d%b" % (self.length.value, self.type[0]) + return self.type[0] def get_value(self): - def _get_value(): - if self.type == TYPE_STRING: - return [0x0b, encode_uleb(len(self.value)) + self.value] - return [self.value] - - val = _get_value() - if self.post_serialized is not None: - val[-1] = self.post_serialized(val[-1]) - + val = self.value + if self.pre_serialized is not None: + val[-1] = self.pre_serialized(val[-1]) return val def pack(self, byte_order = BYTEORDER_LITTLE): + if self.type == TYPE_ULEB: + return encode_uleb(self.value) struct_fmt = byte_order + self.get_struct_fmt() - #print(struct_fmt, self.get_value()) - return struct.pack(struct_fmt, *self.get_value()) + packed = struct.pack(struct_fmt, self.get_value()) + if self.prefix is not None: + packed = self.prefix + packed + return packed + + def unpack(self, length = -1, byte_order = BYTEORDER_LITTLE): + if self.type == TYPE_ULEB: + self.value = decode_uleb(2) + return + if self.type == TYPE_STRING: + length = + struct_fmt = byte_order + self.get_struct_fmt(length) class Serializer: def __init__(self, byte_order = BYTEORDER_LITTLE): @@ -124,3 +140,21 @@ class Serializer: def __bytes__(self): return self.flush() + +class Deserializer: + def __init__(self, byte_order = BYTEORDER_LITTLE): + self.stack = [] + self.byte_order = byte_order + + def add(self, serializable): + if type(serializable) is list: + self.stack += serializable + else: + self.stack.append(serializable) + """ + def deserialize_data(self, stream): + pos = 0 + for s in self.stack: + struct. + s.value + """ \ No newline at end of file diff --git a/osuRepy/replay.py b/osuRepy/replay.py index 09a5463..c82317d 100644 --- a/osuRepy/replay.py +++ b/osuRepy/replay.py @@ -45,30 +45,35 @@ def lzma_compress(data): return struct.pack("