Реализация разбора двоичного формата данных
Не понимаю где я ошибся. Я реализовываю разбор двоичного формата данных. Использовал модуль 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}}
Буду благодарен за вашу помощь.