Реализация разбора двоичного формата данных

Не понимаю где я ошибся. Я реализовываю разбор двоичного формата данных. Использовал модуль struct. Данные начинаются с сигнатуры 0xf 0x48 0x4e 0x59, за которой следует структура A. Порядок байтов идёт от старшего к младшему. Адреса указаны в виде смещений от начала данных. В комментариях указал описания полей.

from struct import *

FMT = dict(
    char='c',
    int8='b',
    uint8='B',
    int16='h',
    uint16='H',
    int32='i',
    uint32='I',
    int64='q',
    uint64='Q',
    float='f',
    double='d',
)


def parse(buf, offs, ty):
    return unpack_from(FMT[ty], buf, offs)[0], offs + calcsize(FMT[ty])


def parse_a(buf, offs):

    # Размер (uint16) и адрес (uint16) массива адресов (uint32) структур B
    a1_size, offs = parse(buf, offs, 'uint16')
    a1_offs, offs = parse(buf, offs, 'uint32')
    a1 = []
    for _ in range(a1_size):
        val, a1_offs = parse_b(buf, a1_offs)
        a1.append(val)
    a1, a1_offs = parse(buf, a1_offs, 'uint16')

    # uint32
    a2, offs = parse(buf, offs, 'uint32')

    # Адрес (uint32) структуры D
    a3_offs, offs = parse(buf, offs, 'uint32')
    a3, a3_offs = parse_d(buf, a3_offs)

    # Размер (uint16) и адрес (uint16) массива char
    a4_size, offs = parse(buf, offs, 'uint16')
    a4_offs, offs = parse(buf, offs, 'uint16')
    a4 = []
    for _ in range(a4_size):
        val, a4_offs = parse(buf, a4_offs, 'char')
        a4.append(val.decode())

    # uint64
    a5, offs = parse(buf, offs, 'uint64')

    # Массив uint8, размер 8
    a6 = []
    for _ in range(8):
        val, offs = parse(buf, offs, 'uint8')
        a6.append(val)

    # Структура F
    a7, offs = parse_f(buf, offs)
    return dict(A1=a1, A2=a2, A3=a3, A4=''.join(a4), A5=a5, A6=a6, A7=a7), offs


def parse_b(buf, offs):

    # uint32
    b1, offs = parse(buf, offs, 'uint32')

    # Адрес (uint16) структуры C
    b2_offs, offs = parse(buf, offs, 'uint16')
    b2, b2_offs = parse_c(buf, b2_offs)
    return dict(B1=b1, B2=b2), offs


def parse_c(buf, offs):
    # uint64
    c1, offs = parse(buf, offs, 'uint64')
    # uint64
    c2, offs = parse(buf, offs, 'uint64')
    return dict(C1=c1, C2=c2), offs


def parse_d(buf, offs):
    # uint8
    d1, offs = parse(buf, offs, 'uint8')
    # Структура E
    d2, offs = parse_e(buf, offs)
    # Массив char, размер 4
    d3 = []
    for _ in range(4):
        val, offs = parse(buf, offs, 'char')
        d3.append(val)
    return dict(D1=d1, D2=d2, D3=d3), offs


def parse_e(buf, offs):
    # uint32
    e1, offs = parse(buf, offs, 'uint32')
    # double
    e2, offs = parse(buf, offs, 'double')
    return dict(E1=e1, E2=e2), offs


def parse_f(buf, offs):
    # float
    f1, offs = parse(buf, offs, 'float')
    # Массив double, размер 3
    f2 = []
    for _ in range(3):
        val, offs = parse(buf, offs, 'double')
        f2.append(val)
    # float
    f3, offs = parse(buf, offs, 'float')
    # float
    f4, offs = parse(buf, offs, 'float')
    # int16
    f5, offs = parse(buf, offs, 'int16')
    # double
    f6, offs = parse(buf, offs, 'double')
    # uint64
    f7, offs = parse(buf, offs, 'uint64')
    return dict(F1=f1, F2=f2, F3=f3, F4=f4, F5=f5, F6=f6, F7=f7), offs


def main(buf):
    return parse_a(buf, 4)[0]

# двоичные данные
buf = (b'\x0fHNY\x00\x02\x00\x86=\x97\xab6\x00\x00\x00\x8e\x00\x03\x00\x9f'
           b'\x1c\xdf\x8a\xdd\xc5\xcb+C\x84+\xa3\xae\xee\x8f\xd3k\xbc\xfa[\xa0'
           b'?\xd7\x8e\xa7|\xaaf\xa0\xbf\xdd\x86\xb4Vf\x9c\x98\xbf\xe0\xd8og\xfc\xa7t'
           b'?Q@\x99?\x1f\xe3\xfcO\xca?\xee_\x82k\x83"\x08\x0e\xa2\xdbs\x80\x03'
           b'\xfa\xb8\xe8\x16\xe0u$\xdd"~Ukd\xfa\xe3y\xd6e6M4\xa2\x00Z\x99N\xcc\x04'
           b'Tb\xcb`\xe8R\x13B\xd9\x13\xb7t\xf9`\xbb\xf4\x00p\x00\x00\x00j\x00\x00'
           b'\x00\x80h7\xffg\x19\xbf\xe0A\x86"2c\xa6igxigga')
print(main(buf))

При запуске я получаю следующую ошибку:

Traceback (most recent call last):
  File "C:\Users\ASUS\PycharmProjects\11\struct11.py", line 134, in <module>
    print(main(buf))
  File "C:\Users\ASUS\PycharmProjects\11\struct11.py", line 124, in main
    return parse_a(buf, 4)[0]
  File "C:\Users\ASUS\PycharmProjects\11\struct11.py", line 29, in parse_a
    val, a1_offs = parse_b(buf, a1_offs)
  File "C:\Users\ASUS\PycharmProjects\11\struct11.py", line 65, in parse_b
    b1, offs = parse(buf, offs, 'uint32')
  File "C:\Users\ASUS\PycharmProjects\11\struct11.py", line 19, in parse
    return unpack_from(FMT[ty], buf, offs)[0], offs + calcsize(FMT[ty])
struct.error: unpack_from requires a buffer of at least 2537391620 bytes for unpacking 4 bytes at offset 2537391616 (actual buffer size is 162)

Результат разбора, который я хочу по условию:

{'A1': [{'B1': 911029410,
         'B2': {'C1': 16723801060021183102, 'C2': 6155124344452929125}},
        {'B1': 4183866356,
         'B2': {'C1': 11046991254954101600, 'C2': 16740463942720272244}}],
 'A2': 1033349942,
 'A3': {'D1': 104,
        'D2': {'E1': 939484953, 'E2': -0.5079985301882644},
        'D3': 'igxi'},
 'A4': 'gga',
 'A5': 2080534237979290435,
 'A6': [132, 43, 163, 174, 238, 143, 211, 107],
 'A7': {'F1': -0.03056126832962036,
        'F2': [0.368081924194124, -0.46134670674877887, -0.5264203101153115],
        'F3': 0.8173919320106506,
        'F4': 0.6245725154876709,
        'F5': 20426,
        'F6': 0.949158868775215,
        'F7': 1054646551873583800}}

Буду благодарен за вашу помощь.


Ответы (0 шт):