mirror of
https://github.com/dgelessus/python-rsrcfork.git
synced 2025-02-08 11:30:26 +00:00
Add Resource.compressed_info attribute
This allows accessing a compressed resource's header data, without having to decompress it or parse the compressed data manually.
This commit is contained in:
parent
a23cd0fcb2
commit
868a322b8e
@ -96,7 +96,7 @@ class ResourceAttrs(enum.Flag):
|
||||
class Resource(object):
|
||||
"""A single resource from a resource file."""
|
||||
|
||||
__slots__ = ("type", "id", "name", "attributes", "data_raw", "_data_decompressed")
|
||||
__slots__ = ("type", "id", "name", "attributes", "data_raw", "_compressed_info", "_data_decompressed")
|
||||
|
||||
def __init__(self, resource_type: bytes, resource_id: int, name: typing.Optional[bytes], attributes: ResourceAttrs, data_raw: bytes):
|
||||
"""Create a new resource with the given type code, ID, name, attributes, and data."""
|
||||
@ -138,6 +138,22 @@ class Resource(object):
|
||||
warnings.warn(DeprecationWarning("The resource_id attribute has been deprecated and will be removed in a future version. Please use the id attribute instead."))
|
||||
return self.id
|
||||
|
||||
@property
|
||||
def compressed_info(self) -> typing.Optional[compress.common.CompressedHeaderInfo]:
|
||||
"""The compressed resource header information, or None if this resource is not compressed.
|
||||
|
||||
Accessing this attribute may raise a DecompressError if the resource data is compressed and the header could not be parsed. To access the unparsed header data, use the data_raw attribute.
|
||||
"""
|
||||
|
||||
if ResourceAttrs.resCompressed in self.attributes:
|
||||
try:
|
||||
return self._compressed_info
|
||||
except AttributeError:
|
||||
self._compressed_info = compress.common.CompressedHeaderInfo.parse(self.data_raw)
|
||||
return self._compressed_info
|
||||
else:
|
||||
return None
|
||||
|
||||
@property
|
||||
def data(self) -> bytes:
|
||||
"""The resource data, decompressed if necessary.
|
||||
@ -149,7 +165,7 @@ class Resource(object):
|
||||
try:
|
||||
return self._data_decompressed
|
||||
except AttributeError:
|
||||
self._data_decompressed = compress.decompress(self.data_raw)
|
||||
self._data_decompressed = compress.decompress_parsed(self.compressed_info, self.data_raw[self.compressed_info.header_length:])
|
||||
return self._data_decompressed
|
||||
else:
|
||||
return self.data_raw
|
||||
|
@ -19,6 +19,20 @@ DECOMPRESSORS = {
|
||||
}
|
||||
|
||||
|
||||
def decompress_parsed(header_info: CompressedHeaderInfo, data: bytes, *, debug: bool=False) -> bytes:
|
||||
"""Decompress the given compressed resource data, whose header has already been removed and parsed into a CompressedHeaderInfo object."""
|
||||
|
||||
try:
|
||||
decompress_func = DECOMPRESSORS[header_info.dcmp_id]
|
||||
except KeyError:
|
||||
raise DecompressError(f"Unsupported 'dcmp' ID: {header_info.dcmp_id}")
|
||||
|
||||
decompressed = decompress_func(header_info, data, debug=debug)
|
||||
if len(decompressed) != header_info.decompressed_length:
|
||||
raise DecompressError(f"Actual length of decompressed data ({len(decompressed)}) does not match length stored in resource ({header_info.decompressed_length})")
|
||||
return decompressed
|
||||
|
||||
|
||||
def decompress(data: bytes, *, debug: bool=False) -> bytes:
|
||||
"""Decompress the given compressed resource data."""
|
||||
|
||||
@ -27,12 +41,4 @@ def decompress(data: bytes, *, debug: bool=False) -> bytes:
|
||||
if debug:
|
||||
print(f"Compressed resource data header: {header_info}")
|
||||
|
||||
try:
|
||||
decompress_func = DECOMPRESSORS[header_info.dcmp_id]
|
||||
except KeyError:
|
||||
raise DecompressError(f"Unsupported 'dcmp' ID: {header_info.dcmp_id}")
|
||||
|
||||
decompressed = decompress_func(header_info, data[header_info.header_length:], debug=debug)
|
||||
if len(decompressed) != header_info.decompressed_length:
|
||||
raise DecompressError(f"Actual length of decompressed data ({len(decompressed)}) does not match length stored in resource ({header_info.decompressed_length})")
|
||||
return decompressed
|
||||
return decompress_parsed(header_info, data[header_info.header_length:], debug=debug)
|
||||
|
Loading…
x
Reference in New Issue
Block a user