Source code for sofab._varint
"""Varint (base-128 LE) encoding and the ZigZag mapping — the hot path.
This module is deliberately small and free of higher-level concepts so it can
later be replaced by a compiled accelerator (mypyc/Cython, or a PyO3 binding
over ``corelib-rs``) without touching the public API. Keep the signatures
stable.
It holds the **encode** half only. Decoding a varint means advancing a cursor
over a refillable buffer, so each engine inlines the codec into its own decode
loops (``Decoder._varint`` / ``Decoder._read_varints``, and their C twins in
``_speedups``); a byte-at-a-time decoder here would be a third copy of §4.1 that
no shipped path can reach, kept in sync by hand (issue #75).
"""
from __future__ import annotations
from .types import MASK64
[docs]
def zigzag_encode(v: int) -> int:
"""Map a signed int to unsigned: ``(n << 1) ^ (n >> 63)`` (64-bit)."""
return ((v << 1) ^ (v >> 63)) & MASK64
[docs]
def zigzag_decode(u: int) -> int:
"""Inverse of :func:`zigzag_encode`: ``(z >> 1) ^ -(z & 1)``."""
return (u >> 1) ^ -(u & 1)
def encode_varint(value: int) -> bytes:
"""Encode an unsigned 64-bit value as a base-128 little-endian varint.
Matches the C ``_varint_encode`` do/while loop: ``0`` encodes to a single
``0x00`` byte.
"""
out = bytearray()
while True:
byte = value & 0x7F
value >>= 7
if value:
out.append(byte | 0x80)
else:
out.append(byte)
return bytes(out)