Reference system for binary data encoding and decoding.

This module provides a reference system that allows for self-referential and circular data structures by deferring the resolution of values until encoding/decoding time. It includes:

  • Basic References: Defer value resolution using coders as keys
  • Computed References: Dynamic calculations based on multiple references
  • Context Integration: Seamless integration with the encoding/decoding context
  • Type Safety: Full TypeScript support with proper type inference
  • Circular Structure Support: Handle self-referential data structures

References are essential for complex binary formats where field lengths depend on other fields or where circular references are needed.

Examples

Example 1

import { assertEquals } from "@std/assert";
import { ref, computedRef, struct, u16le, u8, array } from "@hertzg/binstruct";

// Create references for shared lengths
const channelsLength = u16le();
const pointsLength = u16le();

// Define a structure with shared length references
const coder = struct({
  channelsLength: channelsLength,
  channels: struct({
    r: array(u8(), ref(channelsLength)),
    g: array(u8(), ref(channelsLength)),
    b: array(u8(), ref(channelsLength)),
  }),
  pointsLength: pointsLength,
  points: array(u16le(), ref(pointsLength)),
});

// Test data
const testData = {
  channelsLength: 3,
  channels: {
    r: [255, 128, 64],
    g: [0, 255, 128],
    b: [0, 0, 255],
  },
  pointsLength: 2,
  points: [100, 200],
};

// Encode and decode
const buffer = new Uint8Array(1000);
const bytesWritten = coder.encode(testData, buffer);
const [decoded, bytesRead] = coder.decode(buffer);

// Verify the data
assertEquals(decoded.channelsLength, testData.channelsLength);
assertEquals(decoded.channels.r, testData.channels.r);
assertEquals(decoded.channels.g, testData.channels.g);
assertEquals(decoded.channels.b, testData.channels.b);
assertEquals(decoded.pointsLength, testData.pointsLength);
assertEquals(decoded.points, testData.points);
assertEquals(bytesWritten, bytesRead);

Functions

f
isRef<T>(value: unknown): value is RefValue<T>

Checks if a value is a reference created by the ref function.

f
ref<TDecoded>(coder: Coder<TDecoded>): RefValue<TDecoded>

Creates a reference value that can be resolved during encoding/decoding.

f
refGetValue<T>(
ctx: Context | null | undefined,
refOrValue: RefValue<T> | NoInfer<T>
): NoInfer<T> | undefined

Retrieves the value from a reference or returns the value directly if it's not a reference.

f
refSetValue<T>(
ctx: Context | null | undefined,
coder: Coder<T>,
value: T
): void

Sets a value in the context for a specific coder reference.

f
withRefsInContext(ctx: Context): Context

Ensures that a context has the necessary reference storage initialized.

Interfaces

I
RefsWeakMap

A weak map interface for storing references in the encoding/decoding context.

Type Aliases

T
RefValue<TDecoded> = { (ctx: Context): TDecoded; [kIsRefValue]: true; }

A type representing a reference value that can be resolved during encoding/decoding.

Variables

v
kIsRefValue: symbol

Symbol identifier for reference values.