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 🙏

© 2025 – Pkg Stats / Ryan Hefner

memium

v0.1.10

Published

Linear memory in TypeScript

Downloads

802

Readme

memium: Linear Memory for TypeScript

Memium is a library for working with linear memory in TypeScript. It enables you to use binary structs and pointers[1] easily, without having to worry about the underlying operations. Memium is designed with performance and a seamless user experience in mind.

[1] Work In Progress

Installation

npm install memium

If you're using Memium, especially for big projects, please consider supporting the project.

Structs

The @struct decorator turns a class into a struct. Like the various typed array classes and DataView, Structs are ArrayBufferViews, meaning they have a buffer, byteOffset, and byteLength. They also have a similar constructor to typed arrays. You will need extend a class that implements these, or implement that functionality your self. Uint8array and Utilium's BufferView are good choices.

Once you have a struct, you can decorate members of the class as fields on the struct. The easiest way to do this is using the shortcuts for primitives, though you will need to use @field for nested structs and unions. With shortcuts, you write @types.type for a single value or @types.type(length) for an array. Importing types as t makes this even shorter and is more similar to C-style example_t types.

Structs can have attributes, just like in C. You pass these as arguments to the decorator. At the moment, you can use packed and align(n).

Putting all of it together, you could have something like this:

import { struct, types as t, packed } from 'memium';

@struct(packed)
class Person extends Uint8Array {
	@t.char(1) accessor magic = 'P';

	@t.uint16 accessor age = 0;

	@t.uint8 accessor name_length = 0;

	@t.char(32, { countedBy: 'name_length' }) accessor name: Uint8Array;
}

Structs in Memium have the same behavior as structs in C.

Inheritance

You can use normal class inheritance with structs, though you'll need to use @struct on any subclasses you want to be structs.

For example:

import { struct, types as t, packed, sizeof } from 'memium';

@struct()
class Animal extends Uint8Array {
	@t.char(64) accessor species: Uint8Array;
	@t.float32 accessor age: number;
	@t.float32 accessor weight: number;
}

@struct()
class Duck extends Animal {
	@t.uint8 accessor name_length: number;
	// Dynamically sized array
	@t.char(0, { countedBy: 'name_length' }) accessor name: Uint8Array;
}

const data = new ArrayBuffer(sizeof(Duck) + 32 /* starting memory for the name*/);

const duck = new Duck(data);

const encoder = new TextEncoder();
const encode = encoder.encode.bind(encoder);

Object.assign(duck, {
	species: encode('Mallard'),
	age: 1.5,
	name_length: 5,
	name: encode('Jerry'),
});

// References the same memory
const animal = new Animal(data);

console.log(animal.age); // 1.5

Nesting

As mentioned above, you'll need to use @field for non-primitive types (i.e. structs and unions). Below is a more complex example of a custom file format.

import { struct, types as t, packed, field } from 'memium';

const encoder = new TextEncoder();
const encode = encoder.encode.bind(encoder);

@struct(packed)
class Header extends Uint8Array {
	@t.char(8) accessor magic: Uint8Array = encode('EXAMPLE!');
	@t.uint16 accessor format: number;
	@t.uint16 accessor app_version: number;
	@t.uint8(16) accessor uuid: Uint8Array;
	@t.float64 accessor timestamp: number;
	@t.uint64(12) accessor padding: BigUint64Array; // pad to 128
}

@struct(packed)
class AppFile extends Uint8Array {
	@field(Header) accessor header: Header;
	@t.uint32 accessor n_sections: number;
	@field(Section, { countedBy: 'n_sections' }) accessor sections: Section[];
}

Pointers

[!NOTE] Pointers are a work in progress. What you see below is the planned API.

Pointers are centralized around Pointer, which is used along with array buffers.

The planned API looks like this:

function alloc(size: number): number;

function free(addr: number | Pointer): void;

function realloc(addr: number | Pointer, size: number): number;

class Pointer<T> extends Number {
	buffer: ArrayBufferLike;
	byteOffset: number; // "physical" address
	constructor(type: T, address: number /* "logical" address */);
	deref(): T;
	increment(amount: number): Pointer<T>;
	decrement(amount: number): Pointer<T>;
}

A simple use case:

import { Animal, Duck } from 'the previous example';
import { sizeof, pointer, alloc } from 'memium';

const addr = alloc(sizeof(Duck));

const duck_ptr = new Pointer(Duck, addr);

const duck = duck_ptr.deref();

Paged Memory

[!NOTE] Paged memory is a work in progress. What you see below is the planned API.

The planned API looks like this:

interface Page {
	buffer: ArrayBufferLike;
	offset: number;
}

class PagedMemory {
	constructor(readonly pageSize: number)
	add(buffer: ArrayBufferLike): void;
	alloc(address: number, size: number): boolean;
	at(address: number): Uint8Array;
}

let defaultMemory: PagedMemory;