Protocol Buffers for JavaScript with TypeScript support, providing pure JavaScript implementation for serializing and deserializing structured data using Google's Protocol Buffer format.
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Low-level binary reading and writing operations for custom serialization needs, performance optimization, and direct protobuf wire format manipulation.
Binary writer for encoding protobuf wire format data with buffering and type-specific encoding methods.
class Writer {
/**
* Current length of written data
*/
len: number;
/**
* Operation head (internal)
*/
head: Operation;
/**
* Operation tail (internal)
*/
tail: Operation;
/**
* State stack for nested operations
*/
states: State[];
/**
* Creates a new writer instance
* @returns Writer instance
*/
static create(): Writer;
/**
* Writes unsigned 32-bit integer
* @param value - Value to write (0 to 4294967295)
* @returns This writer
*/
uint32(value: number): Writer;
/**
* Writes signed 32-bit integer
* @param value - Value to write (-2147483648 to 2147483647)
* @returns This writer
*/
int32(value: number): Writer;
/**
* Writes signed zigzag-encoded 32-bit integer
* @param value - Value to write
* @returns This writer
*/
sint32(value: number): Writer;
/**
* Writes unsigned 64-bit integer
* @param value - Value as number or Long
* @returns This writer
*/
uint64(value: number | Long | string): Writer;
/**
* Writes signed 64-bit integer
* @param value - Value as number or Long
* @returns This writer
*/
int64(value: number | Long | string): Writer;
/**
* Writes signed zigzag-encoded 64-bit integer
* @param value - Value as number or Long
* @returns This writer
*/
sint64(value: number | Long | string): Writer;
/**
* Writes fixed 32-bit unsigned integer (little endian)
* @param value - Value to write
* @returns This writer
*/
fixed32(value: number): Writer;
/**
* Writes fixed 32-bit signed integer (little endian)
* @param value - Value to write
* @returns This writer
*/
sfixed32(value: number): Writer;
/**
* Writes fixed 64-bit unsigned integer (little endian)
* @param value - Value as number or Long
* @returns This writer
*/
fixed64(value: number | Long | string): Writer;
/**
* Writes fixed 64-bit signed integer (little endian)
* @param value - Value as number or Long
* @returns This writer
*/
sfixed64(value: number | Long | string): Writer;
/**
* Writes 32-bit float (IEEE 754)
* @param value - Float value
* @returns This writer
*/
float(value: number): Writer;
/**
* Writes 64-bit double (IEEE 754)
* @param value - Double value
* @returns This writer
*/
double(value: number): Writer;
/**
* Writes boolean value
* @param value - Boolean value
* @returns This writer
*/
bool(value: boolean): Writer;
/**
* Writes string value (UTF-8 encoded)
* @param value - String value
* @returns This writer
*/
string(value: string): Writer;
/**
* Writes byte array
* @param value - Byte array
* @returns This writer
*/
bytes(value: Uint8Array | string): Writer;
/**
* Writes protobuf tag (field number and wire type)
* @param id - Field id
* @param wireType - Wire type
* @returns This writer
*/
tag(id: number, wireType: number): Writer;
/**
* Forks this writer (creates nested length-delimited context)
* @returns Forked writer
*/
fork(): Writer;
/**
* Resets writer to initial state
* @returns This writer
*/
reset(): Writer;
/**
* Finishes length-delimited context
* @returns This writer
*/
ldelim(): Writer;
/**
* Finishes writing and returns buffer
* @returns Encoded binary data
*/
finish(): Uint8Array;
}Usage Examples:
const protobuf = require("protobufjs");
// Basic writer usage
const writer = protobuf.Writer.create();
writer.tag(1, 2) // Field 1, length-delimited
.string("hello") // String value
.tag(2, 0) // Field 2, varint
.uint32(42); // Integer value
const buffer = writer.finish();
console.log("Encoded bytes:", Array.from(buffer));
// Length-delimited message writing
const writer2 = protobuf.Writer.create();
writer2.tag(1, 2); // Field 1, length-delimited
const fork = writer2.fork(); // Start nested message
fork.tag(1, 2).string("nested");
fork.tag(2, 0).uint32(123);
writer2.ldelim(); // Finish nested message
const nestedBuffer = writer2.finish();Node.js-specific writer that outputs Node.js Buffer instead of Uint8Array.
class BufferWriter extends Writer {
/**
* Finishes writing and returns Node.js Buffer
* @returns Encoded binary data as Buffer
*/
finish(): Buffer;
}Usage Examples:
// Node.js specific buffer writing
const writer = new protobuf.BufferWriter();
writer.tag(1, 2).string("test");
const buffer = writer.finish();
console.log("Buffer type:", buffer instanceof Buffer); // trueBinary reader for decoding protobuf wire format data with position tracking and type-specific decoding methods.
class Reader {
/**
* Source buffer
*/
buf: Uint8Array;
/**
* Current reading position
*/
pos: number;
/**
* Buffer length
*/
len: number;
/**
* Creates reader from buffer
* @param buffer - Buffer to read from
* @returns Reader instance
*/
static create(buffer: Uint8Array): Reader;
/**
* Reads unsigned 32-bit integer
* @returns Decoded value
*/
uint32(): number;
/**
* Reads signed 32-bit integer
* @returns Decoded value
*/
int32(): number;
/**
* Reads signed zigzag-decoded 32-bit integer
* @returns Decoded value
*/
sint32(): number;
/**
* Reads unsigned 64-bit integer
* @returns Decoded value as Long
*/
uint64(): Long;
/**
* Reads signed 64-bit integer
* @returns Decoded value as Long
*/
int64(): Long;
/**
* Reads signed zigzag-decoded 64-bit integer
* @returns Decoded value as Long
*/
sint64(): Long;
/**
* Reads fixed 32-bit unsigned integer (little endian)
* @returns Decoded value
*/
fixed32(): number;
/**
* Reads fixed 32-bit signed integer (little endian)
* @returns Decoded value
*/
sfixed32(): number;
/**
* Reads fixed 64-bit unsigned integer (little endian)
* @returns Decoded value as Long
*/
fixed64(): Long;
/**
* Reads fixed 64-bit signed integer (little endian)
* @returns Decoded value as Long
*/
sfixed64(): Long;
/**
* Reads 32-bit float (IEEE 754)
* @returns Decoded float value
*/
float(): number;
/**
* Reads 64-bit double (IEEE 754)
* @returns Decoded double value
*/
double(): number;
/**
* Reads boolean value
* @returns Decoded boolean
*/
bool(): boolean;
/**
* Reads string value (UTF-8 decoded)
* @returns Decoded string
*/
string(): string;
/**
* Reads byte array
* @returns Decoded bytes
*/
bytes(): Uint8Array;
/**
* Reads protobuf tag
* @returns Object with id and wireType properties
*/
tag(): { id: number; wireType: number };
/**
* Skips specified number of bytes
* @param length - Number of bytes to skip
* @returns This reader
*/
skip(length: number): Reader;
/**
* Skips value of specified wire type
* @param wireType - Wire type to skip
* @returns This reader
*/
skipType(wireType: number): Reader;
}Usage Examples:
// Basic reader usage
const reader = protobuf.Reader.create(buffer);
while (reader.pos < reader.len) {
const tag = reader.tag();
console.log(`Field ${tag.id}, wireType ${tag.wireType}`);
switch (tag.wireType) {
case 0: // varint
const value = reader.uint32();
console.log("Varint value:", value);
break;
case 2: // length-delimited
const bytes = reader.bytes();
console.log("Bytes length:", bytes.length);
break;
default:
reader.skipType(tag.wireType);
}
}
// Manual message decoding
function decodeMessage(buffer) {
const reader = protobuf.Reader.create(buffer);
const message = {};
while (reader.pos < reader.len) {
const tag = reader.tag();
switch (tag.id) {
case 1:
message.name = reader.string();
break;
case 2:
message.id = reader.uint32();
break;
default:
reader.skipType(tag.wireType);
}
}
return message;
}Node.js-specific reader for reading from Node.js Buffer objects.
class BufferReader extends Reader {
/**
* Source buffer as Node.js Buffer
*/
buf: Buffer;
/**
* Creates reader from Node.js Buffer
* @param buffer - Buffer to read from
* @returns BufferReader instance
*/
static create(buffer: Buffer): BufferReader;
}Protobuf wire type constants for low-level operations.
namespace WireType {
const Varint: 0; // int32, int64, uint32, uint64, sint32, sint64, bool, enum
const Fixed64: 1; // fixed64, sfixed64, double
const LengthDelimited: 2; // string, bytes, embedded messages, packed repeated fields
const StartGroup: 3; // deprecated
const EndGroup: 4; // deprecated
const Fixed32: 5; // fixed32, sfixed32, float
}Usage Examples:
// Using wire type constants
const writer = protobuf.Writer.create();
// Write string field (field 1)
writer.tag(1, protobuf.util.WireType.LengthDelimited);
writer.string("hello world");
// Write integer field (field 2)
writer.tag(2, protobuf.util.WireType.Varint);
writer.uint32(42);
// Write float field (field 3)
writer.tag(3, protobuf.util.WireType.Fixed32);
writer.float(3.14);Advanced binary I/O operations for complex use cases.
class Writer {
/**
* Writes raw buffer data
* @param buffer - Raw buffer to write
* @returns This writer
*/
raw(buffer: Uint8Array): Writer;
/**
* Gets current operation state
* @returns Current state object
*/
state(): State;
/**
* Pushes new state onto stack
* @param state - State to push
* @returns This writer
*/
push(state: State): Writer;
/**
* Pops state from stack
* @returns Popped state
*/
pop(): State;
}
class Reader {
/**
* Creates sub-reader for specified length
* @param length - Length of sub-buffer
* @returns New reader for sub-buffer
*/
slice(length: number): Reader;
/**
* Reads remaining bytes
* @returns All remaining bytes
*/
remaining(): Uint8Array;
}Usage Examples:
// Advanced writer operations
const writer = protobuf.Writer.create();
// Write custom data format
const customData = new Uint8Array([0x01, 0x02, 0x03]);
writer.tag(1, 2); // Length-delimited
writer.uint32(customData.length); // Length prefix
writer.raw(customData); // Raw data
// Complex nested structures
const fork1 = writer.fork();
fork1.tag(1, 2).string("level1");
const fork2 = fork1.fork();
fork2.tag(1, 2).string("level2");
fork1.ldelim(); // Close level2
writer.ldelim(); // Close level1
// Advanced reader operations
const reader = protobuf.Reader.create(buffer);
const tag = reader.tag();
if (tag.wireType === 2) { // Length-delimited
const length = reader.uint32();
const subReader = reader.slice(length);
// Process sub-message with dedicated reader
while (subReader.pos < subReader.len) {
const subTag = subReader.tag();
// Process sub-fields...
}
}interface Operation {
fn: Function;
len: number;
next: Operation | null;
}
interface State {
head: Operation;
tail: Operation;
len: number;
}
interface Long {
low: number;
high: number;
unsigned: boolean;
toNumber(): number;
toString(): string;
}
namespace util {
namespace WireType {
const Varint: 0;
const Fixed64: 1;
const LengthDelimited: 2;
const StartGroup: 3;
const EndGroup: 4;
const Fixed32: 5;
}
}Install with Tessl CLI
npx tessl i tessl/npm-protobufjs