import logging import pathlib import struct import typing from . import dna_io, exceptions log = logging.getLogger(__name__) class BlendFileHeader: """ BlendFileHeader represents the first 12 bytes of a blend file. it contains information about the hardware architecture, which is relevant to the structure of the rest of the file. """ structure = struct.Struct(b'7s1s1s3s') def __init__(self, fileobj: typing.BinaryIO, path: pathlib.Path): log.debug("reading blend-file-header %s", path) header = fileobj.read(self.structure.size) values = self.structure.unpack(header) self.magic = values[0] pointer_size_id = values[1] if pointer_size_id == b'-': self.pointer_size = 8 elif pointer_size_id == b'_': self.pointer_size = 4 else: raise exceptions.BlendFileError('invalid pointer size %r' % pointer_size_id, path) endian_id = values[2] if endian_id == b'v': self.endian = dna_io.LittleEndianTypes self.endian_str = b'<' # indication for struct.Struct() elif endian_id == b'V': self.endian = dna_io.BigEndianTypes self.endian_str = b'>' # indication for struct.Struct() else: raise exceptions.BlendFileError('invalid endian indicator %r' % endian_id, path) version_id = values[3] self.version = int(version_id) def create_block_header_struct(self) -> struct.Struct: """Create a Struct instance for parsing data block headers.""" return struct.Struct(b''.join(( self.endian_str, b'4sI', b'I' if self.pointer_size == 4 else b'Q', b'II', )))