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
10 changes: 5 additions & 5 deletions packages/bundle-size/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@ usually do. We repeat this for an increasing number of files.

| code generator | files | bundle size | minified | compressed |
| ------------------- | ----: | ----------: | --------: | ---------: |
| Protobuf-ES | 1 | 133,976 b | 69,171 b | 15,890 b |
| Protobuf-ES | 4 | 136,165 b | 70,678 b | 16,587 b |
| Protobuf-ES | 8 | 138,927 b | 72,449 b | 17,134 b |
| Protobuf-ES | 16 | 149,377 b | 80,430 b | 19,442 b |
| Protobuf-ES | 32 | 177,168 b | 102,448 b | 24,922 b |
| Protobuf-ES | 1 | 134,690 b | 69,523 b | 15,945 b |
| Protobuf-ES | 4 | 136,879 b | 71,027 b | 16,621 b |
| Protobuf-ES | 8 | 139,641 b | 72,798 b | 17,182 b |
| Protobuf-ES | 16 | 150,091 b | 80,779 b | 19,489 b |
| Protobuf-ES | 32 | 177,882 b | 102,800 b | 24,953 b |
| protobuf-javascript | 1 | 314,120 b | 244,024 b | 35,999 b |
| protobuf-javascript | 4 | 340,137 b | 258,996 b | 37,473 b |
| protobuf-javascript | 8 | 360,931 b | 270,573 b | 38,585 b |
Expand Down
12 changes: 6 additions & 6 deletions packages/bundle-size/chart.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
64 changes: 50 additions & 14 deletions packages/protobuf/src/wire/binary-encoding.ts
Original file line number Diff line number Diff line change
Expand Up @@ -386,24 +386,45 @@ export class BinaryReader {
}

/**
* Reads a tag - field number and wire type. Tags are uint32 varints; values
* that do not fit in uint32 are rejected.
* Reads a tag - field number and wire type.
*
* Inlined for the hot path. Tags are uint32 varints: at most 5 bytes, and
* the 5th byte can carry only 4 value bits (its upper 4 bits and the
* continuation bit must all be zero). Rejects overlong or overflowing
* varints.
*/
tag(): [number, WireType] {
const start = this.pos;
const tag = this.uint32();
const bytesRead = this.pos - start;
if (bytesRead > 5 || (bytesRead == 5 && this.buf[this.pos - 1] > 0x0f)) {
throw new Error("illegal tag: varint overflows uint32");
let b = this.buf[this.pos++];
if ((b & 0x80) == 0) {
this.assertBounds();
return parseTag(b);
}
let tag = b & 0x7f;
b = this.buf[this.pos++];
tag |= (b & 0x7f) << 7;
if ((b & 0x80) == 0) {
this.assertBounds();
return parseTag(tag);
}
const fieldNo = tag >>> 3;
const wireType = tag & 7;
if (fieldNo <= 0 || wireType > 5) {
throw new Error(
"illegal tag: field no " + fieldNo + " wire type " + wireType,
);
b = this.buf[this.pos++];
tag |= (b & 0x7f) << 14;
if ((b & 0x80) == 0) {
this.assertBounds();
return parseTag(tag);
}
b = this.buf[this.pos++];
tag |= (b & 0x7f) << 21;
if ((b & 0x80) == 0) {
this.assertBounds();
return parseTag(tag);
}
b = this.buf[this.pos++];
if (b > 0x0f) {
throw new Error("illegal tag: varint overflows uint32");
}
return [fieldNo, wireType];
tag = (tag | (b << 28)) >>> 0;
this.assertBounds();
return parseTag(tag);
}

/**
Expand Down Expand Up @@ -579,6 +600,21 @@ export class BinaryReader {
}
}

/**
* Split a decoded tag varint into field number and wire type, rejecting
* field number 0 and wire types outside 0-5.
*/
function parseTag(tag: number): [number, WireType] {
const fieldNo = tag >>> 3;
const wireType = tag & 7;
if (fieldNo <= 0 || wireType > 5) {
throw new Error(
"illegal tag: field no " + fieldNo + " wire type " + wireType,
);
}
return [fieldNo, wireType];
}

/**
* Assert a valid signed protobuf 32-bit integer as a number or string.
*/
Expand Down
4 changes: 4 additions & 0 deletions packages/protobuf/src/wire/varint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,10 @@ export function varint32write(value: number, bytes: number[]): void {
/**
* Read an unsigned 32 bit varint.
*
* A uint32 value fits in 5 varint bytes, but this reader accepts up to 10
* bytes and discards the extra high bits. Negative `int32` values encode as
* 10-byte varints and must decode back to the original 32-bit value.
*
* See https://github.com/protocolbuffers/protobuf/blob/8a71927d74a4ce34efe2d8769fda198f52d20d12/js/experimental/runtime/kernel/buffer_decoder.js#L220
*/
export function varint32read<T extends ReaderLike>(this: T): number {
Expand Down
Loading