././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1657326414.262237 kaitaistruct-0.10/0000755000175000017500000000000000000000000013222 5ustar00pppp00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1650053415.0 kaitaistruct-0.10/LICENSE0000777000175000017500000000206400000000000014240 0ustar00pppp00000000000000MIT License Copyright (c) 2015-2022 Kaitai Project Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1657326414.262237 kaitaistruct-0.10/PKG-INFO0000644000175000017500000000456000000000000014324 0ustar00pppp00000000000000Metadata-Version: 2.1 Name: kaitaistruct Version: 0.10 Summary: Kaitai Struct declarative parser generator for binary data: runtime library for Python Home-page: https://kaitai.io Author: Kaitai Project Author-email: greycat@kaitai.io License: MIT Keywords: kaitai,struct,construct,ksy,declarative,data structure,data format,file format,packet format,binary,parser,parsing,unpack,development Classifier: Development Status :: 4 - Beta Classifier: Intended Audience :: Developers Classifier: Topic :: Software Development :: Build Tools Classifier: License :: OSI Approved :: MIT License Classifier: Programming Language :: Python :: 2 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.4 Classifier: Programming Language :: Python :: 3.5 Classifier: Programming Language :: Python :: 3.6 Classifier: Programming Language :: Python :: 3.7 Classifier: Programming Language :: Python :: 3.8 Classifier: Programming Language :: Python :: 3.9 Classifier: Programming Language :: Python :: 3.10 Classifier: Programming Language :: Python :: Implementation :: CPython Classifier: Programming Language :: Python :: Implementation :: PyPy Requires-Python: !=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7 Description-Content-Type: text/markdown License-File: LICENSE # Kaitai Struct: runtime library for Python [![PyPI](https://img.shields.io/pypi/v/kaitaistruct)](https://pypi.org/project/kaitaistruct/) [![PyPI - Python Version](https://img.shields.io/pypi/pyversions/kaitaistruct)](https://pypi.org/project/kaitaistruct/#:~:text=Programming%20Language) This library implements Kaitai Struct API for Python. [Kaitai Struct](https://kaitai.io/) is a declarative language used for describe various binary data structures, laid out in files or in memory: i.e. binary file formats, network stream packet formats, etc. It is similar to [Python's Construct 2.10](https://construct.readthedocs.io/en/latest/) but it is language-agnostic. The format description is done in YAML-based .ksy format, which then can be compiled into a wide range of target languages. Further reading: * [About Kaitai Struct](https://kaitai.io/) * [About API implemented in this library](https://doc.kaitai.io/stream_api.html) * [Python-specific notes](https://doc.kaitai.io/lang_python.html) in KS documentation discuss installation and usage of this runtime ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1650011547.0 kaitaistruct-0.10/README.md0000777000175000017500000000206100000000000014507 0ustar00pppp00000000000000# Kaitai Struct: runtime library for Python [![PyPI](https://img.shields.io/pypi/v/kaitaistruct)](https://pypi.org/project/kaitaistruct/) [![PyPI - Python Version](https://img.shields.io/pypi/pyversions/kaitaistruct)](https://pypi.org/project/kaitaistruct/#:~:text=Programming%20Language) This library implements Kaitai Struct API for Python. [Kaitai Struct](https://kaitai.io/) is a declarative language used for describe various binary data structures, laid out in files or in memory: i.e. binary file formats, network stream packet formats, etc. It is similar to [Python's Construct 2.10](https://construct.readthedocs.io/en/latest/) but it is language-agnostic. The format description is done in YAML-based .ksy format, which then can be compiled into a wide range of target languages. Further reading: * [About Kaitai Struct](https://kaitai.io/) * [About API implemented in this library](https://doc.kaitai.io/stream_api.html) * [Python-specific notes](https://doc.kaitai.io/lang_python.html) in KS documentation discuss installation and usage of this runtime ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1657326414.2466109 kaitaistruct-0.10/kaitaistruct.egg-info/0000755000175000017500000000000000000000000017423 5ustar00pppp00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1657326413.0 kaitaistruct-0.10/kaitaistruct.egg-info/PKG-INFO0000644000175000017500000000456000000000000020525 0ustar00pppp00000000000000Metadata-Version: 2.1 Name: kaitaistruct Version: 0.10 Summary: Kaitai Struct declarative parser generator for binary data: runtime library for Python Home-page: https://kaitai.io Author: Kaitai Project Author-email: greycat@kaitai.io License: MIT Keywords: kaitai,struct,construct,ksy,declarative,data structure,data format,file format,packet format,binary,parser,parsing,unpack,development Classifier: Development Status :: 4 - Beta Classifier: Intended Audience :: Developers Classifier: Topic :: Software Development :: Build Tools Classifier: License :: OSI Approved :: MIT License Classifier: Programming Language :: Python :: 2 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.4 Classifier: Programming Language :: Python :: 3.5 Classifier: Programming Language :: Python :: 3.6 Classifier: Programming Language :: Python :: 3.7 Classifier: Programming Language :: Python :: 3.8 Classifier: Programming Language :: Python :: 3.9 Classifier: Programming Language :: Python :: 3.10 Classifier: Programming Language :: Python :: Implementation :: CPython Classifier: Programming Language :: Python :: Implementation :: PyPy Requires-Python: !=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7 Description-Content-Type: text/markdown License-File: LICENSE # Kaitai Struct: runtime library for Python [![PyPI](https://img.shields.io/pypi/v/kaitaistruct)](https://pypi.org/project/kaitaistruct/) [![PyPI - Python Version](https://img.shields.io/pypi/pyversions/kaitaistruct)](https://pypi.org/project/kaitaistruct/#:~:text=Programming%20Language) This library implements Kaitai Struct API for Python. [Kaitai Struct](https://kaitai.io/) is a declarative language used for describe various binary data structures, laid out in files or in memory: i.e. binary file formats, network stream packet formats, etc. It is similar to [Python's Construct 2.10](https://construct.readthedocs.io/en/latest/) but it is language-agnostic. The format description is done in YAML-based .ksy format, which then can be compiled into a wide range of target languages. Further reading: * [About Kaitai Struct](https://kaitai.io/) * [About API implemented in this library](https://doc.kaitai.io/stream_api.html) * [Python-specific notes](https://doc.kaitai.io/lang_python.html) in KS documentation discuss installation and usage of this runtime ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1657326414.0 kaitaistruct-0.10/kaitaistruct.egg-info/SOURCES.txt0000644000175000017500000000042500000000000021310 0ustar00pppp00000000000000LICENSE README.md kaitaistruct.py pyproject.toml setup.cfg setup.py kaitaistruct.egg-info/PKG-INFO kaitaistruct.egg-info/SOURCES.txt kaitaistruct.egg-info/dependency_links.txt kaitaistruct.egg-info/requires.txt kaitaistruct.egg-info/top_level.txt kaitaistruct.egg-info/zip-safe././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1657326414.0 kaitaistruct-0.10/kaitaistruct.egg-info/dependency_links.txt0000644000175000017500000000000100000000000023471 0ustar00pppp00000000000000 ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1657326414.0 kaitaistruct-0.10/kaitaistruct.egg-info/requires.txt0000644000175000017500000000004200000000000022017 0ustar00pppp00000000000000 [:python_version < "3.4"] enum34 ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1657326414.0 kaitaistruct-0.10/kaitaistruct.egg-info/top_level.txt0000644000175000017500000000001500000000000022151 0ustar00pppp00000000000000kaitaistruct ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1657326413.0 kaitaistruct-0.10/kaitaistruct.egg-info/zip-safe0000644000175000017500000000000100000000000021053 0ustar00pppp00000000000000 ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1657189010.0 kaitaistruct-0.10/kaitaistruct.py0000777000175000017500000004235600000000000016324 0ustar00pppp00000000000000import itertools import sys import struct from io import open, BytesIO, SEEK_CUR, SEEK_END # noqa PY2 = sys.version_info[0] == 2 # Kaitai Struct runtime version, in the format defined by PEP 440. # Used by our setup.cfg to set the version number in # packaging/distribution metadata. # Also used in Python code generated by older ksc versions (0.7 through 0.9) # to check that the imported runtime is compatible with the generated code. # Since ksc 0.10, the compatibility check instead uses the API_VERSION constant, # so that the version string does not need to be parsed at runtime # (see https://github.com/kaitai-io/kaitai_struct/issues/804). __version__ = '0.10' # Kaitai Struct runtime API version, as a tuple of ints. # Used in generated Python code (since ksc 0.10) to check that the imported # runtime is compatible with the generated code. API_VERSION = (0, 10) # pylint: disable=invalid-name,missing-docstring,too-many-public-methods # pylint: disable=useless-object-inheritance,super-with-arguments,consider-using-f-string class KaitaiStruct(object): def __init__(self, stream): self._io = stream def __enter__(self): return self def __exit__(self, *args, **kwargs): self.close() def close(self): self._io.close() @classmethod def from_file(cls, filename): f = open(filename, 'rb') try: return cls(KaitaiStream(f)) except Exception: # close file descriptor, then reraise the exception f.close() raise @classmethod def from_bytes(cls, buf): return cls(KaitaiStream(BytesIO(buf))) @classmethod def from_io(cls, io): return cls(KaitaiStream(io)) class KaitaiStream(object): def __init__(self, io): self._io = io self.align_to_byte() def __enter__(self): return self def __exit__(self, *args, **kwargs): self.close() def close(self): self._io.close() # ======================================================================== # Stream positioning # ======================================================================== def is_eof(self): if self.bits_left > 0: return False io = self._io t = io.read(1) if t == b'': return True io.seek(-1, SEEK_CUR) return False def seek(self, n): self._io.seek(n) def pos(self): return self._io.tell() def size(self): # Python has no internal File object API function to get # current file / StringIO size, thus we use the following # trick. io = self._io # Remember our current position cur_pos = io.tell() # Seek to the end of the stream and remember the full length full_size = io.seek(0, SEEK_END) # Seek back to the current position io.seek(cur_pos) return full_size # ======================================================================== # Integer numbers # ======================================================================== packer_s1 = struct.Struct('b') packer_s2be = struct.Struct('>h') packer_s4be = struct.Struct('>i') packer_s8be = struct.Struct('>q') packer_s2le = struct.Struct('H') packer_u4be = struct.Struct('>I') packer_u8be = struct.Struct('>Q') packer_u2le = struct.Struct('f') packer_f8be = struct.Struct('>d') packer_f4le = struct.Struct(' 0: # 1 bit => 1 byte # 8 bits => 1 byte # 9 bits => 2 bytes bytes_needed = ((bits_needed - 1) // 8) + 1 # `ceil(bits_needed / 8)` buf = self.read_bytes(bytes_needed) if PY2: buf = bytearray(buf) for byte in buf: res = res << 8 | byte new_bits = res res = res >> self.bits_left | self.bits << bits_needed self.bits = new_bits # will be masked at the end of the function else: res = self.bits >> -bits_needed # shift unneeded bits out mask = (1 << self.bits_left) - 1 # `bits_left` is in range 0..7 self.bits &= mask return res # Unused since Kaitai Struct Compiler v0.9+ - compatibility with # older versions. def read_bits_int(self, n): return self.read_bits_int_be(n) def read_bits_int_le(self, n): res = 0 bits_needed = n - self.bits_left if bits_needed > 0: # 1 bit => 1 byte # 8 bits => 1 byte # 9 bits => 2 bytes bytes_needed = ((bits_needed - 1) // 8) + 1 # `ceil(bits_needed / 8)` buf = self.read_bytes(bytes_needed) if PY2: buf = bytearray(buf) for i, byte in enumerate(buf): res |= byte << (i * 8) new_bits = res >> bits_needed res = res << self.bits_left | self.bits self.bits = new_bits else: res = self.bits self.bits >>= n self.bits_left = -bits_needed % 8 mask = (1 << n) - 1 # no problem with this in Python (arbitrary precision integers) res &= mask return res # ======================================================================== # Byte arrays # ======================================================================== def read_bytes(self, n): if n < 0: raise ValueError( "requested invalid %d amount of bytes" % (n,) ) is_satisfiable = True # When a large number of bytes is requested, try to check first # that there is indeed enough data left in the stream. # This avoids reading large amounts of data only to notice afterwards # that it's not long enough. For smaller amounts of data, it's faster to # first read the data unconditionally and check the length afterwards. if ( n >= 8*1024*1024 # = 8 MiB # in Python 2, there is a common error ['file' object has no # attribute 'seekable'], so we need to make sure that seekable() exists and callable(getattr(self._io, 'seekable', None)) and self._io.seekable() ): num_bytes_available = self.size() - self.pos() is_satisfiable = (n <= num_bytes_available) if is_satisfiable: r = self._io.read(n) num_bytes_available = len(r) is_satisfiable = (n <= num_bytes_available) if not is_satisfiable: # noinspection PyUnboundLocalVariable raise EOFError( "requested %d bytes, but only %d bytes available" % (n, num_bytes_available) ) # noinspection PyUnboundLocalVariable return r def read_bytes_full(self): return self._io.read() def read_bytes_term(self, term, include_term, consume_term, eos_error): r = b'' while True: c = self._io.read(1) if c == b'': if eos_error: raise Exception( "end of stream reached, but no terminator %d found" % (term,) ) return r if ord(c) == term: if include_term: r += c if not consume_term: self._io.seek(-1, SEEK_CUR) return r r += c def ensure_fixed_contents(self, expected): actual = self._io.read(len(expected)) if actual != expected: raise Exception( "unexpected fixed contents: got %r, was waiting for %r" % (actual, expected) ) return actual @staticmethod def bytes_strip_right(data, pad_byte): return data.rstrip(KaitaiStream.byte_from_int(pad_byte)) @staticmethod def bytes_terminate(data, term, include_term): new_data, term_byte, _ = data.partition(KaitaiStream.byte_from_int(term)) if include_term: new_data += term_byte return new_data # ======================================================================== # Byte array processing # ======================================================================== @staticmethod def process_xor_one(data, key): if PY2: return bytes(bytearray(v ^ key for v in bytearray(data))) return bytes(v ^ key for v in data) @staticmethod def process_xor_many(data, key): if PY2: return bytes(bytearray(a ^ b for a, b in zip(bytearray(data), itertools.cycle(bytearray(key))))) return bytes(a ^ b for a, b in zip(data, itertools.cycle(key))) @staticmethod def process_rotate_left(data, amount, group_size): if group_size != 1: raise Exception( "unable to rotate group of %d bytes yet" % (group_size,) ) anti_amount = -amount % (group_size * 8) r = bytearray(data) for i, byte in enumerate(r): r[i] = (byte << amount) & 0xff | (byte >> anti_amount) return bytes(r) # ======================================================================== # Misc # ======================================================================== @staticmethod def int_from_byte(v): return ord(v) if PY2 else v @staticmethod def byte_from_int(i): return chr(i) if PY2 else bytes((i,)) @staticmethod def byte_array_index(data, i): return KaitaiStream.int_from_byte(data[i]) @staticmethod def byte_array_min(b): return KaitaiStream.int_from_byte(min(b)) @staticmethod def byte_array_max(b): return KaitaiStream.int_from_byte(max(b)) @staticmethod def resolve_enum(enum_obj, value): """Resolves value using enum: if the value is not found in the map, we'll just use literal value per se. Works around problem with Python enums throwing an exception when encountering unknown value. """ try: return enum_obj(value) except ValueError: return value class KaitaiStructError(Exception): """Common ancestor for all error originating from Kaitai Struct usage. Stores KSY source path, pointing to an element supposedly guilty of an error. """ def __init__(self, msg, src_path): super(KaitaiStructError, self).__init__("%s: %s" % (src_path, msg)) self.src_path = src_path class UndecidedEndiannessError(KaitaiStructError): """Error that occurs when default endianness should be decided with switch, but nothing matches (although using endianness expression implies that there should be some positive result). """ def __init__(self, src_path): super(UndecidedEndiannessError, self).__init__("unable to decide on endianness for a type", src_path) class ValidationFailedError(KaitaiStructError): """Common ancestor for all validation failures. Stores pointer to KaitaiStream IO object which was involved in an error. """ def __init__(self, msg, io, src_path): super(ValidationFailedError, self).__init__("at pos %d: validation failed: %s" % (io.pos(), msg), src_path) self.io = io class ValidationNotEqualError(ValidationFailedError): """Signals validation failure: we required "actual" value to be equal to "expected", but it turned out that it's not. """ def __init__(self, expected, actual, io, src_path): super(ValidationNotEqualError, self).__init__("not equal, expected %s, but got %s" % (repr(expected), repr(actual)), io, src_path) self.expected = expected self.actual = actual class ValidationLessThanError(ValidationFailedError): """Signals validation failure: we required "actual" value to be greater than or equal to "min", but it turned out that it's not. """ def __init__(self, min_bound, actual, io, src_path): super(ValidationLessThanError, self).__init__("not in range, min %s, but got %s" % (repr(min_bound), repr(actual)), io, src_path) self.min = min_bound self.actual = actual class ValidationGreaterThanError(ValidationFailedError): """Signals validation failure: we required "actual" value to be less than or equal to "max", but it turned out that it's not. """ def __init__(self, max_bound, actual, io, src_path): super(ValidationGreaterThanError, self).__init__("not in range, max %s, but got %s" % (repr(max_bound), repr(actual)), io, src_path) self.max = max_bound self.actual = actual class ValidationNotAnyOfError(ValidationFailedError): """Signals validation failure: we required "actual" value to be from the list, but it turned out that it's not. """ def __init__(self, actual, io, src_path): super(ValidationNotAnyOfError, self).__init__("not any of the list, got %s" % (repr(actual)), io, src_path) self.actual = actual class ValidationExprError(ValidationFailedError): """Signals validation failure: we required "actual" value to match the expression, but it turned out that it doesn't. """ def __init__(self, actual, io, src_path): super(ValidationExprError, self).__init__("not matching the expression, got %s" % (repr(actual)), io, src_path) self.actual = actual ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1650009968.0 kaitaistruct-0.10/pyproject.toml0000777000175000017500000000015600000000000016147 0ustar00pppp00000000000000[build-system] requires = ["setuptools >= 38.6.0", "wheel >= 0.23.0"] build-backend = "setuptools.build_meta" ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1657326414.262237 kaitaistruct-0.10/setup.cfg0000777000175000017500000000301400000000000015050 0ustar00pppp00000000000000[metadata] name = kaitaistruct version = attr: kaitaistruct.__version__ author = Kaitai Project author_email = greycat@kaitai.io url = https://kaitai.io description = Kaitai Struct declarative parser generator for binary data: runtime library for Python long_description = file: README.md long_description_content_type = text/markdown license = MIT keywords = kaitai, struct, construct, ksy, declarative, data structure, data format, file format, packet format, binary, parser, parsing, unpack, development classifiers = Development Status :: 4 - Beta Intended Audience :: Developers Topic :: Software Development :: Build Tools License :: OSI Approved :: MIT License Programming Language :: Python :: 2 Programming Language :: Python :: 2.7 Programming Language :: Python :: 3 Programming Language :: Python :: 3.4 Programming Language :: Python :: 3.5 Programming Language :: Python :: 3.6 Programming Language :: Python :: 3.7 Programming Language :: Python :: 3.8 Programming Language :: Python :: 3.9 Programming Language :: Python :: 3.10 Programming Language :: Python :: Implementation :: CPython Programming Language :: Python :: Implementation :: PyPy [options] zip_safe = True include_package_data = True py_modules = kaitaistruct python_requires = >=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.* install_requires = enum34; python_version < "3.4" setup_requires = setuptools >= 38.6.0 wheel >= 0.23.0 [bdist_wheel] universal = 1 [pycodestyle] max-line-length = 140 statistics = True [egg_info] tag_build = tag_date = 0 ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1628934147.0 kaitaistruct-0.10/setup.py0000777000175000017500000000004600000000000014743 0ustar00pppp00000000000000from setuptools import setup setup()