from __future__ import annotations

import struct
from typing import Tuple


class VarIntDecodeError(ValueError):
    pass


def pack_varint(val: int) -> bytes:
    result = bytearray()
    while True:
        byte = val & 0x7F
        val >>= 7
        if val != 0:
            byte |= 0x80
        result.append(byte)
        if val == 0:
            break
    return bytes(result)


def unpack_varint(data: bytes, offset: int = 0) -> Tuple[int, int]:
    result = 0
    shift = 0
    while True:
        if offset >= len(data):
            raise VarIntDecodeError("VarInt data incomplete")
        byte = data[offset]
        offset += 1
        result |= (byte & 0x7F) << shift
        if (byte & 0x80) == 0:
            break
        shift += 7
        if shift >= 35:
            raise VarIntDecodeError("VarInt too large")
    return result, offset
