Core buffers

@webbuf/webbuf

Rust/WASM optimized buffers

Install

npm install @webbuf/webbuf

Usage

import { WebBuf } from "@webbuf/webbuf";

// Create from various sources
const backing = new Uint8Array([0xee, 72, 105, 0xff]);
const selected = WebBuf.view(backing.subarray(1, 3));
new TextDecoder().decode(selected.bytes); // "Hi", not the sentinels
const shared = selected.subarray(0, 1);
const copied = selected.slice(0, 1);
shared.bytes[0] = 66;
selected.toUtf8(); // "Bi": subarray shares storage
copied.toUtf8(); // "H": slice owns a copy
selected instanceof Uint8Array; // false
ArrayBuffer.isView(selected); // false

// Copy only a DataView's selected raw bytes, excluding sentinels
const nativeBytes = new Uint8Array([0xee, 1, 2, 3, 0xff]);
const viewCopy = WebBuf.fromArrayBufferView(
  new DataView(nativeBytes.buffer, 1, 3),
);
nativeBytes.fill(0);
if (viewCopy.toHex() !== "010203")
  throw new Error("Expected copied view bytes");

const buf1 = WebBuf.alloc(32);
const buf2 = WebBuf.fromHex("deadbeef");
const buf3 = WebBuf.fromBase64("SGVsbG8=");
const buf4 = WebBuf.fromUtf8("Hello, world!");
const buf5 = WebBuf.fromArray([1, 2, 3, 4]);

// Ordinary byte predicates, not timing-safe secret comparisons
if (!buf1.isZero() || !WebBuf.alloc(0).isZero())
  throw new Error("Expected zero buffers");
if (buf2.isZero()) throw new Error("Expected nonzero bytes");

// Convert to strings
buf2.toHex(); // "deadbeef"
buf3.toBase64(); // "SGVsbG8="
buf4.toUtf8(); // "Hello, world!"

// Buffer operations
const combined = WebBuf.concat([buf1, buf2]);
const cloned = buf1.clone();
const reversed = buf1.toReverse();

// Comparison
buf1.equals(buf2); // false
buf1.compare(buf2); // -1, 0, or 1

// Numeric serialization does not depend on native array endianness.
const words = new Uint32Array([0x01234567, 0x89abcdef]);
const wordBytes = WebBuf.fromUint32ArrayBE(words);
if (wordBytes.toHex() !== "0123456789abcdef")
  throw new Error("BE word bytes differ");
if (WebBuf.fromUint16ArrayLE(new Uint16Array([0x1234])).toHex() !== "3412")
  throw new Error("LE word bytes differ");
const exact64 = 0x0123456789abcdefn;
if (
  WebBuf.fromBigUint64ArrayLE(
    new BigUint64Array([exact64]),
  ).toBigUint64ArrayLE()[0] !== exact64
)
  throw new Error("Lost 64-bit precision");
if (wordBytes.toUint32ArrayBE()[1] !== 0x89abcdef)
  throw new Error("Word decoding differs");

// Strict Base64url; selectors use the same unpadded output policy.
const urlBytes = WebBuf.fromBase64Url("-_8=");
if (urlBytes.toBase64Url() !== "-_8") throw new Error("Expected no padding");
if (urlBytes.toBase64Url(true) !== "-_8=") throw new Error("Expected padding");
if (WebBuf.from("-_8", "base64url").toString("base64url") !== "-_8")
  throw new Error("Selector mismatch");
if (WebBuf.fromString("-_8", "base64url").toHex() !== "fbff")
  throw new Error("Decoded bytes differ");

WebBuf 4 byte access

WebBuf 4.0.0 was released with this composition-based API, together with all 31 WebBuf npm libraries. WebBuf has a Uint8Array; it is not a Uint8Array. Use buf.bytes[i] for indexed access and pass buf.bytes to TextDecoder, Web Crypto, Node Buffer and WASM. The wrapper itself is not a native BufferSource.

The bytes property is readonly in TypeScript, but its contents are mutable. Native views preserve the selected byte offset and length. Iteration, length, byteLength, byteOffset, buffer and named encoding helpers remain available.

view, subarray and read share selected storage; slice, clone and fromUint8Array copy. Constructing from an ArrayBuffer views it; constructing from an array or iterable copies it. from without a mapper shares native-array or WebBuf input, while a mapper produces a copy.

Stored bytes use ordinary ArrayBuffer backing. SharedArrayBuffer views cannot be wrapped: explicitly copy them with fromUint8Array(sharedView) or new WebBuf(sharedView). Wrapping a Node Buffer produces a plain Uint8Array view of its selected storage without copying.

API reference (3 exports)

Classes

WebBuf

class
constructor(source?: number | ArrayBuffer | ArrayLike<number> | Iterable<number>, byteOffset?: number, length?: number): WebBuf
static concat(list: (Uint8Array | WebBuf)[]): WebBuf
static alloc(size: number, fill?: number): WebBuf
static view(buffer: Uint8Array | WebBuf): WebBuf
static fromUint8Array(buffer: Uint8Array): WebBuf
static fromArrayBufferView(view: ArrayBufferView): WebBuf
static fromArray(array: number[]): WebBuf
static fromUint16ArrayBE(values: Uint16Array): WebBuf
static fromUint16ArrayLE(values: Uint16Array): WebBuf
static fromUint32ArrayBE(values: Uint32Array): WebBuf
static fromUint32ArrayLE(values: Uint32Array): WebBuf
static fromBigUint64ArrayBE(values: BigUint64Array): WebBuf
static fromBigUint64ArrayLE(values: BigUint64Array): WebBuf
static fromUtf8(str: string): WebBuf
static fromString(str: string, encoding?: "utf8" | "hex" | "base64" | "base64url"): WebBuf
static FROM_BASE64_ALGO_THRESHOLD: number
static TO_BASE64_ALGO_THRESHOLD: number
static FROM_HEX_ALGO_THRESHOLD: number
static TO_HEX_ALGO_THRESHOLD: number
static fromHexPureJs(hex: string): WebBuf
static fromHexWasm(hex: string): WebBuf
static fromHex(hex: string): WebBuf
static fromBase64PureJs(b64: string, stripWhitespace?: boolean): WebBuf
static fromBase64Wasm(b64: string, stripWhitespace?: boolean): WebBuf
static fromBase64(b64: string, stripWhitespace?: boolean): WebBuf
static fromBase64Url(text: string, stripWhitespace?: boolean): WebBuf
static fromBase64UrlPureJs(text: string, stripWhitespace?: boolean): WebBuf
static fromBase64UrlWasm(text: string, stripWhitespace?: boolean): WebBuf
static fromBase32(str: string, options?: Base32Options): WebBuf
static from(source: ArrayLike<number> | Iterable<number> | string, mapFn?: ((v: number, k: number) => number) | string, thisArg?: unknown): WebBuf
static compare(buf1: WebBuf, buf2: WebBuf): number
readonly bytes: Uint8Array<ArrayBuffer>
readonly length: number
readonly byteLength: number
readonly byteOffset: number
readonly buffer: ArrayBuffer
[Symbol.iterator](): IterableIterator<number>
set(source: ArrayLike<number> | WebBuf, offset?: number): void
fill(value: number, start?: number, end?: number): WebBuf
slice(start?: number, end?: number): WebBuf
subarray(start?: number, end?: number): WebBuf
reverse(): WebBuf
clone(): WebBuf
toReverse(): WebBuf
copy(target: WebBuf, targetStart?: number, sourceStart?: number, sourceEnd?: number): number
toUint16ArrayBE(): Uint16Array<ArrayBuffer>
toUint16ArrayLE(): Uint16Array<ArrayBuffer>
toUint32ArrayBE(): Uint32Array<ArrayBuffer>
toUint32ArrayLE(): Uint32Array<ArrayBuffer>
toBigUint64ArrayBE(): BigUint64Array<ArrayBuffer>
toBigUint64ArrayLE(): BigUint64Array<ArrayBuffer>
toHexPureJs(): string
toHexWasm(): string
toHex(): string
toBase64Url(padding?: boolean): string
toBase64UrlPureJs(padding?: boolean): string
toBase64UrlWasm(padding?: boolean): string
toBase64PureJs(): string
toBase64Wasm(): string
toBase64(): string
toBase32(options?: Base32Options): string
toUtf8(): string
toString(encoding?: "utf8" | "hex" | "base64" | "base64url"): string
inspect(): string
toArray(): number[]
compare(other: WebBuf): number
equals(other: WebBuf): boolean
isZero(): boolean
write(buf: WebBuf, offset?: number): number
read(offset: number, ext: number): WebBuf
wipe(): void

Interfaces

Base32Options

interface

Options for base32 encoding/decoding

alphabet?: Base32Alphabet
padding?: boolean

Type aliases

Base32Alphabet

type

Base32 alphabet types matching the Rust base32 crate

type Base32Alphabet = "Crockford" | "Rfc4648" | "Rfc4648Hex" | "Rfc4648HexLower" | "Rfc4648Lower" | "Z"