52 lines
1.4 KiB
Python
52 lines
1.4 KiB
Python
|
|
import json
|
||
|
|
from pathlib import Path
|
||
|
|
from typing import Dict, Any, Tuple
|
||
|
|
|
||
|
|
|
||
|
|
class GXLoaderError(Exception):
|
||
|
|
pass
|
||
|
|
|
||
|
|
|
||
|
|
class GXLoader:
|
||
|
|
MAGIC = b'XIC'
|
||
|
|
VERSION = 1
|
||
|
|
|
||
|
|
@staticmethod
|
||
|
|
def load_gx(path: str) -> Tuple[Dict[str, Any], bytes]:
|
||
|
|
try:
|
||
|
|
gx_file = Path(path)
|
||
|
|
if not gx_file.exists():
|
||
|
|
raise GXLoaderError(f"File not found: {path}")
|
||
|
|
|
||
|
|
data = gx_file.read_bytes()
|
||
|
|
|
||
|
|
if len(data) < 8:
|
||
|
|
raise GXLoaderError("File too short for GX header")
|
||
|
|
|
||
|
|
if data[:3] != GXLoader.MAGIC:
|
||
|
|
raise GXLoaderError("Invalid magic number")
|
||
|
|
|
||
|
|
version = data[3]
|
||
|
|
if version != GXLoader.VERSION:
|
||
|
|
raise GXLoaderError(f"Unsupported version: {version}")
|
||
|
|
|
||
|
|
manifest_len = int.from_bytes(data[4:8], 'big')
|
||
|
|
|
||
|
|
if len(data) < 8 + manifest_len:
|
||
|
|
raise GXLoaderError("Incomplete manifest")
|
||
|
|
|
||
|
|
manifest_json = data[8:8 + manifest_len]
|
||
|
|
compressed_payload = data[8 + manifest_len:]
|
||
|
|
|
||
|
|
manifest = json.loads(manifest_json.decode('utf-8'))
|
||
|
|
|
||
|
|
return manifest, compressed_payload
|
||
|
|
except GXLoaderError:
|
||
|
|
raise
|
||
|
|
except Exception as e:
|
||
|
|
raise GXLoaderError(f"Failed to load .gx file: {e}")
|
||
|
|
|
||
|
|
|
||
|
|
def load_gx(path: str) -> Tuple[Dict[str, Any], bytes]:
|
||
|
|
return GXLoader.load_gx(path)
|