diff --git a/hippolyzer/lib/base/llsd.py b/hippolyzer/lib/base/llsd.py index 7f211be..73a34d6 100644 --- a/hippolyzer/lib/base/llsd.py +++ b/hippolyzer/lib/base/llsd.py @@ -1,3 +1,4 @@ +import datetime import typing import zlib @@ -52,16 +53,93 @@ def format_notation(val: typing.Any): def format_binary(val: typing.Any, with_header=True): - val = llbase.llsd.format_binary(val) - if not with_header: - return val.split(b"\n", 1)[1] + val = _format_binary_recurse(val) + if with_header: + return b'\n' + val return val +# This is copied almost wholesale from https://bitbucket.org/lindenlab/llbase/src/master/llbase/llsd.py +# With a few minor changes to make serialization round-trip correctly. It's evil. +def _format_binary_recurse(something) -> bytes: + """Binary formatter workhorse.""" + def _format_list(something): + array_builder = [] + array_builder.append(b'[' + struct.pack('!i', len(something))) + for item in something: + array_builder.append(_format_binary_recurse(item)) + array_builder.append(b']') + return b''.join(array_builder) + + if something is None: + return b'!' + elif isinstance(something, LLSD): + return _format_binary_recurse(something.thing) + elif isinstance(something, bool): + if something: + return b'1' + else: + return b'0' + elif is_integer(something): + try: + return b'i' + struct.pack('!i', something) + except (OverflowError, struct.error) as exc: + raise LLSDSerializationError(str(exc), something) + elif isinstance(something, float): + try: + return b'r' + struct.pack('!d', something) + except SystemError as exc: + raise LLSDSerializationError(str(exc), something) + elif isinstance(something, uuid.UUID): + return b'u' + something.bytes + elif isinstance(something, binary): + return b'b' + struct.pack('!i', len(something)) + something + elif is_string(something): + if is_unicode(something): + something = something.encode("utf8") + return b's' + struct.pack('!i', len(something)) + something + elif isinstance(something, uri): + return b'l' + struct.pack('!i', len(something)) + something.encode("utf8") + elif isinstance(something, datetime.datetime): + return b'd' + struct.pack('