Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Copyright (c) 2024, Mapbox
Copyright (c) 2026, Mapbox
All rights reserved.

Redistribution and use in source and binary forms, with or without
Expand Down
40 changes: 24 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,14 @@ $ pbf example.proto > example.js
Then read and write objects using the module like this:

```js
import Pbf from 'pbf';
import {PbfReader, PbfWriter} from 'pbf';
import {readExample, writeExample} from './example.js';

// read
var obj = readExample(new Pbf(buffer));
const obj = readExample(new PbfReader(buffer));

// write
const pbf = new Pbf();
const pbf = new PbfWriter();
writeExample(obj, pbf);
const buffer = pbf.finish();
```
Expand All @@ -58,7 +58,7 @@ const {readExample, writeExample} = compile(proto);
#### Custom Reading

```js
var data = new Pbf(buffer).readFields(readData, {});
const data = new PbfReader(buffer).readFields(readData, {});

function readData(tag, data, pbf) {
if (tag === 1) data.name = pbf.readString();
Expand All @@ -74,9 +74,9 @@ function readLayer(tag, layer, pbf) {
#### Custom Writing

```js
var pbf = new Pbf();
const pbf = new PbfWriter();
writeData(data, pbf);
var buffer = pbf.finish();
const buffer = pbf.finish();

function writeData(data, pbf) {
pbf.writeStringField(1, data.name);
Expand All @@ -94,36 +94,38 @@ function writeLayer(layer, pbf) {
Install using NPM with `npm install pbf`, then import as a module:

```js
import Pbf from 'pbf';
import {PbfReader, PbfWriter} from 'pbf';
```

Or use as a module directly in the browser with [jsDelivr](https://www.jsdelivr.com/esm):

```html
<script type="module">
import Pbf from 'https://cdn.jsdelivr.net/npm/pbf/+esm';
import {PbfReader, PbfWriter} from 'https://cdn.jsdelivr.net/npm/pbf/+esm';
</script>
```

Alternatively, there's a browser bundle with a `Pbf` global variable:
Alternatively, there's a browser bundle exposing a `Pbf` global with `PbfReader` and `PbfWriter` properties:

```html
<script src="https://cdn.jsdelivr.net/npm/pbf"></script>
```

## API

Create a `Pbf` object, optionally given a `Buffer` or `Uint8Array` as input data:
The library exposes two classes: `PbfReader` for decoding and `PbfWriter` for encoding. Splitting them lets bundlers tree-shake the half you don't use.

Create a `PbfReader` from a `Buffer` or `Uint8Array`:

```js
// parse a pbf file from disk in Node
const pbf = new Pbf(fs.readFileSync('data.pbf'));
const pbf = new PbfReader(fs.readFileSync('data.pbf'));

// parse a pbf file in a browser after an ajax request with responseType="arraybuffer"
const pbf = new Pbf(new Uint8Array(xhr.response));
const pbf = new PbfReader(new Uint8Array(xhr.response));
```

`Pbf` object properties:
Both classes expose the following properties:

```js
pbf.length; // length of the underlying buffer
Expand All @@ -143,7 +145,7 @@ pbf.readFields((tag) => {
```

It optionally accepts an object that will be passed to the reading function for easier construction of decoded data,
and also passes the `Pbf` object as a third argument:
and also passes the `PbfReader` object as a third argument:

```js
const result = pbf.readFields(readField, {})
Expand Down Expand Up @@ -205,6 +207,12 @@ Packed reading methods:

#### Writing

Create a `PbfWriter` (optionally with a pre-allocated `Buffer` or `Uint8Array`):

```js
const pbf = new PbfWriter();
```

Write values:

```js
Expand Down Expand Up @@ -287,7 +295,7 @@ The `--legacy` switch makes it generate a CommonJS module instead of ESM.
`Pbf` will generate `read<Identifier>` and `write<Identifier>` functions for every message in the schema. For nested messages, their names will be concatenated — e.g. `Message` inside `Test` will produce `readTestMessage` and `writeTestMessage` functions.


* `read(pbf)` - decodes an object from the given `Pbf` instance.
* `write(obj, pbf)` - encodes an object into the given `Pbf` instance (usually empty).
* `read(pbf)` - decodes an object from the given `PbfReader` instance.
* `write(obj, pbf)` - encodes an object into the given `PbfWriter` instance (usually empty).

The resulting code is clean and simple, so it's meant to be customized.
6 changes: 3 additions & 3 deletions bench/bench-tiles.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {mkdirSync, existsSync, readFileSync, writeFileSync} from 'fs';
import {join, dirname} from 'path';
import {fileURLToPath} from 'url';
import {readTile, writeTile} from '../test/fixtures/vector_tile.js';
import Pbf from '../index.js';
import {PbfReader, PbfWriter} from '../index.js';

const token = process.env.ACCESS_TOKEN;
if (!token) throw new Error('Missing ACCESS_TOKEN environment variable (Mapbox access token).');
Expand All @@ -31,11 +31,11 @@ function processTile(body) {
numTiles++;

let now = clock();
const tile = readTile(new Pbf(body));
const tile = readTile(new PbfReader(body));
readTime += clock(now);

now = clock();
const pbf = new Pbf();
const pbf = new PbfWriter();
writeTile(tile, pbf);
const buf = pbf.finish();
writeTime += clock(now);
Expand Down
28 changes: 14 additions & 14 deletions bench/bench.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,47 +6,47 @@ import protocolBuffers from 'protocol-buffers';
import protobufjs from 'protobufjs';

import {readTile, writeTile} from '../test/fixtures/vector_tile.js';
import Pbf from '../index.js';
import {PbfReader, PbfWriter} from '../index.js';

var data = fs.readFileSync(new URL('../test/fixtures/12665.vector.pbf', import.meta.url)),
const data = fs.readFileSync(new URL('../test/fixtures/12665.vector.pbf', import.meta.url)),
suite = new Benchmark.Suite(),
vtProtoUrl = new URL('../test/fixtures/vector_tile.proto', import.meta.url),
ProtocolBuffersTile = protocolBuffers(fs.readFileSync(vtProtoUrl)).Tile,
ProtobufjsTile = protobufjs.loadSync(fileURLToPath(vtProtoUrl)).lookup('vector_tile.Tile');

var pbfTile = readTile(new Pbf(data)),
const pbfTile = readTile(new PbfReader(data)),
tileJSON = JSON.stringify(pbfTile),
protocolBuffersTile = ProtocolBuffersTile.decode(data),
protobufjsTile = ProtobufjsTile.decode(data);

suite
.add('decode vector tile with pbf', function() {
readTile(new Pbf(data));
.add('decode vector tile with pbf', () => {
readTile(new PbfReader(data));
})
.add('encode vector tile with pbf', function() {
var pbf = new Pbf();
.add('encode vector tile with pbf', () => {
const pbf = new PbfWriter();
writeTile(pbfTile, pbf);
pbf.finish();
})
.add('decode vector tile with protocol-buffers', function() {
.add('decode vector tile with protocol-buffers', () => {
ProtocolBuffersTile.decode(data);
})
.add('encode vector tile with protocol-buffers', function() {
.add('encode vector tile with protocol-buffers', () => {
ProtocolBuffersTile.encode(protocolBuffersTile);
})
.add('decode vector tile with protobuf.js', function() {
.add('decode vector tile with protobuf.js', () => {
ProtobufjsTile.decode(data);
})
.add('encode vector tile with protobuf.js', function() {
.add('encode vector tile with protobuf.js', () => {
ProtobufjsTile.encode(protobufjsTile);
})
.add('JSON.parse vector tile', function() {
.add('JSON.parse vector tile', () => {
JSON.parse(tileJSON);
})
.add('JSON.stringify vector tile', function() {
.add('JSON.stringify vector tile', () => {
JSON.stringify(pbfTile);
})
.on('cycle', function(event) {
.on('cycle', (event) => {
console.log(String(event.target));
})
.run();
Loading
Loading