⚡Extremely Fast Way to Work with Binary Data - Flash Buffer for TypeScript

typescript dev.to

Speed ​​up binary I/O with zero-copy performance, automatic offset management, and a set of advanced tools.

Working with binary data in JavaScript and TypeScript has always been a chore. Manually tracking offsets, worrying about endianness, and constantly copying memory—it's easy to get bogged down in boilerplate code. Existing libraries only address some of the issues, but they either tie to Node.js Buffer or don't support modern features like SharedArrayBuffer.

Today I'm excited to introduce Flash-Buffer: a lightning-fast binary data library that makes manipulating ArrayBuffers as easy as working with JSON.


🤔 Problem: Binary data is complex and slow

Whether you're parsing a custom network protocol, reading media file headers, or serializing game state for transmission over WebSocket, you'll encounter the same inconveniences:

  • Manual offset management. Every read or write requires updating the offset variable. This is a source of infinite per-unit errors.
  • Data copying. Standard methods often create new buffers instead of working with existing ones. This kills performance on large data sets.
  • Lack of convenient abstractions. You want to write a string or a floating-point number, but you have to fiddle with DataView and TextEncoder.

Flash-Buffer solves these problems by providing an intuitive API that remains incredibly fast.


🚀 Key Features

  • Zero-Copy. Reading data returns a Uint8Array, which is a direct "view" of the memory location. No unnecessary copying just pure performance.
  • Smart memory management. Automatic buffer expansion on write (exact, powerOfTwo, fixed strategies), built-in buffer pool to reduce GC load, native resize() support for ArrayBuffer.
  • Cross-platform. Works in browsers, Node.js, Deno, and Bun. Supports SharedArrayBuffer for efficient data exchange between threads without copying.
  • Advanced data formats:
  • - VarInt (LEB128) with ZigZag encoding-like Protobuf.
  • Bitwise operations (BitBuffer) for flags, compressed data, and cryptography.
  • C-strings (null-terminated).
  • Stream adapters for the Web Streams API.
  • Schematic serialization. Use TypeScript decorators (@field) to describe the class structure, and the library will automatically serialize it to and from a binary buffer.

💻 Usage examples

Basic reading and writing:

import { FlashBuffer } from 'flash-buffer';

// Create a buffer (auto-growing, little-endian by default)
const buf = new FlashBuffer({ endianness: 'little' });

// Write data
buf.writeUint32(0xDEADBEEF);
buf.writeString('Hello, Flash!', 'utf-8', true); // true = prefix length as uint32

// Reset the offset for reading
buf.reset();

// Read data back
const value = buf.readUint32();
const strLength = buf.readUint32();
const str = buf.readString(strLength);

console.log(value.toString(16)); // 'deadbeef'
console.log(str);               // 'Hello, Flash!'
Enter fullscreen mode Exit fullscreen mode

Working with VarInt (Variable-Length Integers):

import { FlashBuffer } from 'flash-buffer';

const buf = new FlashBuffer();

// Write a large number (less than 128) in one byte instead of four
buf.writeVarUint(127);

// Write a negative number efficiently using ZigZag encoding
buf.writeVarInt(-15);

buf.reset();

console.log(buf.readVarUint()); // 127
console.log(buf.readVarInt());  // -15
console.log(buf.offset);        // 3 (1 byte for 127 + 2 bytes for -15)
Enter fullscreen mode Exit fullscreen mode

Bit-level operations:

import { FlashBuffer } from 'flash-buffer';

const buf = new FlashBuffer();
const bits = buf.bit();

// Write a sequence of bits that may cross byte boundaries
bits.writeBits(0b11111, 5);
bits.writeBits(0b10101, 5);
bits.flush(); // Important: flush to finalize the byte and align the offset

buf.reset();
const readBits = buf.bit();
console.log(readBits.readBits(5)); // 0b11111 (31)
console.log(readBits.readBits(5)); // 0b10101 (21)
Enter fullscreen mode Exit fullscreen mode

Serializing objects using decorators:

import { FlashBufferSchema, field } from 'flash-buffer';

/* Create serializable class (Player) */
class Player {
  @field({ type: 'uint32' }) id: number = 0;
  @field({ type: 'string' }) name: string = '';
  @field({ type: 'float32' }) x: number = 0;
  @field({ type: 'float32' }) y: number = 0;
}

/* Create new Player */
const player = new Player();
player.id = 1;
player.name = 'John';
player.x = 100.5;
player.y = 200.5;

/* Serialize and Restore Object */
const buf = FlashBufferSchema.serialize(player);
const restored = FlashBufferSchema.deserialize(Player, buf.reset());
Enter fullscreen mode Exit fullscreen mode

📊 Comparison with similar libraries

Several excellent libraries exist for binary data manipulation. Flash Buffer was designed to combine their strengths and offer unique capabilities.

Feature flash-buffer smart-buffer @hazae41/binary @jsonjoy.com/buffers
Zero-Copy
**SharedArrayBuffer**
Automatic Growth
Streaming (Web Streams)
Bit-Level Operations
VarInt (LEB128)
C-Strings
Schema Serialization
Buffer Pool

Unique advantages of Flash Buffer:

  • Full support for SharedArrayBuffer the key to copy-free multithreading.
  • Modern DataView-style API intuitive and concise.
  • A wide range of out-of-the-box tools: from VarInt to Serialization and streams.

📦 Installation and getting started

Just install via NPM (zero-dependency library):

npm install flash-buffer
Enter fullscreen mode Exit fullscreen mode

Or clone from GitHub:
https://github.com/devsdaddy/flash-buffer/


💎 Conclusion

Flash-Buffer was created to free you from the pain of manually handling binary data. It combines the performance of zero-copy, the convenience of high-level abstractions, and support for modern web standards. If you write network protocols, parse files, or develop high-load services, try Flash-Buffer and you'll be surprised at how simple binary code can be.

I welcome stars, issues, and pull requests on GitHub. Share your experiences or questions in the comments!

Read Full Tutorial open_in_new
arrow_back Back to Tutorials