ddn.encoding.rle
ddn.encoding.rle — run-length encoding, DDN-RLE/1 dialect.
Typed runs over uint/ulong elements. The byte dialect (M031, encodeUint32 and friends below) is a sequence of tokens: a varint header (count << 1) | kind — kind 0 RUN (one W-byte little-endian value repeated count times), kind 1 LITERAL (count values) — with the element width W ∈ {1,2,4,8} supplied by the caller, never carried in the stream. Design record: doc/DDN-ENCODING.md D20–D25.
This file's typed layer (run detection and bounded expansion) is usable independently of the byte codec.
Contract highlights: per-token commit atomicity with precise prefix reporting on capacity failure, checked count × W arithmetic, no allocation, no throwing (@nogc nothrow), CTFE.
Example:
import ddn.encoding.rle;
const uint[5] vals = [7, 7, 7, 8, 9];
assert(rle.runLengthAtUint32(vals[]) == 3);
uint[3] out_;
assert(rle.expandRunUint32(7, 3, out_[]).value == 3
&& out_[] == [7, 7, 7]);Types 2
Recoverable RLE failure with bounded context.
bytes/values carry the committed prefix at detection (INVALID_VALUE: values is the offending value index and bytes == 0).
Code codeWhich failure happened.size_t bytesBytes consumed when detected (encode prefix or decode input).size_t valuesValues written (or the offending index) when detected.CodeFailure classification.A decoded stream: values written and bytes consumed.
size_t valuesValues written to the destination.size_t bytesBytes consumed from the input (the whole stream on success).Functions 14
size_t runLengthAtUint32(scope const(uint)[] values) @safe pure nothrow @nogcLength of the run of equal values starting at `values[0]` (`≥ 1` for non-empty input; `0` for empty input).size_t runLengthAtUint64(scope const(ulong)[] values) @safe pure nothrow @nogcDitto (`ulong` elements).Result!(size_t, RleError) expandRunUint32(uint value, size_t count,
return scope uint[] dst) @safe pure nothrow @nogcWrites `count` copies of `value` into `dst` (bounded expansion).Result!(size_t, RleError) expandRunUint64(ulong value, size_t count,
return scope ulong[] dst) @safe pure nothrow @nogcDitto (`ulong` elements).size_t maxEncodedSize(size_t count, ubyte widthBytes) @safe pure nothrow @nogcMaximum byte length `encode*` can emit for `count` values at element width `widthBytes` (conservative: a varint header per token plus payload; greedy literals pair up, single values may stand alone...Result!(size_t, RleError) encodeUint32(scope const(uint)[] values,
ubyte widthBytes, return scope ubyte[] dst) @safe nothrow @nogcEncodes values into a `DDN-RLE/1` stream at element width `W`.Result!(size_t, RleError) encodeUint64(scope const(ulong)[] values,
ubyte widthBytes, return scope ubyte[] dst) @safe nothrow @nogcDitto (`ulong` elements; `W` in `{1,2,4,8}`).Result!(size_t, RleError) _encode(V)(
scope const(V)[] values, ubyte widthBytes, scope ubyte[] dst) static @safe nothrow @nogcsize_t _putValue(V)(scope ubyte[] dst, size_t at, V v,
ubyte widthBytes) static @safe nothrow @nogcResult!(RleDecoded, RleError) decodeUint32(scope const(ubyte)[] src,
ubyte widthBytes, return scope uint[] dst) @safe nothrow @nogcDecodes a whole `DDN-RLE/1` stream at element width `W`.Result!(RleDecoded, RleError) decodeUint64(scope const(ubyte)[] src,
ubyte widthBytes, return scope ulong[] dst) @safe nothrow @nogcDitto (`ulong` elements; `W` in `{1,2,4,8}`).Result!(RleDecoded, RleError) _decode(V)(
scope const(ubyte)[] src, ubyte widthBytes, scope V[] dst) static @safe nothrow @nogcVariables 1
maxTokenCount = 2_147_483_647