Merge implementations of read_exact functions/methods

The old functions/methods still exist, so that they continue to raise
the same exceptions as before (which are different depending on
context), but they now use the same implementation internally.
This commit is contained in:
dgelessus 2020-07-18 21:07:12 +02:00
parent 4bbf2f7c14
commit 476a68916b
3 changed files with 29 additions and 8 deletions

18
rsrcfork/_io_utils.py Normal file
View File

@ -0,0 +1,18 @@
"""A collection of utility functions and classes related to IO streams. For internal use only."""
import typing
def read_exact(stream: typing.BinaryIO, byte_count: int) -> bytes:
"""Read byte_count bytes from the stream and raise an exception if too few bytes are read (i. e. if EOF was hit prematurely).
:param stream: The stream to read from.
:param byte_count: The number of bytes to read.
:return: The read data, which is exactly ``byte_count`` bytes long.
:raise EOFError: If not enough data could be read from the stream.
"""
data = stream.read(byte_count)
if len(data) != byte_count:
raise EOFError(f"Attempted to read {byte_count} bytes of data, but only got {len(data)} bytes")
return data

View File

@ -8,6 +8,7 @@ import types
import typing
import warnings
from . import _io_utils
from . import compress
# The formats of all following structures is as described in the Inside Macintosh book (see module docstring).
@ -393,10 +394,10 @@ class ResourceFile(typing.Mapping[bytes, typing.Mapping[int, Resource]], typing.
def _read_exact(self, byte_count: int) -> bytes:
"""Read byte_count bytes from the stream and raise an exception if too few bytes are read (i. e. if EOF was hit prematurely)."""
data = self._stream.read(byte_count)
if len(data) != byte_count:
raise InvalidResourceFileError(f"Attempted to read {byte_count} bytes of data, but only got {len(data)} bytes")
return data
try:
return _io_utils.read_exact(self._stream, byte_count)
except EOFError as e:
raise InvalidResourceFileError(str(e))
def _stream_unpack(self, st: struct.Struct) -> tuple:
"""Unpack data from the stream according to the struct st. The number of bytes to read is determined using st.size, so variable-sized structs cannot be used with this method."""

View File

@ -2,6 +2,8 @@ import io
import struct
import typing
from .. import _io_utils
class DecompressError(Exception):
"""Raised when resource data decompression fails, because the data is invalid or the compression type is not supported."""
@ -182,10 +184,10 @@ def make_peekable(stream: typing.BinaryIO) -> "PeekableIO":
def read_exact(stream: typing.BinaryIO, byte_count: int) -> bytes:
"""Read byte_count bytes from the stream and raise an exception if too few bytes are read (i. e. if EOF was hit prematurely)."""
data = stream.read(byte_count)
if len(data) != byte_count:
raise DecompressError(f"Attempted to read {byte_count} bytes of data, but only got {len(data)} bytes")
return data
try:
return _io_utils.read_exact(stream, byte_count)
except EOFError as e:
raise DecompressError(str(e))
def read_variable_length_integer(stream: typing.BinaryIO) -> int: