Skip to content

writer

πŸ€– AI-Generated Content

This documentation was generated with AI assistance and is still being audited. Some, or potentially a lot, of this information may be inaccurate. Learn more.

flavor.psp.format_2025.writer

PSPF package writer for low-level binary serialization.

Classes

Functions

write_package

write_package(
    spec: BuildSpec,
    output_path: Path,
    slots: list[PreparedSlot],
    index: PSPFIndex,
    private_key: bytes,
    public_key: bytes,
) -> int

Write the complete package file.

Parameters:

Name Type Description Default
spec BuildSpec

Build specification

required
output_path Path

Path where package should be written

required
slots list[PreparedSlot]

Prepared slot data

required
index PSPFIndex

Package index (will be updated with offsets/sizes)

required
private_key bytes

Private key for signing

required
public_key bytes

Public key for verification

required

Returns:

Type Description
int

Total package size in bytes

Source code in flavor/psp/format_2025/writer.py
def write_package(
    spec: BuildSpec,
    output_path: Path,
    slots: list[PreparedSlot],
    index: PSPFIndex,
    private_key: bytes,
    public_key: bytes,
) -> int:
    """
    Write the complete package file.

    Args:
        spec: Build specification
        output_path: Path where package should be written
        slots: Prepared slot data
        index: Package index (will be updated with offsets/sizes)
        private_key: Private key for signing
        public_key: Public key for verification

    Returns:
        Total package size in bytes
    """
    # Ensure output directory exists
    ensure_parent_dir(output_path)

    # Load launcher
    launcher_data = _load_launcher(spec)

    # Process launcher for Windows PE compatibility if needed
    launcher_data = process_launcher_for_pspf(launcher_data)

    launcher_size = len(launcher_data)
    logger.trace("πŸš€πŸ“πŸ“‹ Launcher loaded and processed", size=launcher_size)

    # Create launcher info for metadata
    launcher_info = _create_launcher_info(launcher_data)

    # Update index with launcher size
    index.launcher_size = launcher_size

    # Create and compress metadata
    metadata = assemble_metadata(spec, slots, launcher_info)
    metadata_json = json_dumps(metadata, indent=2).encode("utf-8")
    metadata_compressed = gzip.compress(metadata_json, mtime=0)

    # Sign metadata
    signer = Ed25519Signer(private_key=private_key)
    signature = signer.sign(metadata_json)
    padded_signature = signature + b"\x00" * (512 - 64)
    index.integrity_signature = padded_signature

    # Write package file
    with output_path.open("wb") as f:
        # Write launcher
        f.write(launcher_data)
        f.seek(launcher_size)

        # Write compressed metadata
        _write_metadata(f, metadata_compressed, index)

        # Write slots if present
        if slots:
            _write_slots(f, slots, spec, index)

        # Write magic trailer
        _write_trailer(f, index)

        actual_size = f.tell()

    # Set executable permissions
    set_file_permissions(output_path, DEFAULT_EXECUTABLE_PERMS)

    return actual_size