From 23e4eb5017f7234d04184c951daf26187d33b432 Mon Sep 17 00:00:00 2001 From: achingbrain Date: Wed, 12 Oct 2022 11:22:25 +0100 Subject: [PATCH 1/3] chore: add protobuf-ts to benchmarks --- packages/protons-benchmark/README.md | 41 +- packages/protons-benchmark/package.json | 4 +- packages/protons-benchmark/src/bench.proto | 3 +- packages/protons-benchmark/src/index.ts | 9 +- .../src/protobuf-ts/bench.ts | 362 ++++++++++++++++++ .../protons-benchmark/src/protons/bench.ts | 113 +++--- packages/protons-benchmark/src/protons/rpc.ts | 325 ++++++++-------- packages/protons-benchmark/src/rpc.proto | 2 +- 8 files changed, 632 insertions(+), 227 deletions(-) create mode 100644 packages/protons-benchmark/src/protobuf-ts/bench.ts diff --git a/packages/protons-benchmark/README.md b/packages/protons-benchmark/README.md index 4e88155..d589ee9 100644 --- a/packages/protons-benchmark/README.md +++ b/packages/protons-benchmark/README.md @@ -35,21 +35,40 @@ Run the benchmark suite: ```console $ npm start -Running "Encode/Decode" suite... -Progress: 100% +> protons-benchmark@0.0.0 prestart +> npm run build - pbjs: - 12 166 ops/s, ±3.92% | 5.12% slower - protons: - 9 755 ops/s, ±2.19% | slowest, 23.93% slower +> protons-benchmark@0.0.0 build +> aegir build --no-bundle && cp -R src/protobufjs dist/src/protobufjs - protobufjs: - 12 823 ops/s, ±2.02% | fastest +[15:02:28] tsc [started] +[15:02:32] tsc [completed] -Finished 3 cases! - Fastest: protobufjs - Slowest: protons +> protons-benchmark@0.0.0 start +> node dist/src/index.js + +pbjs x 11,798 ops/sec ±4.58% (88 runs sampled) +protons x 11,693 ops/sec ±2.69% (85 runs sampled) +protobuf.js x 12,419 ops/sec ±1.66% (88 runs sampled) +@protobuf-ts x 10,536 ops/sec ±3.14% (85 runs sampled) +Fastest is protobuf.js +``` + +Or in a browser: + +```console +$ npm run start:browser + +> protons-benchmark@0.0.0 start:browser +> npx playwright-test dist/src/index.js --runner benchmark + +✔ chromium set up +pbjs x 19,027 ops/sec ±0.86% (67 runs sampled) +protons x 18,901 ops/sec ±0.65% (67 runs sampled) +protobuf.js x 18,937 ops/sec ±0.55% (65 runs sampled) +@protobuf-ts x 16,669 ops/sec ±0.49% (68 runs sampled) +Fastest is pbjs,protobuf.js ``` ## License diff --git a/packages/protons-benchmark/package.json b/packages/protons-benchmark/package.json index 6cc8dc5..41dc330 100644 --- a/packages/protons-benchmark/package.json +++ b/packages/protons-benchmark/package.json @@ -65,9 +65,11 @@ "dep-check": "aegir dep-check", "build": "aegir build --no-bundle && cp -R src/protobufjs dist/src/protobufjs", "prestart": "npm run build", - "start": "node dist/src/index.js" + "start": "node dist/src/index.js", + "start:browser": "npx playwright-test dist/src/index.js --runner benchmark" }, "dependencies": { + "@protobuf-ts/plugin": "^2.8.1", "@types/benchmark": "^2.1.1", "aegir": "^37.0.5", "benchmark": "^2.1.4", diff --git a/packages/protons-benchmark/src/bench.proto b/packages/protons-benchmark/src/bench.proto index 126ac8e..55791bf 100755 --- a/packages/protons-benchmark/src/bench.proto +++ b/packages/protons-benchmark/src/bench.proto @@ -9,6 +9,7 @@ message Bar { } enum FOO { + NONE=0; LOL=1; ABE=3; } @@ -19,7 +20,7 @@ message Yo { message Lol { optional string lol = 1; - required Bar b = 2; + Bar b = 2; } message Test { diff --git a/packages/protons-benchmark/src/index.ts b/packages/protons-benchmark/src/index.ts index 49fc81c..a79345d 100644 --- a/packages/protons-benchmark/src/index.ts +++ b/packages/protons-benchmark/src/index.ts @@ -10,6 +10,7 @@ import { expect } from 'aegir/chai' import { Test as ProtonsTest } from './protons/bench.js' import { encodeTest as pbjsEncodeTest, decodeTest as pbjsDecodeTest } from './pbjs/bench.js' import { Test as ProtobufjsTest } from './protobufjs/bench.js' +import { Test as ProtobufTsTest } from './protobuf-ts/bench.js' const message = { meh: { @@ -46,12 +47,18 @@ new Benchmark.Suite() expectDecodedCorrectly(result) }) - .add('protobufjs', () => { + .add('protobuf.js', () => { const buf = ProtobufjsTest.encode(message).finish() const result = ProtobufjsTest.decode(buf) expectDecodedCorrectly(result) }) + .add('@protobuf-ts', () => { + const buf = ProtobufTsTest.toBinary(message) + const result = ProtobufTsTest.fromBinary(buf) + + expectDecodedCorrectly(result) + }) .on('error', (err: Error) => { console.error(err) }) diff --git a/packages/protons-benchmark/src/protobuf-ts/bench.ts b/packages/protons-benchmark/src/protobuf-ts/bench.ts new file mode 100644 index 0000000..738ea94 --- /dev/null +++ b/packages/protons-benchmark/src/protobuf-ts/bench.ts @@ -0,0 +1,362 @@ +// @generated by protobuf-ts 2.8.1 +// @generated from protobuf file "bench.proto" (syntax proto3) +// tslint:disable +import type { BinaryWriteOptions } from "@protobuf-ts/runtime"; +import type { IBinaryWriter } from "@protobuf-ts/runtime"; +import { WireType } from "@protobuf-ts/runtime"; +import type { BinaryReadOptions } from "@protobuf-ts/runtime"; +import type { IBinaryReader } from "@protobuf-ts/runtime"; +import { UnknownFieldHandler } from "@protobuf-ts/runtime"; +import type { PartialMessage } from "@protobuf-ts/runtime"; +import { reflectionMergePartial } from "@protobuf-ts/runtime"; +import { MESSAGE_TYPE } from "@protobuf-ts/runtime"; +import { MessageType } from "@protobuf-ts/runtime"; +/** + * @generated from protobuf message Foo + */ +export interface Foo { + /** + * @generated from protobuf field: optional uint32 baz = 1; + */ + baz?: number; +} +/** + * @generated from protobuf message Bar + */ +export interface Bar { + /** + * @generated from protobuf field: optional Foo tmp = 1; + */ + tmp?: Foo; +} +/** + * @generated from protobuf message Yo + */ +export interface Yo { + /** + * @generated from protobuf field: repeated FOO lol = 1; + */ + lol: FOO[]; +} +/** + * @generated from protobuf message Lol + */ +export interface Lol { + /** + * @generated from protobuf field: optional string lol = 1; + */ + lol?: string; + /** + * @generated from protobuf field: Bar b = 2; + */ + b?: Bar; +} +/** + * @generated from protobuf message Test + */ +export interface Test { + /** + * @generated from protobuf field: optional Lol meh = 6; + */ + meh?: Lol; + /** + * @generated from protobuf field: optional uint32 hello = 3; + */ + hello?: number; + /** + * @generated from protobuf field: optional string foo = 1; + */ + foo?: string; + /** + * @generated from protobuf field: optional bytes payload = 7; + */ + payload?: Uint8Array; +} +/** + * @generated from protobuf enum FOO + */ +export enum FOO { + /** + * @generated from protobuf enum value: NONE = 0; + */ + NONE = 0, + /** + * @generated from protobuf enum value: LOL = 1; + */ + LOL = 1, + /** + * @generated from protobuf enum value: ABE = 3; + */ + ABE = 3 +} +// @generated message type with reflection information, may provide speed optimized methods +class Foo$Type extends MessageType { + constructor() { + super("Foo", [ + { no: 1, name: "baz", kind: "scalar", opt: true, T: 13 /*ScalarType.UINT32*/ } + ]); + } + create(value?: PartialMessage): Foo { + const message = {}; + globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + if (value !== undefined) + reflectionMergePartial(this, message, value); + return message; + } + internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: Foo): Foo { + let message = target ?? this.create(), end = reader.pos + length; + while (reader.pos < end) { + let [fieldNo, wireType] = reader.tag(); + switch (fieldNo) { + case /* optional uint32 baz */ 1: + message.baz = reader.uint32(); + break; + default: + let u = options.readUnknownField; + if (u === "throw") + throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`); + let d = reader.skip(wireType); + if (u !== false) + (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d); + } + } + return message; + } + internalBinaryWrite(message: Foo, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter { + /* optional uint32 baz = 1; */ + if (message.baz !== undefined) + writer.tag(1, WireType.Varint).uint32(message.baz); + let u = options.writeUnknownFields; + if (u !== false) + (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer); + return writer; + } +} +/** + * @generated MessageType for protobuf message Foo + */ +export const Foo = new Foo$Type(); +// @generated message type with reflection information, may provide speed optimized methods +class Bar$Type extends MessageType { + constructor() { + super("Bar", [ + { no: 1, name: "tmp", kind: "message", T: () => Foo } + ]); + } + create(value?: PartialMessage): Bar { + const message = {}; + globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + if (value !== undefined) + reflectionMergePartial(this, message, value); + return message; + } + internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: Bar): Bar { + let message = target ?? this.create(), end = reader.pos + length; + while (reader.pos < end) { + let [fieldNo, wireType] = reader.tag(); + switch (fieldNo) { + case /* optional Foo tmp */ 1: + message.tmp = Foo.internalBinaryRead(reader, reader.uint32(), options, message.tmp); + break; + default: + let u = options.readUnknownField; + if (u === "throw") + throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`); + let d = reader.skip(wireType); + if (u !== false) + (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d); + } + } + return message; + } + internalBinaryWrite(message: Bar, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter { + /* optional Foo tmp = 1; */ + if (message.tmp) + Foo.internalBinaryWrite(message.tmp, writer.tag(1, WireType.LengthDelimited).fork(), options).join(); + let u = options.writeUnknownFields; + if (u !== false) + (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer); + return writer; + } +} +/** + * @generated MessageType for protobuf message Bar + */ +export const Bar = new Bar$Type(); +// @generated message type with reflection information, may provide speed optimized methods +class Yo$Type extends MessageType { + constructor() { + super("Yo", [ + { no: 1, name: "lol", kind: "enum", repeat: 1 /*RepeatType.PACKED*/, T: () => ["FOO", FOO] } + ]); + } + create(value?: PartialMessage): Yo { + const message = { lol: [] }; + globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + if (value !== undefined) + reflectionMergePartial(this, message, value); + return message; + } + internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: Yo): Yo { + let message = target ?? this.create(), end = reader.pos + length; + while (reader.pos < end) { + let [fieldNo, wireType] = reader.tag(); + switch (fieldNo) { + case /* repeated FOO lol */ 1: + if (wireType === WireType.LengthDelimited) + for (let e = reader.int32() + reader.pos; reader.pos < e;) + message.lol.push(reader.int32()); + else + message.lol.push(reader.int32()); + break; + default: + let u = options.readUnknownField; + if (u === "throw") + throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`); + let d = reader.skip(wireType); + if (u !== false) + (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d); + } + } + return message; + } + internalBinaryWrite(message: Yo, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter { + /* repeated FOO lol = 1; */ + if (message.lol.length) { + writer.tag(1, WireType.LengthDelimited).fork(); + for (let i = 0; i < message.lol.length; i++) + writer.int32(message.lol[i]); + writer.join(); + } + let u = options.writeUnknownFields; + if (u !== false) + (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer); + return writer; + } +} +/** + * @generated MessageType for protobuf message Yo + */ +export const Yo = new Yo$Type(); +// @generated message type with reflection information, may provide speed optimized methods +class Lol$Type extends MessageType { + constructor() { + super("Lol", [ + { no: 1, name: "lol", kind: "scalar", opt: true, T: 9 /*ScalarType.STRING*/ }, + { no: 2, name: "b", kind: "message", T: () => Bar } + ]); + } + create(value?: PartialMessage): Lol { + const message = {}; + globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + if (value !== undefined) + reflectionMergePartial(this, message, value); + return message; + } + internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: Lol): Lol { + let message = target ?? this.create(), end = reader.pos + length; + while (reader.pos < end) { + let [fieldNo, wireType] = reader.tag(); + switch (fieldNo) { + case /* optional string lol */ 1: + message.lol = reader.string(); + break; + case /* Bar b */ 2: + message.b = Bar.internalBinaryRead(reader, reader.uint32(), options, message.b); + break; + default: + let u = options.readUnknownField; + if (u === "throw") + throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`); + let d = reader.skip(wireType); + if (u !== false) + (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d); + } + } + return message; + } + internalBinaryWrite(message: Lol, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter { + /* optional string lol = 1; */ + if (message.lol !== undefined) + writer.tag(1, WireType.LengthDelimited).string(message.lol); + /* Bar b = 2; */ + if (message.b) + Bar.internalBinaryWrite(message.b, writer.tag(2, WireType.LengthDelimited).fork(), options).join(); + let u = options.writeUnknownFields; + if (u !== false) + (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer); + return writer; + } +} +/** + * @generated MessageType for protobuf message Lol + */ +export const Lol = new Lol$Type(); +// @generated message type with reflection information, may provide speed optimized methods +class Test$Type extends MessageType { + constructor() { + super("Test", [ + { no: 6, name: "meh", kind: "message", T: () => Lol }, + { no: 3, name: "hello", kind: "scalar", opt: true, T: 13 /*ScalarType.UINT32*/ }, + { no: 1, name: "foo", kind: "scalar", opt: true, T: 9 /*ScalarType.STRING*/ }, + { no: 7, name: "payload", kind: "scalar", opt: true, T: 12 /*ScalarType.BYTES*/ } + ]); + } + create(value?: PartialMessage): Test { + const message = {}; + globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + if (value !== undefined) + reflectionMergePartial(this, message, value); + return message; + } + internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: Test): Test { + let message = target ?? this.create(), end = reader.pos + length; + while (reader.pos < end) { + let [fieldNo, wireType] = reader.tag(); + switch (fieldNo) { + case /* optional Lol meh */ 6: + message.meh = Lol.internalBinaryRead(reader, reader.uint32(), options, message.meh); + break; + case /* optional uint32 hello */ 3: + message.hello = reader.uint32(); + break; + case /* optional string foo */ 1: + message.foo = reader.string(); + break; + case /* optional bytes payload */ 7: + message.payload = reader.bytes(); + break; + default: + let u = options.readUnknownField; + if (u === "throw") + throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`); + let d = reader.skip(wireType); + if (u !== false) + (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d); + } + } + return message; + } + internalBinaryWrite(message: Test, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter { + /* optional Lol meh = 6; */ + if (message.meh) + Lol.internalBinaryWrite(message.meh, writer.tag(6, WireType.LengthDelimited).fork(), options).join(); + /* optional uint32 hello = 3; */ + if (message.hello !== undefined) + writer.tag(3, WireType.Varint).uint32(message.hello); + /* optional string foo = 1; */ + if (message.foo !== undefined) + writer.tag(1, WireType.LengthDelimited).string(message.foo); + /* optional bytes payload = 7; */ + if (message.payload !== undefined) + writer.tag(7, WireType.LengthDelimited).bytes(message.payload); + let u = options.writeUnknownFields; + if (u !== false) + (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer); + return writer; + } +} +/** + * @generated MessageType for protobuf message Test + */ +export const Test = new Test$Type(); diff --git a/packages/protons-benchmark/src/protons/bench.ts b/packages/protons-benchmark/src/protons/bench.ts index 877991e..693cd59 100644 --- a/packages/protons-benchmark/src/protons/bench.ts +++ b/packages/protons-benchmark/src/protons/bench.ts @@ -1,7 +1,9 @@ /* eslint-disable import/export */ +/* eslint-disable complexity */ /* eslint-disable @typescript-eslint/no-namespace */ +/* eslint-disable @typescript-eslint/no-unnecessary-boolean-literal-compare */ -import { encodeMessage, decodeMessage, message, enumeration } from 'protons-runtime' +import { encodeMessage, decodeMessage, message, writer, enumeration } from 'protons-runtime' import type { Uint8ArrayList } from 'uint8arraylist' import type { Codec } from 'protons-runtime' @@ -14,18 +16,18 @@ export namespace Foo { export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, writer, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { - writer.fork() + w.fork() } if (obj.baz != null) { - writer.uint32(8) - writer.uint32(obj.baz) + w.uint32(8) + w.uint32(obj.baz) } if (opts.lengthDelimited !== false) { - writer.ldelim() + w.ldelim() } }, (reader, length) => { const obj: any = {} @@ -70,18 +72,27 @@ export namespace Bar { export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, writer, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { - writer.fork() + w.fork() } if (obj.tmp != null) { - writer.uint32(10) - Foo.codec().encode(obj.tmp, writer) + const mw = writer() + Foo.codec().encode(obj.tmp, mw, { + lengthDelimited: false, + writeDefaults: false + }) + const buf = mw.finish() + + if (buf.byteLength > 0) { + w.uint32(10) + w.bytes(buf) + } } if (opts.lengthDelimited !== false) { - writer.ldelim() + w.ldelim() } }, (reader, length) => { const obj: any = {} @@ -118,11 +129,13 @@ export namespace Bar { } export enum FOO { + NONE = 'NONE', LOL = 'LOL', ABE = 'ABE' } enum __FOOValues { + NONE = 0, LOL = 1, ABE = 3 } @@ -141,22 +154,20 @@ export namespace Yo { export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, writer, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { - writer.fork() + w.fork() } if (obj.lol != null) { for (const value of obj.lol) { - writer.uint32(8) - FOO.codec().encode(value, writer) + w.uint32(8) + FOO.codec().encode(value, w) } - } else { - throw new Error('Protocol error: required field "lol" was not found in object') } if (opts.lengthDelimited !== false) { - writer.ldelim() + w.ldelim() } }, (reader, length) => { const obj: any = { @@ -196,7 +207,7 @@ export namespace Yo { export interface Lol { lol?: string - b: Bar + b?: Bar } export namespace Lol { @@ -204,30 +215,35 @@ export namespace Lol { export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, writer, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { - writer.fork() + w.fork() } if (obj.lol != null) { - writer.uint32(10) - writer.string(obj.lol) + w.uint32(10) + w.string(obj.lol) } if (obj.b != null) { - writer.uint32(18) - Bar.codec().encode(obj.b, writer) - } else { - throw new Error('Protocol error: required field "b" was not found in object') + const mw = writer() + Bar.codec().encode(obj.b, mw, { + lengthDelimited: false, + writeDefaults: false + }) + const buf = mw.finish() + + if (buf.byteLength > 0) { + w.uint32(18) + w.bytes(buf) + } } if (opts.lengthDelimited !== false) { - writer.ldelim() + w.ldelim() } }, (reader, length) => { - const obj: any = { - b: undefined - } + const obj: any = {} const end = length == null ? reader.len : reader.pos + length @@ -247,10 +263,6 @@ export namespace Lol { } } - if (obj.b == null) { - throw new Error('Protocol error: value for required field "b" was not found in protobuf') - } - return obj }) } @@ -279,33 +291,42 @@ export namespace Test { export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, writer, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { - writer.fork() + w.fork() } if (obj.meh != null) { - writer.uint32(50) - Lol.codec().encode(obj.meh, writer) + const mw = writer() + Lol.codec().encode(obj.meh, mw, { + lengthDelimited: false, + writeDefaults: false + }) + const buf = mw.finish() + + if (buf.byteLength > 0) { + w.uint32(50) + w.bytes(buf) + } } if (obj.hello != null) { - writer.uint32(24) - writer.uint32(obj.hello) + w.uint32(24) + w.uint32(obj.hello) } if (obj.foo != null) { - writer.uint32(10) - writer.string(obj.foo) + w.uint32(10) + w.string(obj.foo) } if (obj.payload != null) { - writer.uint32(58) - writer.bytes(obj.payload) + w.uint32(58) + w.bytes(obj.payload) } if (opts.lengthDelimited !== false) { - writer.ldelim() + w.ldelim() } }, (reader, length) => { const obj: any = {} diff --git a/packages/protons-benchmark/src/protons/rpc.ts b/packages/protons-benchmark/src/protons/rpc.ts index 571ed08..75781fd 100644 --- a/packages/protons-benchmark/src/protons/rpc.ts +++ b/packages/protons-benchmark/src/protons/rpc.ts @@ -1,7 +1,9 @@ /* eslint-disable import/export */ +/* eslint-disable complexity */ /* eslint-disable @typescript-eslint/no-namespace */ +/* eslint-disable @typescript-eslint/no-unnecessary-boolean-literal-compare */ -import { encodeMessage, decodeMessage, message } from 'protons-runtime' +import { encodeMessage, decodeMessage, message, writer } from 'protons-runtime' import type { Uint8ArrayList } from 'uint8arraylist' import type { Codec } from 'protons-runtime' @@ -22,23 +24,23 @@ export namespace RPC { export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, writer, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { - writer.fork() + w.fork() } if (obj.subscribe != null) { - writer.uint32(8) - writer.bool(obj.subscribe) + w.uint32(8) + w.bool(obj.subscribe) } if (obj.topic != null) { - writer.uint32(18) - writer.string(obj.topic) + w.uint32(18) + w.string(obj.topic) } if (opts.lengthDelimited !== false) { - writer.ldelim() + w.ldelim() } }, (reader, length) => { const obj: any = {} @@ -91,48 +93,48 @@ export namespace RPC { export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, writer, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { - writer.fork() + w.fork() } if (obj.from != null) { - writer.uint32(10) - writer.bytes(obj.from) + w.uint32(10) + w.bytes(obj.from) } if (obj.data != null) { - writer.uint32(18) - writer.bytes(obj.data) + w.uint32(18) + w.bytes(obj.data) } if (obj.seqno != null) { - writer.uint32(26) - writer.bytes(obj.seqno) + w.uint32(26) + w.bytes(obj.seqno) } - if (obj.topic != null) { - writer.uint32(34) - writer.string(obj.topic) - } else { - throw new Error('Protocol error: required field "topic" was not found in object') + if (opts.writeDefaults === true || obj.topic !== '') { + w.uint32(34) + w.string(obj.topic) } if (obj.signature != null) { - writer.uint32(42) - writer.bytes(obj.signature) + w.uint32(42) + w.bytes(obj.signature) } if (obj.key != null) { - writer.uint32(50) - writer.bytes(obj.key) + w.uint32(50) + w.bytes(obj.key) } if (opts.lengthDelimited !== false) { - writer.ldelim() + w.ldelim() } }, (reader, length) => { - const obj: any = {} + const obj: any = { + topic: '' + } const end = length == null ? reader.len : reader.pos + length @@ -164,10 +166,6 @@ export namespace RPC { } } - if (obj.topic == null) { - throw new Error('Protocol error: value for required field "topic" was not found in protobuf') - } - return obj }) } @@ -196,52 +194,77 @@ export namespace RPC { export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, writer, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { - writer.fork() + w.fork() } if (obj.ihave != null) { for (const value of obj.ihave) { - writer.uint32(10) - RPC.ControlIHave.codec().encode(value, writer) + const mw = writer() + RPC.ControlIHave.codec().encode(value, mw, { + lengthDelimited: false, + writeDefaults: true + }) + const buf = mw.finish() + + w.uint32(10) + w.bytes(buf) } - } else { - throw new Error('Protocol error: required field "ihave" was not found in object') } if (obj.iwant != null) { for (const value of obj.iwant) { - writer.uint32(18) - RPC.ControlIWant.codec().encode(value, writer) + const mw = writer() + RPC.ControlIWant.codec().encode(value, mw, { + lengthDelimited: false, + writeDefaults: true + }) + const buf = mw.finish() + + w.uint32(18) + w.bytes(buf) } - } else { - throw new Error('Protocol error: required field "iwant" was not found in object') } if (obj.graft != null) { for (const value of obj.graft) { - writer.uint32(26) - RPC.ControlGraft.codec().encode(value, writer) + const mw = writer() + RPC.ControlGraft.codec().encode(value, mw, { + lengthDelimited: false, + writeDefaults: true + }) + const buf = mw.finish() + + w.uint32(26) + w.bytes(buf) } - } else { - throw new Error('Protocol error: required field "graft" was not found in object') } if (obj.prune != null) { for (const value of obj.prune) { - writer.uint32(34) - RPC.ControlPrune.codec().encode(value, writer) + const mw = writer() + RPC.ControlPrune.codec().encode(value, mw, { + lengthDelimited: false, + writeDefaults: true + }) + const buf = mw.finish() + + w.uint32(34) + w.bytes(buf) } - } else { - throw new Error('Protocol error: required field "prune" was not found in object') } if (opts.lengthDelimited !== false) { - writer.ldelim() + w.ldelim() } }, (reader, length) => { - const obj: any = {} + const obj: any = { + ihave: [], + iwant: [], + graft: [], + prune: [] + } const end = length == null ? reader.len : reader.pos + length @@ -250,19 +273,15 @@ export namespace RPC { switch (tag >>> 3) { case 1: - obj.ihave = obj.ihave ?? [] obj.ihave.push(RPC.ControlIHave.codec().decode(reader, reader.uint32())) break case 2: - obj.iwant = obj.iwant ?? [] obj.iwant.push(RPC.ControlIWant.codec().decode(reader, reader.uint32())) break case 3: - obj.graft = obj.graft ?? [] obj.graft.push(RPC.ControlGraft.codec().decode(reader, reader.uint32())) break case 4: - obj.prune = obj.prune ?? [] obj.prune.push(RPC.ControlPrune.codec().decode(reader, reader.uint32())) break default: @@ -271,27 +290,6 @@ export namespace RPC { } } - obj.ihave = obj.ihave ?? [] - obj.iwant = obj.iwant ?? [] - obj.graft = obj.graft ?? [] - obj.prune = obj.prune ?? [] - - if (obj.ihave == null) { - throw new Error('Protocol error: value for required field "ihave" was not found in protobuf') - } - - if (obj.iwant == null) { - throw new Error('Protocol error: value for required field "iwant" was not found in protobuf') - } - - if (obj.graft == null) { - throw new Error('Protocol error: value for required field "graft" was not found in protobuf') - } - - if (obj.prune == null) { - throw new Error('Protocol error: value for required field "prune" was not found in protobuf') - } - return obj }) } @@ -318,30 +316,30 @@ export namespace RPC { export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, writer, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { - writer.fork() + w.fork() } if (obj.topicID != null) { - writer.uint32(10) - writer.string(obj.topicID) + w.uint32(10) + w.string(obj.topicID) } if (obj.messageIDs != null) { for (const value of obj.messageIDs) { - writer.uint32(18) - writer.bytes(value) + w.uint32(18) + w.bytes(value) } - } else { - throw new Error('Protocol error: required field "messageIDs" was not found in object') } if (opts.lengthDelimited !== false) { - writer.ldelim() + w.ldelim() } }, (reader, length) => { - const obj: any = {} + const obj: any = { + messageIDs: [] + } const end = length == null ? reader.len : reader.pos + length @@ -353,7 +351,6 @@ export namespace RPC { obj.topicID = reader.string() break case 2: - obj.messageIDs = obj.messageIDs ?? [] obj.messageIDs.push(reader.bytes()) break default: @@ -362,12 +359,6 @@ export namespace RPC { } } - obj.messageIDs = obj.messageIDs ?? [] - - if (obj.messageIDs == null) { - throw new Error('Protocol error: value for required field "messageIDs" was not found in protobuf') - } - return obj }) } @@ -393,25 +384,25 @@ export namespace RPC { export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, writer, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { - writer.fork() + w.fork() } if (obj.messageIDs != null) { for (const value of obj.messageIDs) { - writer.uint32(10) - writer.bytes(value) + w.uint32(10) + w.bytes(value) } - } else { - throw new Error('Protocol error: required field "messageIDs" was not found in object') } if (opts.lengthDelimited !== false) { - writer.ldelim() + w.ldelim() } }, (reader, length) => { - const obj: any = {} + const obj: any = { + messageIDs: [] + } const end = length == null ? reader.len : reader.pos + length @@ -420,7 +411,6 @@ export namespace RPC { switch (tag >>> 3) { case 1: - obj.messageIDs = obj.messageIDs ?? [] obj.messageIDs.push(reader.bytes()) break default: @@ -429,12 +419,6 @@ export namespace RPC { } } - obj.messageIDs = obj.messageIDs ?? [] - - if (obj.messageIDs == null) { - throw new Error('Protocol error: value for required field "messageIDs" was not found in protobuf') - } - return obj }) } @@ -460,18 +444,18 @@ export namespace RPC { export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, writer, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { - writer.fork() + w.fork() } if (obj.topicID != null) { - writer.uint32(10) - writer.string(obj.topicID) + w.uint32(10) + w.string(obj.topicID) } if (opts.lengthDelimited !== false) { - writer.ldelim() + w.ldelim() } }, (reader, length) => { const obj: any = {} @@ -518,35 +502,42 @@ export namespace RPC { export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, writer, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { - writer.fork() + w.fork() } if (obj.topicID != null) { - writer.uint32(10) - writer.string(obj.topicID) + w.uint32(10) + w.string(obj.topicID) } if (obj.peers != null) { for (const value of obj.peers) { - writer.uint32(18) - RPC.PeerInfo.codec().encode(value, writer) + const mw = writer() + RPC.PeerInfo.codec().encode(value, mw, { + lengthDelimited: false, + writeDefaults: true + }) + const buf = mw.finish() + + w.uint32(18) + w.bytes(buf) } - } else { - throw new Error('Protocol error: required field "peers" was not found in object') } if (obj.backoff != null) { - writer.uint32(24) - writer.uint64(obj.backoff) + w.uint32(24) + w.uint64(obj.backoff) } if (opts.lengthDelimited !== false) { - writer.ldelim() + w.ldelim() } }, (reader, length) => { - const obj: any = {} + const obj: any = { + peers: [] + } const end = length == null ? reader.len : reader.pos + length @@ -558,7 +549,6 @@ export namespace RPC { obj.topicID = reader.string() break case 2: - obj.peers = obj.peers ?? [] obj.peers.push(RPC.PeerInfo.codec().decode(reader, reader.uint32())) break case 3: @@ -570,12 +560,6 @@ export namespace RPC { } } - obj.peers = obj.peers ?? [] - - if (obj.peers == null) { - throw new Error('Protocol error: value for required field "peers" was not found in protobuf') - } - return obj }) } @@ -602,23 +586,23 @@ export namespace RPC { export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, writer, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { - writer.fork() + w.fork() } if (obj.peerID != null) { - writer.uint32(10) - writer.bytes(obj.peerID) + w.uint32(10) + w.bytes(obj.peerID) } if (obj.signedPeerRecord != null) { - writer.uint32(18) - writer.bytes(obj.signedPeerRecord) + w.uint32(18) + w.bytes(obj.signedPeerRecord) } if (opts.lengthDelimited !== false) { - writer.ldelim() + w.ldelim() } }, (reader, length) => { const obj: any = {} @@ -661,39 +645,61 @@ export namespace RPC { export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, writer, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { - writer.fork() + w.fork() } if (obj.subscriptions != null) { for (const value of obj.subscriptions) { - writer.uint32(10) - RPC.SubOpts.codec().encode(value, writer) + const mw = writer() + RPC.SubOpts.codec().encode(value, mw, { + lengthDelimited: false, + writeDefaults: true + }) + const buf = mw.finish() + + w.uint32(10) + w.bytes(buf) } - } else { - throw new Error('Protocol error: required field "subscriptions" was not found in object') } if (obj.messages != null) { for (const value of obj.messages) { - writer.uint32(18) - RPC.Message.codec().encode(value, writer) + const mw = writer() + RPC.Message.codec().encode(value, mw, { + lengthDelimited: false, + writeDefaults: true + }) + const buf = mw.finish() + + w.uint32(18) + w.bytes(buf) } - } else { - throw new Error('Protocol error: required field "messages" was not found in object') } if (obj.control != null) { - writer.uint32(26) - RPC.ControlMessage.codec().encode(obj.control, writer) + const mw = writer() + RPC.ControlMessage.codec().encode(obj.control, mw, { + lengthDelimited: false, + writeDefaults: false + }) + const buf = mw.finish() + + if (buf.byteLength > 0) { + w.uint32(26) + w.bytes(buf) + } } if (opts.lengthDelimited !== false) { - writer.ldelim() + w.ldelim() } }, (reader, length) => { - const obj: any = {} + const obj: any = { + subscriptions: [], + messages: [] + } const end = length == null ? reader.len : reader.pos + length @@ -702,11 +708,9 @@ export namespace RPC { switch (tag >>> 3) { case 1: - obj.subscriptions = obj.subscriptions ?? [] obj.subscriptions.push(RPC.SubOpts.codec().decode(reader, reader.uint32())) break case 2: - obj.messages = obj.messages ?? [] obj.messages.push(RPC.Message.codec().decode(reader, reader.uint32())) break case 3: @@ -718,17 +722,6 @@ export namespace RPC { } } - obj.subscriptions = obj.subscriptions ?? [] - obj.messages = obj.messages ?? [] - - if (obj.subscriptions == null) { - throw new Error('Protocol error: value for required field "subscriptions" was not found in protobuf') - } - - if (obj.messages == null) { - throw new Error('Protocol error: value for required field "messages" was not found in protobuf') - } - return obj }) } diff --git a/packages/protons-benchmark/src/rpc.proto b/packages/protons-benchmark/src/rpc.proto index 3ddce5b..eb1a81d 100644 --- a/packages/protons-benchmark/src/rpc.proto +++ b/packages/protons-benchmark/src/rpc.proto @@ -14,7 +14,7 @@ message RPC { optional bytes from = 1; optional bytes data = 2; optional bytes seqno = 3; - required string topic = 4; + string topic = 4; optional bytes signature = 5; optional bytes key = 6; } From de0d9f374512089d5b686f1a73699a810e861155 Mon Sep 17 00:00:00 2001 From: achingbrain Date: Wed, 12 Oct 2022 11:27:04 +0100 Subject: [PATCH 2/3] chore: linting --- packages/protons-benchmark/package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/protons-benchmark/package.json b/packages/protons-benchmark/package.json index 41dc330..ac357f0 100644 --- a/packages/protons-benchmark/package.json +++ b/packages/protons-benchmark/package.json @@ -56,6 +56,7 @@ }, "ignorePatterns": [ "src/pbjs/*", + "src/protobuf-ts/*", "src/protobufjs/*" ] }, From 7fa06a99a9cc3e58456133e373d15abb79f60f87 Mon Sep 17 00:00:00 2001 From: achingbrain Date: Wed, 12 Oct 2022 11:53:29 +0100 Subject: [PATCH 3/3] chore: add missing dep --- packages/protons-benchmark/package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/protons-benchmark/package.json b/packages/protons-benchmark/package.json index ac357f0..7c78c4d 100644 --- a/packages/protons-benchmark/package.json +++ b/packages/protons-benchmark/package.json @@ -71,6 +71,7 @@ }, "dependencies": { "@protobuf-ts/plugin": "^2.8.1", + "@protobuf-ts/runtime": "^2.8.1", "@types/benchmark": "^2.1.1", "aegir": "^37.0.5", "benchmark": "^2.1.4",