@bitruvius/codec-runtime
v0.3.2
Published
Bitruvius SDK codec runtime: capability-gated decode-backend selection and WebAssembly loading
Downloads
309
Readme
@bitruvius/codec-runtime
One decode policy for the Bitruvius wasm codecs: pick a backend the runtime can actually run, initialize the wasm once, speak one worker wire.
Internal building block. This package exists so that
@bitruvius/sdk-maplibreand the Bitruvius codecs can resolve their dependencies on npm. It has no standalone product story. Unless you are deliberately building against it, install the SDK instead.
Why it is its own package
A Bitruvius wasm codec answers the same three questions before it decodes a byte. Which backend can this runtime actually run? Where do the wasm bytes come from, and how do we avoid initializing them twice? What does a decode worker put on the wire?
Those answers must not vary by codec. requested: 'cpu-wasm' has to mean the
same thing everywhere, a browser without WebAssembly SIMD has to fail the same
way everywhere, and every decode worker has to speak the exact wire that
WorkerPool in @bitruvius/foundation correlates on, or the pool cannot match
a reply to its request.
The codecs themselves are peers, though. Each one ships its own WebAssembly module, so a codec that imported another codec just to borrow its backend selector would drag that codec's wasm payload into your bundle. The shared policy therefore lives here, in a package that has no codec of its own and no wasm to carry.
It also sits deliberately below the geospatial layer. Choosing a backend is a
decode-execution concern, not a geometry concern, so this package depends only
on @bitruvius/foundation and pulls in no geospatial types, no WebGL and no
DOM. That is what lets a raster codec and a point cloud codec share one
implementation.
What is in it
Three small pieces.
Backend selection
selectDecodeBackend() reconciles three inputs into one answer: the caller's
optional requested backend, the supportedBackends a codec actually
implements, and the detected runtime capabilities (SelectableCaps, which is
wasmSimd and workers).
import { selectDecodeBackend } from '@bitruvius/codec-runtime';
import { detectCapabilities } from '@bitruvius/foundation';
const backend = selectDecodeBackend({
supported: ['cpu-wasm-workers', 'cpu-wasm'],
caps: detectCapabilities(),
});
// 'cpu-wasm-workers' when workers exist, else 'cpu-wasm'An explicit request wins only when the codec supports it and the runtime can run
it. With no viable request, a codec that offers 'auto' gets it, since 'auto'
splits in-process against pool per call and so subsumes any static
recommendation. Failing that, the choice falls to foundation's
recommendDecodeBackend, clamped to the viable set, with single-thread
cpu-wasm as the last resort. The reserved GPU backends (webgl2-unpack,
webgpu-compute) are not implemented yet and never win, so a codec can name
them without lying to callers.
Missing SIMD throws instead of degrading quietly: the vendored wasm is built with
+simd128 and there is no non-SIMD build to fall back to.
wasm loading
resolveWasmInitArg() decides what to hand a wasm-bindgen init(): explicit
bytes first, then an explicit URL, then undefined so the bundler resolves the
.wasm sitting beside the JS glue. The explicit paths are what make cross-origin
CDN delivery, Node and Bun, and loading from inside a worker work at all, since
none of them can rely on that sibling lookup.
WasmCache.loadOnce(key, init) memoizes initialization per module key.
Concurrent callers share one in-flight promise, and a rejected init is evicted so
the next call retries rather than caching a permanent failure.
import { WasmCache, resolveWasmInitArg, type WasmSource } from '@bitruvius/codec-runtime';
import init from './my_codec_bg.js';
const cache = new WasmCache();
const ready = (src?: WasmSource) => cache.loadOnce('my-codec', () => init(resolveWasmInitArg(src)));Worker wire
WorkerRequest<T> and WorkerResponse<T>, with the isWorkerResponse and
isErrorResponse guards: the { __id, request } in, { __id, result } or
{ __id, error } out contract that foundation's WorkerPool dispatches against.
Centralized so codec workers and the pool cannot drift apart. These types are
internal to the SDK.
Who should depend on it
Applications should install @bitruvius/sdk-maplibre and never see this package.
Depend on it directly in one case: you are authoring a custom decoder backend.
selectDecodeBackend, WasmSource and WasmCache are the extension points for
that work.
npm i @bitruvius/codec-runtimeInside the SDK, @bitruvius/bvc uses selectDecodeBackend to choose among its
in-process, worker-pool and per-call 'auto' decoders.
Trademarks
MapLibre is a trademark of the MapLibre organization. All other marks are the property of their respective owners.
These names are used solely to identify the software this package interoperates with. WebGL is a trademark of The Khronos Group Inc.
Bitruvius is not affiliated with, sponsored by, or endorsed by any of them, and no such relationship is implied.
License
Proprietary. The full terms ship as LICENSE inside this package, and are readable
before installing at cdn.bitruvius.com/legal/sdk-license-v1.txt.
© Bitruvius, Inc.
