nx_zigzag_varint.nx
buildroot/runtime/nx_zigzag_varint.nx
about
nx_zigzag_varint.nx -- Protobuf zigzag encoding for signed integers.
Distinct from nx_zigzag.nx (JPEG/MPEG/H.264 8x8 DCT scan-order
primitive). Same word, completely different math. This one is the
Protobuf signed-integer compression scheme.
Problem: a naive varint encoding of a signed i64 wastes bytes on
small negative numbers. -1 encoded as two's complement i64 is
0xFFFFFFFFFFFFFFFF, which a 7-bit-continuation varint emits as 10
full bytes. Zigzag remaps signed integers so small absolute values
(positive OR negative) encode to small unsigned values:
0 -> 0 -1 -> 1 1 -> 2 -2 -> 3 2 -> 4 ...
The mapping is bit-twiddled: encode(n) = (n << 1) ^ (n >> 63).
(Note: this relies on >> being arithmetic-shift, which is correct
behaviour for the encoding step per the cardinal on shift-arith
in the parser-quirks meta-class memory.)
After zigzag, a varint of (encode(n)) emits 1 byte for |n| < 64,
2 bytes for |n| < 8192, etc. For game deltas that cluster near
zero (velocity changes, health deltas, small move offsets) this
saves ~50% of bytes on typical streams.
Composes with nx_state_delta_codec's varint codec to build a
world-class binary protocol for poor-internet multiplayer.
Source: developers.google.com/protocol-buffers/docs/encoding#signed-ints
Introduced by Google Protocol Buffers (Sanjay Ghemawat + Jeff Dean
2001), now a de-facto standard for binary protocols.
genealogy_id: protobuf_2001_zigzag_varint_encoding
lineage_id: signed_integer_compact_encoding
dependencies 2 imports · 1 importers
imports: nx_syscalls.nxnx_tier.nx
imported by: nx_state_delta_codec.nx
call flow from main pre-order; caps 40 nodes / depth 6 declared; ↻ = already shown
structs
| none |
consts
| 43 | const K_MAGIC_1000000: i64 = 1000000 |
| 44 | const K_MAGIC_2000000: i64 = 2000000 |
| 45 | const K_MAGIC_1999999: i64 = 1999999 |
functions
| 51 | func nx_zigzag_varint_encode(n: i64) -> i64 |
| 59 | func nx_zigzag_varint_decode(u: i64) -> i64 |
| 70 | func main() -> i64 |