import hashlib import zlib from typing import Tuple class GSZ3DecompressionError(Exception): pass class GSZ3Decompressor: MAGIC = b'GSZ3' VERSION = 1 @staticmethod def decompress(data: bytes) -> str: if len(data) < 12: raise GSZ3DecompressionError("Data too short for GSZ3 header") if data[:4] != GSZ3Decompressor.MAGIC: raise GSZ3DecompressionError("Invalid GSZ3 magic number") version = int.from_bytes(data[4:5], 'big') if version != GSZ3Decompressor.VERSION: raise GSZ3DecompressionError(f"Unsupported GSZ3 version: {version}") payload_len = int.from_bytes(data[5:9], 'big') stored_checksum = data[9:12] if len(data) < 12 + payload_len: raise GSZ3DecompressionError("Incomplete payload") payload = data[12:12 + payload_len] computed_checksum = GSZ3Decompressor._compute_checksum(payload) if computed_checksum != stored_checksum: raise GSZ3DecompressionError("Checksum mismatch") try: decompressed = zlib.decompress(payload) return decompressed.decode('utf-8') except (zlib.error, UnicodeDecodeError) as e: raise GSZ3DecompressionError(f"Decompression failed: {e}") @staticmethod def compress(text: str) -> bytes: data = text.encode('utf-8') compressed = zlib.compress(data, level=9) checksum = GSZ3Decompressor._compute_checksum(compressed) payload_len = len(compressed) header = GSZ3Decompressor.MAGIC header += bytes([GSZ3Decompressor.VERSION]) header += payload_len.to_bytes(4, 'big') header += checksum return header + compressed @staticmethod def _compute_checksum(data: bytes) -> bytes: h = hashlib.sha256(data).digest() return h[:3]