CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-pbf

A low-level, lightweight protocol buffers implementation for JavaScript with high-performance binary serialization and deserialization capabilities.

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

buffer-operations.mddocs/

Buffer Reading and Writing

Core protocol buffer reading and writing functionality with support for all protocol buffer data types, packed fields, and direct buffer manipulation.

Reading Operations

Field-Level Reading

Read protocol buffer messages using field-based callbacks:

class Pbf {
    /**
     * Read all fields in a message using a callback function
     */
    readFields<T>(readField: (tag: number, result: T, pbf: Pbf) => void, result: T, end?: number): T;
    
    /**
     * Read an embedded message
     */
    readMessage<T>(readField: (tag: number, result: T, pbf: Pbf) => void, result: T): T;
}

Scalar Data Type Reading

Read individual data types from the buffer:

class Pbf {
    // Integer types
    readVarint(isSigned?: boolean): number;
    readSVarint(): number;
    readFixed32(): number;
    readSFixed32(): number;
    readFixed64(): number;
    readSFixed64(): number;
    
    // Floating point types
    readFloat(): number;
    readDouble(): number;
    
    // Other types
    readBoolean(): boolean;
    readString(): string;
    readBytes(): Uint8Array;
    
    // Legacy compatibility
    readVarint64(): number;
    
    // Internal helper for packed field reading
    readPackedEnd(): number;
}

Packed Field Reading

Read packed repeated fields efficiently:

class Pbf {
    readPackedVarint(arr?: number[], isSigned?: boolean): number[];
    readPackedSVarint(arr?: number[]): number[];
    readPackedBoolean(arr?: boolean[]): boolean[];
    readPackedFloat(arr?: number[]): number[];
    readPackedDouble(arr?: number[]): number[];
    readPackedFixed32(arr?: number[]): number[];
    readPackedSFixed32(arr?: number[]): number[];
    readPackedFixed64(arr?: number[]): number[];
    readPackedSFixed64(arr?: number[]): number[];
}

Buffer Navigation

Control reading position and skip unwanted fields:

class Pbf {
    buf: Uint8Array;     // Underlying buffer
    dataView: DataView;  // Data view for binary operations
    pos: number;         // Current reading/writing position
    type: number;        // Current field wire type
    length: number;      // Total buffer length
    
    /**
     * Skip a field value based on its wire type
     */
    skip(val: number): void;
    
    /**
     * Internal helper method for packed field reading
     * Determines the end position for packed field data
     */
    readPackedEnd(): number;
}

Writing Operations

Buffer Management

Manage buffer allocation and finalization:

class Pbf {
    /**
     * Ensure buffer has space for at least min bytes
     */
    realloc(min: number): void;
    
    /**
     * Finalize buffer and return the written data
     */
    finish(): Uint8Array;
    
    /**
     * Write a field tag and wire type
     */
    writeTag(tag: number, type: number): void;
}

Scalar Data Type Writing

Write individual data types to the buffer:

class Pbf {
    // Integer types
    writeVarint(val: number): void;
    writeSVarint(val: number): void;
    writeFixed32(val: number): void;
    writeSFixed32(val: number): void;
    writeFixed64(val: number): void;
    writeSFixed64(val: number): void;
    
    // Floating point types
    writeFloat(val: number): void;
    writeDouble(val: number): void;
    
    // Other types
    writeBoolean(val: boolean): void;
    writeString(str: string): void;
    writeBytes(buffer: Uint8Array): void;
}

Field Writing

Write fields with tags and wire types:

class Pbf {
    // Field writing with tags
    writeVarintField(tag: number, val: number): void;
    writeSVarintField(tag: number, val: number): void;
    writeFixed32Field(tag: number, val: number): void;
    writeSFixed32Field(tag: number, val: number): void;
    writeFixed64Field(tag: number, val: number): void;
    writeSFixed64Field(tag: number, val: number): void;
    writeFloatField(tag: number, val: number): void;
    writeDoubleField(tag: number, val: number): void;
    writeBooleanField(tag: number, val: boolean): void;
    writeStringField(tag: number, str: string): void;
    writeBytesField(tag: number, buffer: Uint8Array): void;
}

Message Writing

Write embedded messages and raw message data:

class Pbf {
    /**
     * Write an embedded message with tag
     */
    writeMessage<T>(tag: number, fn: (obj: T, pbf: Pbf) => void, obj: T): void;
    
    /**
     * Write a raw message without tag
     */
    writeRawMessage<T>(fn: (obj: T, pbf: Pbf) => void, obj: T): void;
}

Packed Field Writing

Write packed repeated fields efficiently:

class Pbf {
    writePackedVarint(tag: number, arr: number[]): void;
    writePackedSVarint(tag: number, arr: number[]): void;
    writePackedBoolean(tag: number, arr: boolean[]): void;
    writePackedFloat(tag: number, arr: number[]): void;
    writePackedDouble(tag: number, arr: number[]): void;
    writePackedFixed32(tag: number, arr: number[]): void;
    writePackedSFixed32(tag: number, arr: number[]): void;
    writePackedFixed64(tag: number, arr: number[]): void;
    writePackedSFixed64(tag: number, arr: number[]): void;
}

Usage Examples

Custom Reading

const pbf = new Pbf(buffer);
const data = pbf.readFields(readDataField, {});

function readDataField(tag, data, pbf) {
    if (tag === 1) data.name = pbf.readString();
    else if (tag === 2) data.version = pbf.readVarint();
    else if (tag === 3) data.tags = pbf.readPackedVarint(data.tags || []);
    else if (tag === 4) {
        data.metadata = pbf.readMessage(readMetadata, {});
    }
}

function readMetadata(tag, metadata, pbf) {
    if (tag === 1) metadata.author = pbf.readString();
    else if (tag === 2) metadata.timestamp = pbf.readFixed64();
}

Custom Writing

const pbf = new Pbf();
writeData(data, pbf);
const buffer = pbf.finish();

function writeData(data, pbf) {
    if (data.name) pbf.writeStringField(1, data.name);
    if (data.version) pbf.writeVarintField(2, data.version);
    if (data.tags && data.tags.length) pbf.writePackedVarint(3, data.tags);
    if (data.metadata) pbf.writeMessage(4, writeMetadata, data.metadata);
}

function writeMetadata(metadata, pbf) {
    if (metadata.author) pbf.writeStringField(1, metadata.author);
    if (metadata.timestamp) pbf.writeFixed64Field(2, metadata.timestamp);
}

Lazy Decoding

const pbf = new Pbf(buffer);
let metadataPos = -1;

// First pass - save position of expensive field
pbf.readFields((tag, result, pbf) => {
    if (tag === 1) result.name = pbf.readString();
    else if (tag === 4) metadataPos = pbf.pos; // Save position, don't read yet
}, {});

// Later - decode the expensive field when needed
if (metadataPos >= 0) {
    pbf.pos = metadataPos;
    const metadata = pbf.readMessage(readMetadata, {});
}

Wire Format Constants

declare const PBF_VARINT: 0;   // int32, int64, uint32, uint64, sint32, sint64, bool, enum
declare const PBF_FIXED64: 1;  // double, fixed64, sfixed64
declare const PBF_BYTES: 2;    // string, bytes, embedded messages, packed repeated fields
declare const PBF_FIXED32: 5;  // float, fixed32, sfixed32

Install with Tessl CLI

npx tessl i tessl/npm-pbf

docs

buffer-operations.md

cli-tool.md

index.md

schema-compilation.md

tile.json