function lazy
lazy<TDecoded>(factory: () => Coder<TDecoded>): Coder<TDecoded>

Wraps a coder factory so the coder it produces is built on first use instead of when lazy() is called, and only ever built once.

Use this to close mutually-recursive coder graphs — for example a tunneling protocol whose payload can itself contain the outer protocol (VXLAN carrying Ethernet carrying IPv4 carrying UDP carrying VXLAN again). Writing that graph with plain consts is impossible: whichever coder is declared last needs the first one, which is still in its temporal dead zone. Wrapping the back-reference in lazy(() => firstCoder) defers reading firstCoder until an encode/decode call actually happens, by which point every top-level const in the module has been assigned.

The factory is called at most once. Its result is cached and reused for every subsequent encode/decode on this lazy() coder, so building the inner coder graph (e.g. calling struct()/refineSwitch()) is not repeated per call.

Examples

Deferring construction until first use

import { assertEquals } from "@std/assert";
import { lazy } from "@hertzg/binstruct/lazy";
import { u16le } from "@hertzg/binstruct/numeric";

let builds = 0;
const coder = lazy(() => {
  builds++;
  return u16le();
});

assertEquals(builds, 0); // not built yet

const buffer = new Uint8Array(4);
coder.encode(513, buffer);
coder.decode(buffer);
coder.encode(7, buffer);

assertEquals(builds, 1); // built once, then memoized

Type Parameters

TDecoded

The type of the value the inner coder decodes to.

Parameters

factory: () => Coder<TDecoded>

Builds the inner coder. Called at most once, on first encode or decode.

Return Type

A Coder<TDecoded> that transparently delegates to the coder factory builds.