Files
altium-render-engine/backend/app/parser/record_decoder.py
T
nearology 56c5ee23d3
Verify / test (push) Failing after 2m54s
first commit
2026-11-05 17:31:17 +03:30

79 خطوط
2.8 KiB
Python

"""Bounds-checked property record reader; keeps physical indexes including binary records."""
import re
import base64
import struct
from dataclasses import dataclass
MAX_RECORDS = 100_000
MAX_RECORD_BYTES = 4 * 1024 * 1024
class ParseError(ValueError):
pass
@dataclass
class Record:
index: int
stream: str
properties: dict[str,str]
binary: bool = False
@property
def id(self):
return f'{self.stream}:{self.index}'
def properties(payload: bytes):
result = {}
# UTF8 companion fields take precedence irrespective of source order.
utf8 = {}
for item in payload.rstrip(b'\x00\r\n').split(b'|'):
if b'=' not in item:
continue
k,v = item.split(b'=',1)
key = k.decode('ascii',errors='replace').upper()
if key.startswith('%UTF8%'):
utf8[key[6:]] = v.decode('utf-8',errors='replace')
else:
result[key] = v.decode('cp1252',errors='replace')
result.update(utf8)
return result
def binary_records(data: bytes, stream: str):
offset=0
records=[]
while offset < len(data):
if len(records)>MAX_RECORDS:
raise ParseError('Record count limit exceeded')
if len(data)-offset<4:
if not any(data[offset:]): break
raise ParseError(f'{stream}: truncated length at byte {offset}')
word=struct.unpack_from('<I',data,offset)[0]
length, kind=word&0xffffff, word>>24
if not 0 < length <= MAX_RECORD_BYTES or length>len(data)-offset-4:
raise ParseError(f'{stream}: invalid record length {length} at byte {offset}')
payload=data[offset+4:offset+4+length]
# Header is outside OWNERINDEX numbering; first object is index zero.
records.append(Record(len(records)-1,stream,properties(payload) if kind==0 else {'BINARY_KIND':str(kind),'BINARY_BASE64':base64.b64encode(payload).decode('ascii')},kind!=0))
offset+=4+length
return records
def ascii_records(data: bytes):
lines=data.lstrip(b'\xef\xbb\xbf').splitlines()
records=[]
for line in lines:
if not line.strip(): continue
if len(line)>MAX_RECORD_BYTES: raise ParseError('Text record size limit exceeded')
if len(records)>MAX_RECORDS: raise ParseError('Record count limit exceeded')
p=properties(line)
if not p or not ('HEADER' in p or 'RECORD' in p):
raise ParseError('Malformed ASCII schematic record')
records.append(Record(len(records)-1,'FileHeader',p))
return records
def detect_format(data):
if data.startswith(b'\xd0\xcf\x11\xe0\xa1\xb1\x1a\xe1'): return 'ole'
if re.match(br'\|HEADER=',data.lstrip(b'\xef\xbb\xbf \r\n'),re.I): return 'ascii'
raise ParseError('Not a supported SchDoc: expected OLE container or |HEADER= ASCII schematic')