This module provides a refinement system for binary structure coders. It allows you to transform decoded values into refined types and vice versa during encoding/decoding operations.

Examples

Example 1

import { assertEquals } from "@std/assert";
import { u8, refine } from "@hertzg/binstruct";

const bitfield = refine(u8(), {
  refine: (unrefined: number) =>
    unrefined.toString(2)
      .padStart(8, "0")
      .split("")
      .map(Number),
  unrefine: (refined) => parseInt(refined.join(""), 2),
});

const coder = bitfield();
const buffer = new Uint8Array(10);

const bytesWritten = coder.encode([1, 0, 1, 0, 1, 0, 1, 0], buffer);
const [decoded, bytesRead] = coder.decode(buffer);

assertEquals(bytesWritten, 1);
assertEquals(bytesRead, bytesWritten);
assertEquals(buffer[0], 0b10101010);
assertEquals(decoded, [1, 0, 1, 0, 1, 0, 1, 0]);

Example 2

import { assertEquals } from "@std/assert";
import { u8, refine } from "@hertzg/binstruct";
import type { Context } from "@hertzg/binstruct";

const u8Mapped = refine(u8(), {
  refine: (unrefined, _context, min: number, max: number) : number =>
    (min + (max - min) * unrefined / 0xff) >>> 0,
  unrefine: (refined, _context, min: number, max: number) => ((refined - min) / (max - min) * 0xff) >>> 0,
});

const coder = u8Mapped(-100, 100);
const buffer = new Uint8Array(100);

const bytesWritten = coder.encode(0, buffer);
const [decoded, bytesRead] = coder.decode(buffer);

assertEquals(bytesWritten, 1);
assertEquals(bytesRead, bytesWritten);
assertEquals(buffer[0], 0x7f);
assertEquals(decoded, 0);

Functions

Type Aliases

T
DecodedFields<TCoders extends FieldCoders> = [K in keyof TCoders]: TCoders[K] extends Coder<infer T> ? T : never

Mapped type extracting the decoded value type for each entry in a FieldCoders map. Given { payload: Coder<Ipv4> } it yields { payload: Ipv4 }.

T
FieldCoders = Record<string, Coder<any>>

Map of host field names to the sub-coder that decodes/encodes that field's bytes. Used as the input to refineFields.