import enum
from restruct import Struct, Processed, parse


class BType(enum.Enum):
    Dict = 1
    Array = 2
    Int = 4
    String = 9
    Null = 11

class BDictElem(Struct, generics={'T'}):
    key:   T
    value: T

Byteswap = lambda x, n: Processed(x,
    parse=lambda v: int.from_bytes(v.to_bytes(n, byteorder='big'), byteorder='little'),
    emit= lambda v: int.from_bytes(v.to_bytes(n, byteorder='big'), byteorder='little'),
)

class BElem(Struct, partials={'T', 'SA', 'SI', 'SS'}, recursive=True):
    size:  Byteswap(Bits(24), 3) @ SA.count @ SI.bits @ SS.length
    type:  Enum(BType, Bits(7)) @ T.selector
    last:  Bool(Bits(1))
    value: Switch(options={
        BType.Dict:   Arr(BDictElem[Self]) @ SA,
        BType.Array:  Arr(Self) @ SA,
        BType.Int:    UInt() @ SI,
        BType.String: AlignTo(Str(type='raw') @ SS, 4),
    }) @ T

class BList(Struct):
    size: UInt(32)
    root: BElem


print(parse(BList, bytes.fromhex("""
d3 00 00 00
04 00 00 81
    06 00 00 09 47 6c 6f 62 61 6c 02 00
    02 00 00 01
        05 00 00 09 77 69 64 74 68 01 00 00
        40 00 00 04 80 07 00 00 00 00 00 00
        06 00 00 09 68 65 69 67 68 74 02 00
        40 00 00 84 38 04 00 00 00 00 00 00
""")))