Skip to content

Buffers & Typed Arrays

Fresh 🌱

For binary data, Neon exposes JavaScript ArrayBuffer, Buffer, and typed arrays. The modern API, JsTypedArray<T>, gives you a typed Rust slice view directly over the underlying memory, so you can read and write bytes without copying.

Creating buffers

The context constructs binary containers:

rust
let buffer = cx.buffer(1024)?;          // Node Buffer of 1024 bytes
let array_buffer = cx.array_buffer(256)?; // ArrayBuffer of 256 bytes

Idiomatic slice access with JsTypedArray

Instead of working with a generic JsArrayBuffer and manual locking, prefer a specific JsTypedArray<T> (for example JsTypedArray<u32>). It hands you a Rust slice you can use directly:

rust
// Read access: borrow an immutable slice
let b: Handle<JsTypedArray<u32>> = /* an argument or constructed value */;
let slice: &[u32] = b.as_slice(&cx);
let first = slice[0];

Reading and writing across two arrays

When you need to read from one buffer and write to another, take an immutable slice from the source and a mutable slice from the destination:

rust
let src_buf: Handle<JsTypedArray<u32>> = /* ... */;
let dst_buf: Handle<JsTypedArray<u32>> = /* ... */;

let lock = cx.lock();
let src = src_buf.as_slice(&lock).unwrap();
let dst = dst_buf.as_mut_slice(&lock).unwrap();

for (d, s) in dst.iter_mut().zip(src.iter()) {
    *d = *s * 2;
}

cx.lock() produces a lock that guarantees no JavaScript runs while you hold live slices, keeping the borrow safe.

Why typed arrays over raw ArrayBuffer

The older pattern required locking, borrowing the raw buffer, and casting bytes to a typed slice by hand:

rust
// Older, more verbose style
let b: Handle<JsArrayBuffer> = /* ... */;
{
    let guard = cx.lock();
    let data = b.borrow(&guard);
    let slice = data.as_slice::<u32>();
    // ...
}

The JsTypedArray<T> approach collapses that into a single as_slice(&cx) call with the element type known up front. Prefer it for new code.

When to use what

Data shapeUse
Arbitrary JS values in an arrayJsArray
Raw bytes / binary payloadscx.buffer() / cx.array_buffer()
Typed numeric data with slice accessJsTypedArray<T> (u8, u32, f64, ...)

Zero-copy is the win

Typed-array slices view the same memory JavaScript holds - there is no copy. That is what makes Neon attractive for image processing, audio, parsers, and other byte-heavy workloads.

Do not hold slices across JS calls

A borrowed slice is only valid while the lock is held and no JavaScript runs. Never stash a slice and call back into JS while you still hold it.