# Buffer helpers

Lightweight helpers for encoding/decoding JSON to/from binary (Uint8Array / ArrayBuffer / Node Buffer).

`powerBuffer` provides tiny, allocation-friendly helpers optimized for passing JSON payloads through transferable binary buffers (for example, when posting messages to Workers). It prefers zero-copy views for ArrayBuffer/TypedArray inputs and falls back to `TextEncoder`/`TextDecoder` (or Node `Buffer`) when available.

## o2u8(obj)

Encode a value to a `Uint8Array` (UTF-8 JSON).

- `obj` — Any value to encode. If the value is already a `Uint8Array`/TypedArray/ArrayBuffer it will be returned or converted to a view.

Returns: `Uint8Array` — UTF-8 encoded bytes. Throws if no encoder is available in the environment.

Example

```javascript
import { o2u8, u82o } from 'performance-helpers/powerBuffer';

// encode a JSON payload to transferable Uint8Array and post to a worker
const payload = { id: 42, name: 'big-image', meta: { size: 1024 * 1024 } };
const bytes = o2u8(payload);
// `bytes.buffer` can be transferred to a Worker to avoid structured-clone copies
worker.postMessage(bytes, [bytes.buffer]);
```

## u82o(buf)

Decode a binary buffer (Uint8Array/ArrayBuffer/Buffer) containing JSON UTF-8 to a JS value.

- `buf` — The binary input to decode. Accepted types: `Uint8Array`, `ArrayBuffer`, TypedArray, or Node `Buffer`.

Returns: parsed JS value. Throws `TypeError` for unsupported input types or malformed UTF-8 JSON.

Example — worker receiver

```javascript
import { u82o } from 'performance-helpers/powerBuffer';

self.onmessage = (e) => {
  // decode transferable Uint8Array back to JS value
  const obj = u82o(e.data);
  // process obj
};
```

> **Receiving from `PowerPool`?** These helpers encode and decode a _bare_ JSON body.
> Since 2.0 `PowerPool` wraps that body in a [`PowerMessageCodec`](powerMessageCodec.md) frame,
> so a worker should use `decodeMessage(e.data).value` instead of `u82o(e.data)`. `o2u8`/`u82o`
> remain the right tools for your own transports, and are what the codec's `json` payload codec
> is built on. See
> [Migrating to the framed protocol](powerPool.md#migrating-to-the-framed-protocol-breaking-change-in-20).

## o2b(obj)

Encode to an `ArrayBuffer` (legacy API). Returns an owning ArrayBuffer (slice if necessary).

Parameters: same as `o2u8`.

Returns: `ArrayBuffer`.

## b2o(buf)

Legacy wrapper around `u82o` for ArrayBuffer/TypedArray/Buffer.

## Recommendations

- Use `o2u8`/`u82o` when sending/receiving structured JSON through `postMessage` to make use of transferables and reduce copy overhead.

```javascript
// worker.js
self.onmessage(e => {
    const json_input = u82o(e.data);
    ...
    const output = o2u8(json_output);
    self.postMessage(output, [output.buffer])
})
```

```javascript
// worker.js
self.onmessage = (e) => {
  const jsonInput = u82o(e.data);
  const result = process(jsonInput);
  const out = o2u8(result);
  self.postMessage(out, [out.buffer]);
};

// main thread
worker.onmessage = (e) => {
  const jsonOut = u82o(e.data);
  handleResult(jsonOut);
};
```

## PowerBufferPool

A pool of reusable `Uint8Array` buffers, keyed by size bucket, for hot encode/decode paths.

```javascript
import { PowerBufferPool } from 'performance-helpers/powerBuffer';

const pool = new PowerBufferPool({ buckets: [256, 1024, 4096], maxPerBucket: 16 });
const buf = pool.acquire(100); // Uint8Array, byteLength >= 100 (256 bucket)
// ... use buf ...
pool.release(buf); // returns true when retained
pool.dispose();
```

- `acquire(size)` returns a `Uint8Array` whose `byteLength` is at least `size`. Reused buffers are zeroed before return.
- `release(buf)` returns `true` when the buffer is retained, `false` when dropped (non-matching size, pool full, or disposed).
- A buffer must not be used after `release()` — the pool may hand the same memory to another caller.
- `stats()` reports `pooled`, `acquires`, `reuses`, `releases`, `drops`, `reuseRate`.
- Implements `dispose()`, `[Symbol.dispose]`, `[Symbol.asyncDispose]`.

## Cleanup with `using`

`PowerBuffer` implements `Symbol.dispose` / `Symbol.asyncDispose`:

```javascript
{
  using buf = new PowerBuffer(1024);
  buf.write(new Uint8Array([1, 2, 3]));
} // buf.dispose() runs here
```
