npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

bincode-ts

v1.0.0

Published

Codec bincode in typescript.

Readme

bincode-ts

CI codecov npm version npm downloads License: MIT TypeScript Rust Compatible

A high-performance TypeScript library for type-safe binary serialization using Rust-inspired bincode format. bincode-ts provides efficient encoding and decoding of complex data structures with full TypeScript type safety and support for both fixed and variable-length encoding schemes.

What is bincode-ts?

bincode-ts is a binary serialization library that brings Rust's type system concepts to TypeScript, offering:

  • Type Safety: Full TypeScript support with compile-time type checking
  • High Performance: Efficient binary serialization optimized for speed
  • Flexible Encoding: Support for both fixed and variable-length integer encoding
  • Zero Dependencies: Pure TypeScript implementation
  • Composable Types: Build complex data structures from simple primitives
  • Memory Efficient: Minimal overhead binary format

Features

  • 🎯 Complete Type Safety: Full TypeScript type inference and checking
  • 🚀 High Performance: Optimized binary encoding/decoding
  • 📊 Multiple Encoding Modes: Fixed-length and variable-length integer encoding
  • 🏗️ Composable Architecture: Combine primitive and composite types
  • 🌐 Universal Compatibility: Works in Node.js, browsers, and other JavaScript runtimes
  • 🔧 Custom Types: Extensible with user-defined serialization logic
  • 📦 Zero Dependencies: No external dependencies

Installation

npm install bincode-ts

Quick Start

import { Struct, String, u8, u32, encode, decode } from 'bincode-ts';

// Define a struct type
const Person = Struct({
  name: String,
  age: u8,
  id: u32
});

// Create data
const person = {
  name: "Alice",
  age: 30,
  id: 12345
};

// Encode to binary format
const buffer = new ArrayBuffer(256);
const size = encode(Person, person, buffer);
const encoded = buffer.slice(0, size);

// Decode from binary format
const decoded = decode(Person, encoded);
console.log(decoded.value); // { name: "Alice", age: 30, id: 12345 }
console.log(decoded.offset); // Number of bytes read

Supported Types

Primitive Types

Unsigned Integers

  • u8 - 8-bit unsigned integer (0 to 255)
  • u16 - 16-bit unsigned integer (0 to 65,535)
  • u32 - 32-bit unsigned integer (0 to 4,294,967,295)
  • u64 - 64-bit unsigned integer (BigInt)

Signed Integers

  • i8 - 8-bit signed integer (-128 to 127)
  • i16 - 16-bit signed integer (-32,768 to 32,767)
  • i32 - 32-bit signed integer (-2,147,483,648 to 2,147,483,647)
  • i64 - 64-bit signed integer (BigInt)

Floating Point

  • f32 - 32-bit floating point number
  • f64 - 64-bit floating point number

Other Primitives

  • bool - Boolean value
  • String - UTF-8 encoded string with variable length
  • Unit - Zero-sized type

Composite Types

Struct

Named field containers for structured data:

const User = Struct({
  id: u32,
  username: String,
  email: String,
  isActive: bool,
  balance: f64
});

const user = {
  id: 123,
  username: "alice",
  email: "[email protected]",
  isActive: true,
  balance: 1000.50
};

Tuple

Ordered collections of heterogeneous types:

const Coordinates = Tuple(f32, f32, f32); // (x, y, z)
const point: [number, number, number] = [1.0, 2.0, 3.0];

const UserInfo = Tuple(String, u8, bool);
const info: [string, number, boolean] = ["Alice", 30, true];

Array

Fixed-size collections of homogeneous types:

const Numbers = Array(u32, 5);
const data = array(1, 2, 3, 4, 5); // Exactly 5 elements

const Matrix = Array(Array(f32, 3), 3); // 3x3 matrix

Collection

Variable-size collections:

const NumberList = Collection(u32);
const numbers = [1, 2, 3, 4, 5]; // Any number of elements

const StringList = Collection(String);
const tags = ["typescript", "rust", "serialization"];

Enum

Tagged unions with variants:

const Status = Enum({
  Success: _(0),
  Error: _(1, Tuple(String)),
  Pending: _(2),
  InProgress: _(3, Tuple(u8)) // Progress percentage
});

// Create enum values
const success = $('Success');
const error = $('Error', ["Network timeout"] as [string]);
const progress = $('InProgress', [75] as [number]);

Option

Represents optional values:

const OptionalNumber = Option(u32);

// Some value
const someValue = 42;
const encodedSome = encode(OptionalNumber, someValue, buffer);

// None value
const noneValue = null;
const encodedNone = encode(OptionalNumber, noneValue, buffer);

Result

Represents success/error states:

const StringResult = Result(String, u32);

// Success case
const okValue = $('Ok', ["Success message"] as [string]);

// Error case  
const errValue = $('Err', [404] as [number]);

Encoding Configurations

bincode-ts supports different encoding configurations for optimal performance:

Standard (Fixed-Length) Encoding

import { BincodeConfig } from 'bincode-ts';

const config = BincodeConfig.STANDARD; // Default configuration
// - Little endian byte order
// - Fixed 8-byte length prefixes for collections and strings
// - Compatible with Rust bincode default settings

Variable-Length Encoding

const variantConfig: BincodeConfig = {
  endian: 'little',
  int_encoding: 'variant', // Variable-length encoding
  limit: undefined
};

// More efficient for smaller collections and strings
const data = ["short", "strings"];
const size = encode(Collection(String), data, buffer, 0, variantConfig);

Variable-length encoding uses:

  • 1 byte for lengths < 251
  • 3 bytes for lengths 251-65535
  • 5 bytes for lengths 65536-4294967295
  • 9 bytes for larger lengths

Complex Examples

Nested Structures

const Address = Struct({
  street: String,
  city: String,
  zipCode: u32
});

const Person = Struct({
  name: String,
  age: u8,
  address: Address,
  tags: Collection(String),
  scores: Array(u8, 3)
});

const person = {
  name: "John Doe",
  age: 30,
  address: {
    street: "123 Main St",
    city: "Springfield", 
    zipCode: 12345
  },
  tags: ["developer", "typescript"],
  scores: array(95, 87, 92)
};

Collections of Structs

const Employee = Struct({
  name: String,
  id: u32,
  department: String
});

const EmployeeList = Collection(Employee);

const employees = [
  { name: "Alice", id: 1001, department: "Engineering" },
  { name: "Bob", id: 1002, department: "Marketing" },
  { name: "Charlie", id: 1003, department: "Sales" }
];

const buffer = new ArrayBuffer(1024);
const size = encode(EmployeeList, employees, buffer);
const decoded = decode(EmployeeList, buffer.slice(0, size));

Custom Types

import { CustomTypeClass, BincodeConfig } from 'bincode-ts';

// Custom Date type that serializes as Unix timestamp
class DateType extends CustomTypeClass<Date, 'Date'> {
  readonly type = 'Date';

  encode(buffer: ArrayBuffer, value: Date, offset: number, config: BincodeConfig): number {
    const view = new DataView(buffer);
    const timestamp = BigInt(value.getTime());
    view.setBigUint64(offset, timestamp, config.endian === 'little');
    return offset + 8;
  }

  decode(buffer: ArrayBuffer, offset: number, config: BincodeConfig): { value: Date, offset: number } {
    const view = new DataView(buffer);
    const timestamp = view.getBigUint64(offset, config.endian === 'little');
    return {
      value: new Date(Number(timestamp)),
      offset: offset + 8
    };
  }
}

const dateType = new DateType();

// Usage
const now = new Date();
const buffer = new ArrayBuffer(16);
const size = encode(dateType, now, buffer);
const { value: decoded } = decode(dateType, buffer);

Error Handling

Bincode-TS provides comprehensive error handling with specific error types:

import { BincodeError } from 'bincode-ts';

try {
  const result = decode(SomeType, buffer);
  console.log(result.value);
} catch (error) {
  if (error instanceof BincodeError) {
    switch (error.bincodeErrorKind) {
      case 'OverflowLimit':
        console.error('Buffer overflow:', error.message);
        break;
      case 'InvalidVariant':
        console.error('Invalid enum variant:', error.message);
        break;
      case 'InvalidType':
        console.error('Type validation failed:', error.message);
        break;
      // Handle other error types...
    }
  }
}

API Reference

Core Functions

encode<T>(type: T, value: Value<T>, buffer: ArrayBuffer, offset?: number, config?: BincodeConfig): number

Encodes a value into binary format.

Parameters:

  • type: The type definition
  • value: The value to encode (must match the type)
  • buffer: Target ArrayBuffer
  • offset: Starting position (default: 0)
  • config: Encoding configuration (default: BincodeConfig.STANDARD)

Returns: Number of bytes written

decode<T>(type: T, buffer: ArrayBuffer, offset?: number, config?: BincodeConfig): { value: Value<T>, offset: number }

Decodes a value from binary format.

Parameters:

  • type: The type definition
  • buffer: Source ArrayBuffer containing binary data
  • offset: Starting position (default: 0)
  • config: Decoding configuration (default: BincodeConfig.STANDARD)

Returns: Object with decoded value and final offset

Utility Functions

array<T, N>(...elements: T[]): T[] & { readonly length: N }

Creates a fixed-length array for use with Array types:

const fixedArray = array(1, 2, 3, 4, 5); // length is exactly 5
const ArrayType = Array(u32, 5);

$<K, V>(variant: K, value?: V): EnumVariantValue<K, V>

Creates enum variant values:

const success = $('Success');
const error = $('Error', ["Something went wrong"]);

Performance Considerations

Buffer Sizing

Pre-allocate appropriately sized buffers to avoid reallocations:

// For collections, estimate: 8 bytes (length) + (element_count * element_size)
const estimatedSize = 8 + (1000 * 4); // 1000 u32 values
const buffer = new ArrayBuffer(estimatedSize);

Variable vs Fixed Encoding

  • Use variable encoding for small collections and short strings
  • Use fixed encoding for consistent performance and larger datasets

Memory Usage

// Efficient: reuse buffers
const buffer = new ArrayBuffer(4096);
let offset = 0;

offset = encode(Type1, value1, buffer, offset);
offset = encode(Type2, value2, buffer, offset);
offset = encode(Type3, value3, buffer, offset);

// Get the used portion
const used = buffer.slice(0, offset);

Testing

# Run all tests
npm test

# Run specific test suites
npm test -- --testNamePattern="Primitive Types"
npm test -- --testNamePattern="Composite Types"
npm test -- --testNamePattern="Error Handling"

# Run tests in watch mode
npm run test:watch

# Generate coverage report
npm run test:coverage

Development

# Install dependencies
npm install

# Build TypeScript
npm run build

# Lint code
npm run lint

# Type checking
npm run type-check

Contributing

Contributions are welcome! Please ensure:

  1. All tests pass (npm test)
  2. Code follows linting rules (npm run lint)
  3. TypeScript compiles without errors (npm run build)
  4. Add tests for new features
  5. Update documentation as needed

License

MIT License - see the LICENSE file for details.

Changelog

See CHANGELOG.md for version history and breaking changes.