ddn.encoding.varint

ddn.encoding.varint — checked unsigned base-128 varints (LEB128).

Canonical little-endian base-128 encoding over caller-provided buffers: each byte carries 7 value bits, the high bit marks continuation. 32-bit values take 1–5 bytes (5th byte ≤ 0x0F), 64-bit values 1–10 (10th byte ≤ 0x01).

Contract highlights (design record doc/DDN-ENCODING.md):

  • Encode checks capacity first and is non-committing:

    on INSUFFICIENT_CAPACITY the output buffer is untouched.

  • Decode is strict-canonical: overlong encodings (trailing

    zero final byte where a shorter form exists) and payloads beyond the width are rejected, not silently accepted.

  • Errors are VarintError values in a ddn.result.Result:

    bounded context (the byte count examined when the failure was detected), no allocation, no throwing — @nogc nothrow throughout. TRUNCATED and INSUFFICIENT_CAPACITY are retryable; OVERLONG and OVERFLOW mean the data is wrong.

Signed integers: compose ZigZag with these functions (ddn.encoding.zigzag), the sint32/sint64 family — see the N009 notes in the design record.

Example:

import ddn.encoding.varint;

ubyte[10] buf;
auto r = varint.encodeUint64(300, buf[]);
assert(r.ok && r.value == 2 && buf[0 .. 2] == [0xAC, 0x02]);
auto d = varint.decodeUint64(buf[0 .. 2]);
assert(d.ok && d.value.value == 300 && d.value.length == 2);

Types 3

Recoverable varint failure with bounded context.

examined is the number of input bytes the decoder had consumed (encode: always 0 — the buffer is untouched) when the failure was detected. No strings, no pointers: the struct is returnable in @nogc nothrow contexts everywhere.

Fields
Code codeWhich failure happened.
size_t examinedBytes examined when the failure was detected.
Nested Templates
CodeFailure classification.
structVarint64

A decoded 64-bit varint: value plus bytes consumed.

Fields
ulong valueThe decoded value.
ubyte lengthBytes consumed from the input (1–10).
structVarint32

A decoded 32-bit varint: value plus bytes consumed.

Fields
uint valueThe decoded value.
ubyte lengthBytes consumed from the input (1–5).

Functions 6

fnubyte uint64Length(ulong v) @safe pure nothrow @nogcBytes `encodeUint64` needs for `v` (1–10).
fnubyte uint32Length(uint v) @safe pure nothrow @nogcBytes `encodeUint32` needs for `v` (1–5).
fnResult!(size_t, VarintError) encodeUint64(ulong v, return scope ubyte[] dst) @safe pure nothrow @nogcEncodes `v` as a canonical varint into `dst` (non-committing).
fnResult!(size_t, VarintError) encodeUint32(uint v, return scope ubyte[] dst) @safe pure nothrow @nogcEncodes `v` as a canonical varint into `dst` (non-committing).
fnResult!(Varint64, VarintError) decodeUint64(scope const(ubyte)[] src) @safe pure nothrow @nogcDecodes one canonical 64-bit varint from `src`.
fnResult!(Varint32, VarintError) decodeUint32(scope const(ubyte)[] src) @safe pure nothrow @nogcDecodes one canonical 32-bit varint from `src`.