"""Models for the C99 Intel HEX parser. No Python parser fallback.""" import ctypes as ct from functools import lru_cache from protocan.native import _load_library class Cell(ct.Structure): _fields_ = [('address', ct.c_uint32), ('value', ct.c_uint8)] @lru_cache(maxsize=1) def library(): lib = _load_library() try: lib.firmware_hex_parse.argtypes = [ct.c_char_p, ct.c_size_t, ct.POINTER(Cell), ct.c_size_t, ct.c_size_t, ct.POINTER(ct.c_size_t), ct.POINTER(ct.c_size_t)] lib.firmware_hex_parse.restype = ct.c_int lib.firmware_hex_segment_size.argtypes = [ct.POINTER(Cell), ct.c_size_t, ct.c_size_t] lib.firmware_hex_segment_size.restype = ct.c_size_t except AttributeError as exc: raise RuntimeError('Rebuild SETProtocol: native firmware image API is missing') from exc return lib def parse_segments(text, max_records, error_type, segment_type): try: raw = bytes(text) if isinstance(text, (bytes, bytearray)) else str(text or '').encode('ascii') except UnicodeError as exc: raise error_type('Intel HEX должен состоять из ASCII') from exc if max_records < 1 or len(raw) > 64 * 1024 * 1024: raise error_type('Файл Intel HEX превышает допустимый размер') cells = (Cell * max(1, len(raw) // 2))() count, line = ct.c_size_t(), ct.c_size_t() lib = library() status = lib.firmware_hex_parse(raw, len(raw), cells, len(cells), max_records, ct.byref(count), ct.byref(line)) if status: messages = {1: 'неверный формат', 2: 'неверная checksum записи', 3: 'неизвестный тип или неверная длина записи', 4: 'нет данных/EOF или данные после записи EOF', 5: 'адрес описан повторно', 6: 'адрес выходит за uint32', 7: 'превышено допустимое число записей', 8: "запись должна начинаться с ':'", 9: 'запись содержит не пары HEX-символов', 10: 'длина записи не совпадает с полем count'} raise error_type('Intel HEX, строка %d: %s' % (line.value, messages.get(status, 'ошибка'))) result, offset = [], 0 while offset < count.value: size = lib.firmware_hex_segment_size(cells, count.value, offset) result.append(segment_type(cells[offset].address, bytes(cells[i].value for i in range(offset, offset + size)))) offset += size return result