From 744d00717ae110c0bfbabad04727e7619b041904 Mon Sep 17 00:00:00 2001 From: achingbrain Date: Wed, 18 Mar 2026 15:50:42 +0100 Subject: [PATCH 1/4] feat: add streaming decode To be able to do things like find list entries without reading the full list first, add a streaming decode method that makes message fields available as they are decoded. Optionally yield collections after parsing. --- packages/protons-runtime/src/codec.ts | 49 +- packages/protons-runtime/src/codecs/enum.ts | 2 +- .../protons-runtime/src/codecs/message.ts | 6 +- packages/protons-runtime/src/decode.ts | 2 +- packages/protons-runtime/src/encode.ts | 2 +- packages/protons-runtime/src/index.ts | 8 +- packages/protons-runtime/src/stream.ts | 9 + packages/protons/package.json | 1 + packages/protons/src/index.ts | 312 ++- packages/protons/test/fixtures/basic.ts | 122 +- packages/protons/test/fixtures/bitswap.ts | 482 ++++- packages/protons/test/fixtures/circuit.ts | 188 +- .../test/fixtures/custom-option-jstype.ts | 252 ++- packages/protons/test/fixtures/daemon.ts | 1753 +++++++++++++++-- packages/protons/test/fixtures/dht.ts | 349 +++- packages/protons/test/fixtures/maps.ts | 610 +++++- packages/protons/test/fixtures/noise.ts | 136 +- packages/protons/test/fixtures/oneof.ts | 240 ++- packages/protons/test/fixtures/optional.ts | 326 ++- packages/protons/test/fixtures/peer.ts | 289 ++- packages/protons/test/fixtures/proto2.ts | 67 +- .../protons/test/fixtures/protons-options.ts | 222 ++- packages/protons/test/fixtures/repeated.ts | 447 ++++- packages/protons/test/fixtures/singular.ts | 344 +++- packages/protons/test/fixtures/test.ts | 372 +++- .../protons/test/streaming-decode.spec.ts | 103 + 26 files changed, 6296 insertions(+), 397 deletions(-) create mode 100644 packages/protons-runtime/src/stream.ts create mode 100644 packages/protons/test/streaming-decode.spec.ts diff --git a/packages/protons-runtime/src/codec.ts b/packages/protons-runtime/src/codec.ts index bf02047..0f06795 100644 --- a/packages/protons-runtime/src/codec.ts +++ b/packages/protons-runtime/src/codec.ts @@ -1,13 +1,13 @@ import type { Writer, Reader } from './index.ts' // https://developers.google.com/protocol-buffers/docs/encoding#structure -export enum CODEC_TYPES { - VARINT = 0, - BIT64, - LENGTH_DELIMITED, - START_GROUP, - END_GROUP, - BIT32 +export const CODEC_TYPES = { + VARINT: 0, + BIT64: 1, + LENGTH_DELIMITED: 2, + START_GROUP: 3, + END_GROUP: 4, + BIT32: 5 } export interface EncodeOptions { @@ -59,18 +59,45 @@ export interface DecodeFunction { (reader: Reader, length?: number, opts?: DecodeOptions): T } -export interface Codec { +export interface StreamingDecodeOptions extends DecodeOptions { + /** + * If true, yield a value event for repeated elements/maps, otherwise only + * yield events for collection members + * + * @default false + */ + emitCollections?: false +} + +export interface StreamingDecodeWithCollectionsOptions extends DecodeOptions { + /** + * If true, yield a value event for repeated elements/maps, otherwise only + * yield events for collection members + * + * @default false + */ + emitCollections: true +} + +export interface StreamFunction { + (reader: Reader, length?: number, opts?: StreamingDecodeOptions): Generator + (reader: Reader, length?: number, opts?: StreamingDecodeWithCollectionsOptions): Generator +} + +export interface Codec { name: string - type: CODEC_TYPES + type: number encode: EncodeFunction decode: DecodeFunction + stream: StreamFunction } -export function createCodec (name: string, type: CODEC_TYPES, encode: EncodeFunction, decode: DecodeFunction): Codec { +export function createCodec (name: string, type: number, encode: EncodeFunction, decode: DecodeFunction, stream: StreamFunction): Codec { return { name, type, encode, - decode + decode, + stream } } diff --git a/packages/protons-runtime/src/codecs/enum.ts b/packages/protons-runtime/src/codecs/enum.ts index fb83643..68a6777 100644 --- a/packages/protons-runtime/src/codecs/enum.ts +++ b/packages/protons-runtime/src/codecs/enum.ts @@ -1,7 +1,7 @@ import { createCodec, CODEC_TYPES } from '../codec.ts' import type { DecodeFunction, EncodeFunction, Codec } from '../codec.ts' -export function enumeration (v: any): Codec { +export function enumeration (v: any): Codec { function findValue (val: string | number): number { // Use the reverse mapping to look up the enum key for the stored value // https://www.typescriptlang.org/docs/handbook/enums.html#reverse-mappings diff --git a/packages/protons-runtime/src/codecs/message.ts b/packages/protons-runtime/src/codecs/message.ts index 0c7c2d5..3f7bed3 100644 --- a/packages/protons-runtime/src/codecs/message.ts +++ b/packages/protons-runtime/src/codecs/message.ts @@ -1,10 +1,10 @@ import { createCodec, CODEC_TYPES } from '../codec.ts' -import type { EncodeFunction, DecodeFunction, Codec } from '../codec.ts' +import type { EncodeFunction, DecodeFunction, Codec, StreamFunction } from '../codec.ts' export interface Factory { new (obj: A): T } -export function message (encode: EncodeFunction, decode: DecodeFunction): Codec { - return createCodec('message', CODEC_TYPES.LENGTH_DELIMITED, encode, decode) +export function message (encode: EncodeFunction, decode: DecodeFunction, stream: StreamFunction): Codec { + return createCodec('message', CODEC_TYPES.LENGTH_DELIMITED, encode, decode, stream) } diff --git a/packages/protons-runtime/src/decode.ts b/packages/protons-runtime/src/decode.ts index 18ef696..73ca27a 100644 --- a/packages/protons-runtime/src/decode.ts +++ b/packages/protons-runtime/src/decode.ts @@ -2,7 +2,7 @@ import { createReader } from './utils/reader.ts' import type { Codec, DecodeOptions } from './codec.ts' import type { Uint8ArrayList } from 'uint8arraylist' -export function decodeMessage (buf: Uint8Array | Uint8ArrayList, codec: Pick, 'decode'>, opts?: DecodeOptions): T { +export function decodeMessage (buf: Uint8Array | Uint8ArrayList, codec: Pick, 'decode'>, opts?: DecodeOptions): T { const reader = createReader(buf) return codec.decode(reader, undefined, opts) diff --git a/packages/protons-runtime/src/encode.ts b/packages/protons-runtime/src/encode.ts index 5ac8c39..0ae7963 100644 --- a/packages/protons-runtime/src/encode.ts +++ b/packages/protons-runtime/src/encode.ts @@ -1,7 +1,7 @@ import { createWriter } from './utils/writer.ts' import type { Codec } from './codec.ts' -export function encodeMessage (message: Partial, codec: Pick, 'encode'>): Uint8Array { +export function encodeMessage (message: Partial, codec: Pick, 'encode'>): Uint8Array { const w = createWriter() codec.encode(message, w, { diff --git a/packages/protons-runtime/src/index.ts b/packages/protons-runtime/src/index.ts index 29d4279..9bf9efe 100644 --- a/packages/protons-runtime/src/index.ts +++ b/packages/protons-runtime/src/index.ts @@ -14,7 +14,7 @@ import type { Codec } from './codec.ts' export interface FieldDef { name: string - codec: Codec + codec: Codec optional?: true repeats?: true packed?: true @@ -28,11 +28,15 @@ export { encodeMessage } from './encode.ts' +export { + streamMessage +} from './stream.ts' + export { enumeration } from './codecs/enum.ts' export { message } from './codecs/message.ts' export { createReader as reader } from './utils/reader.ts' export { createWriter as writer } from './utils/writer.ts' -export type { Codec, EncodeOptions, DecodeOptions } from './codec.ts' +export type { Codec, EncodeOptions, DecodeOptions, StreamingDecodeOptions, StreamingDecodeWithCollectionsOptions } from './codec.ts' export interface Writer { /** diff --git a/packages/protons-runtime/src/stream.ts b/packages/protons-runtime/src/stream.ts new file mode 100644 index 0000000..8c07b52 --- /dev/null +++ b/packages/protons-runtime/src/stream.ts @@ -0,0 +1,9 @@ +import { createReader } from './utils/reader.ts' +import type { Codec, StreamingDecodeOptions } from './codec.ts' +import type { Uint8ArrayList } from 'uint8arraylist' + +export function * streamMessage (buf: Uint8Array | Uint8ArrayList, codec: Pick, 'stream'>, opts?: StreamingDecodeOptions): Generator { + const reader = createReader(buf) + + yield * codec.stream(reader, undefined, opts) +} diff --git a/packages/protons/package.json b/packages/protons/package.json index 8bc3120..9acb465 100644 --- a/packages/protons/package.json +++ b/packages/protons/package.json @@ -56,6 +56,7 @@ }, "devDependencies": { "aegir": "^47.0.5", + "it-all": "^3.0.9", "long": "^5.2.0", "pbjs": "^0.0.14", "protobufjs": "^7.0.0", diff --git a/packages/protons/src/index.ts b/packages/protons/src/index.ts index 570715d..7cb11da 100644 --- a/packages/protons/src/index.ts +++ b/packages/protons/src/index.ts @@ -199,13 +199,19 @@ import { promisify } from 'util' import { main as pbjs } from 'protobufjs-cli/pbjs.js' import { NoMessagesFoundError, ParseError } from 'protons-runtime' -export enum CODEC_TYPES { - VARINT = 0, - BIT64, - LENGTH_DELIMITED, - START_GROUP, - END_GROUP, - BIT32 +export const CODEC_TYPES = { + VARINT: 0, + BIT64: 1, + LENGTH_DELIMITED: 2, + START_GROUP: 3, + END_GROUP: 4, + BIT32: 5 +} + +interface StreamEvent { + name: string + fields: string[] + collection: boolean } function pathWithExtension (input: string, extension: string, outputDir?: string): string { @@ -213,6 +219,18 @@ function pathWithExtension (input: string, extension: string, outputDir?: string return path.join(output, path.basename(input).split('.').slice(0, -1).join('.') + extension) } +function camelize (input: string): string { + return `${input.substring(0, 1).toUpperCase()}${input.substring(1)}` +} + +function interfacesOrEmpty (evts: StreamEvent[]): string { + if (evts.length === 0) { + return '{}' + } + + return evts.map(evt => evt.name).join(' | ') +} + /** * This will be removed in a future release * @@ -493,7 +511,7 @@ function findDef (typeName: string, classDef: MessageDef, moduleDef: ModuleDef): throw new Error(`Could not resolve type name "${typeName}"`) } -function createDefaultObject (fields: Record, messageDef: MessageDef, moduleDef: ModuleDef): string { +function createDefaultObject (fields: Record, messageDef: MessageDef, moduleDef: ModuleDef, indent = ''): string { const output = Object.entries(fields) .map(([name, fieldDef]) => { if (fieldDef.map) { @@ -556,12 +574,37 @@ function createDefaultObject (fields: Record, messageDef: Mess return `${name}: ${defaultValue}` }) .filter(Boolean) - .join(',\n ') + .join(`,\n ${indent}`) + + if (output !== '') { + return ` + ${indent}${output} + ${indent}` + } + + return '' +} + +function createLimitObject (fields: Record): string { + const output = Object.entries(fields) + .map(([name, fieldDef]) => { + if (fieldDef.map) { + return `${name}: 0` + } + + if (fieldDef.repeated) { + return `${name}: 0` + } + + return '' + }) + .filter(Boolean) + .join(',\n ') if (output !== '') { return ` - ${output} - ` + ${output} + ` } return '' @@ -585,7 +628,7 @@ const encoders: Record = { uint64: 'uint64' } -const codecTypes: Record = { +const codecTypes: Record = { bool: CODEC_TYPES.VARINT, bytes: CODEC_TYPES.LENGTH_DELIMITED, double: CODEC_TYPES.BIT64, @@ -693,7 +736,7 @@ enum __${messageDef.name}Values { } export namespace ${messageDef.name} { - export const codec = (): Codec<${messageDef.name}> => { + export const codec = (): Codec<${messageDef.name}, any, any> => { return enumeration<${messageDef.name}>(__${messageDef.name}Values) } } @@ -717,9 +760,12 @@ export namespace ${messageDef.name} { // import relevant modules moduleDef.addImport('protons-runtime', 'encodeMessage') moduleDef.addImport('protons-runtime', 'decodeMessage') + moduleDef.addImport('protons-runtime', 'streamMessage') moduleDef.addImport('protons-runtime', 'message') moduleDef.addTypeImport('protons-runtime', 'Codec') moduleDef.addTypeImport('protons-runtime', 'DecodeOptions') + moduleDef.addTypeImport('protons-runtime', 'StreamingDecodeOptions') + moduleDef.addTypeImport('protons-runtime', 'StreamingDecodeWithCollectionsOptions') moduleDef.addTypeImport('uint8arraylist', 'Uint8ArrayList') const interfaceFields = defineFields(fields, messageDef, moduleDef) @@ -870,6 +916,7 @@ export interface ${messageDef.name} { const enforceOneOfEncoding = createOneOfEncoding(messageDef) const enforceOneOfDecoding = createOneOfDecoding(messageDef) + const streamEvents: StreamEvent[] = [] const decodeFields = Object.entries(fields) .map(([fieldName, fieldDef]) => { @@ -990,12 +1037,196 @@ export interface ${messageDef.name} { }) .join('\n ') + const streamFields = Object.entries(fields) + .map(([fieldName, fieldDef]) => { + let valueDef = `${findJsTypeName(fieldDef.type, messageDef, moduleDef, fieldDef)}${fieldDef.repeated ? '[]' : ''}` + + if (fieldDef.map) { + valueDef = `Map<${findJsTypeName(fieldDef.keyType, messageDef, moduleDef, fieldDef)}, ${findJsTypeName(fieldDef.valueType, messageDef, moduleDef, fieldDef)}>` + } + + streamEvents.push({ + name: `${messageDef.name}${camelize(fieldName)}FieldEvent`, + fields: [ + `field: '${fieldName}'`, + `value: ${valueDef}` + ], + collection: fieldDef.map || fieldDef.repeated + }) + + if (fieldDef.map) { + streamEvents.push({ + name: `${messageDef.name}${camelize(fieldName)}EntryEvent`, + fields: [ + `field: '${fieldName}$entry'`, + `key: ${findJsTypeName(fieldDef.keyType, messageDef, moduleDef, fieldDef)}`, + `value: ${findJsTypeName(fieldDef.valueType, messageDef, moduleDef, fieldDef)}` + ], + collection: false + }) + } else if (fieldDef.repeated) { + streamEvents.push({ + name: `${messageDef.name}${camelize(fieldName)}ValueEvent`, + fields: [ + `field: '${fieldName}$value'`, + 'index: number', + `value: ${findJsTypeName(fieldDef.type, messageDef, moduleDef, fieldDef)}` + ], + collection: false + }) + } + + function createStreamField (fieldName: string, fieldDef: FieldDef): string { + let codec: string = encoders[fieldDef.type] + let type: string = fieldDef.type + + if (codec == null) { + if (fieldDef.enum) { + moduleDef.addImport('protons-runtime', 'enumeration') + type = 'enum' + } else { + moduleDef.addImport('protons-runtime', 'message') + type = 'message' + } + + const typeName = findJsTypeName(fieldDef.type, messageDef, moduleDef, fieldDef) + codec = `${typeName}.codec()` + } + + // override setting type on js object + const jsTypeOverride = findJsTypeOverride(fieldDef.type, fieldDef) + + let fieldOpts = '' + + if (fieldDef.message) { + let suffix = '' + + if (fieldDef.repeated) { + suffix = '$' + } + + fieldOpts = `, { + limits: opts.limits?.${fieldName}${suffix} + }` + } + + if (fieldDef.map) { + fieldOpts = `, { + limits: { + value: opts.limits?.${fieldName}$value + } + }` + + // do not pass limit opts to map value types that are enums or + // primitives - only support messages + if (types[fieldDef.valueType] != null) { + // primmitive type + fieldOpts = '' + } else { + const valueType = findDef(fieldDef.valueType, messageDef, moduleDef) + + if (isEnumDef(valueType)) { + // enum type + fieldOpts = '' + } + } + } + + const parseValue = `${decoderGenerators[type] == null + ? `${codec}.decode(reader${type === 'message' + ? `, reader.uint32()${fieldOpts}` + : ''})` + : decoderGenerators[type](jsTypeOverride)}` + + if (fieldDef.map) { + moduleDef.addImport('protons-runtime', 'MaxSizeError') + + let limit = ` + if (opts.limits?.${fieldName} != null && (opts.emitCollections === true ? obj.${fieldName}.size === opts.limits.${fieldName} : obj.${fieldName} === opts.limits.${fieldName})) { + throw new MaxSizeError('Decode error - map field "${fieldName}" had too many elements') + } +` + + if (fieldDef.lengthLimit != null) { + limit += ` + if (opts.emitCollections === true ? obj.${fieldName}.size === ${fieldDef.lengthLimit} : obj.${fieldName} === ${fieldDef.lengthLimit}) { + throw new MaxSizeError('Decode error - map field "${fieldName}" had too many elements') + } +` + } + + return `case ${fieldDef.id}: {${limit} + const entry = ${parseValue} + + yield { + field: '${fieldName}', + key: entry.key, + value: entry.value + } + + if (opts.emitCollections === true) { + obj.${fieldName}.set(entry.key, entry.value) + } else { + obj.${fieldName}++ + } + + break + }` + } else if (fieldDef.repeated) { + moduleDef.addImport('protons-runtime', 'MaxLengthError') + + let limit = ` + if (opts.limits?.${fieldName} != null && (opts.emitCollections === true ? obj.${fieldName}.length === opts.limits.${fieldName} : obj.${fieldName} === opts.limits.${fieldName})) { + throw new MaxLengthError('Decode error - map field "${fieldName}" had too many elements') + } +` + + if (fieldDef.lengthLimit != null) { + limit += ` + if (opts.emitCollections === true ? obj.${fieldName}.length === ${fieldDef.lengthLimit} : obj.${fieldName} === ${fieldDef.lengthLimit}) { + throw new MaxLengthError('Decode error - repeated field "${fieldName}" had too many elements') + } +` + } + + return `case ${fieldDef.id}: {${limit} + const value = ${parseValue} + + yield { + field: '${fieldName}$value', + index: opts.emitCollections === true ? obj.${fieldName}.length : obj.${fieldName}, + value + } + + if (opts.emitCollections === true) { + obj.${fieldName}.push(value) + } else { + obj.${fieldName}++ + } + + break + }` + } + + return `case ${fieldDef.id}: { + yield { + field: '${fieldName}', + value: ${parseValue} + } + break + }` + } + + return createStreamField(fieldName, fieldDef) + }) + .join('\n ') + interfaceCodecDef = ` - let _codec: Codec<${messageDef.name}> + let _codec: Codec<${messageDef.name}, ${messageDef.name}StreamEvent, ${messageDef.name}StreamCollectionsEvent> - export const codec = (): Codec<${messageDef.name}> => { + export const codec = (): Codec<${messageDef.name}, ${messageDef.name}StreamEvent, ${messageDef.name}StreamCollectionsEvent> => { if (_codec == null) { - _codec = message<${messageDef.name}>((obj, w, opts = {}) => { + _codec = message<${messageDef.name}, ${messageDef.name}StreamEvent, ${messageDef.name}StreamCollectionsEvent>((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -1020,18 +1251,63 @@ ${enforceOneOfEncoding}${encodeFields === '' ? '' : `${encodeFields}\n`} } ${enforceOneOfDecoding === '' ? '' : `${enforceOneOfDecoding}\n`} return obj + }, function * (reader, length, opts = {}) { + let obj: any + + if (opts.emitCollections === true) { + obj = {${createDefaultObject(fields, messageDef, moduleDef, ' ')}} + } else { + obj = {${createLimitObject(fields)}} + } + + const end = length == null ? reader.len : reader.pos + length + + while (reader.pos < end) { + const tag = reader.uint32() + + switch (tag >>> 3) {${streamFields === '' ? '' : `\n ${streamFields}`} + default: { + reader.skipType(tag & 7) + break + } + } + } +${enforceOneOfDecoding === '' ? '' : `${enforceOneOfDecoding}\n`} + if (opts.emitCollections === true) { + for (const [key, value] of Object.entries(obj)) { + if (Array.isArray(value) || value instanceof Map) { + yield { + field: key, + value + } + } + } + } }) } return _codec } - export const encode = (obj: Partial<${messageDef.name}>): Uint8Array => { + ${streamEvents.map(evt => `export interface ${evt.name} { + ${evt.fields.join('\n ')} + }`).join('\n\n ')} + + export type ${messageDef.name}StreamEvent = ${interfacesOrEmpty(streamEvents.filter(evt => !evt.collection))} + export type ${messageDef.name}StreamCollectionsEvent = ${interfacesOrEmpty(streamEvents.filter(evt => evt.collection))} + + export function encode (obj: Partial<${messageDef.name}>): Uint8Array { return encodeMessage(obj, ${messageDef.name}.codec()) } - export const decode = (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions<${messageDef.name}>): ${messageDef.name} => { + export function decode (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions<${messageDef.name}>): ${messageDef.name} { return decodeMessage(buf, ${messageDef.name}.codec(), opts) + } + + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions<${messageDef.name}>): Generator<${messageDef.name}StreamEvent> + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions<${messageDef.name}>): Generator<${messageDef.name}StreamCollectionsEvent> + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + return streamMessage(buf, ${messageDef.name}.codec(), opts) }` return ` diff --git a/packages/protons/test/fixtures/basic.ts b/packages/protons/test/fixtures/basic.ts index 4ea2ef8..7ac1f08 100644 --- a/packages/protons/test/fixtures/basic.ts +++ b/packages/protons/test/fixtures/basic.ts @@ -1,5 +1,13 @@ -import { decodeMessage, encodeMessage, message } from 'protons-runtime' -import type { Codec, DecodeOptions } from 'protons-runtime' +/* eslint-disable import/export */ +/* eslint-disable complexity */ +/* eslint-disable @typescript-eslint/no-namespace */ +/* eslint-disable @typescript-eslint/no-unnecessary-boolean-literal-compare */ +/* eslint-disable @typescript-eslint/no-empty-interface */ +/* eslint-disable import/consistent-type-specifier-style */ +/* eslint-disable @typescript-eslint/no-unused-vars */ + +import { decodeMessage, encodeMessage, message, streamMessage } from 'protons-runtime' +import type { Codec, DecodeOptions, StreamingDecodeOptions, StreamingDecodeWithCollectionsOptions } from 'protons-runtime' import type { Uint8ArrayList } from 'uint8arraylist' export interface Basic { @@ -8,11 +16,11 @@ export interface Basic { } export namespace Basic { - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -57,29 +65,86 @@ export namespace Basic { } return obj + }, function * (reader, length, opts = {}) { + let obj: any + + if (opts.emitCollections === true) { + obj = { + num: 0 + } + } else { + obj = {} + } + + const end = length == null ? reader.len : reader.pos + length + + while (reader.pos < end) { + const tag = reader.uint32() + + switch (tag >>> 3) { + case 1: { + yield { + field: 'foo', + value: reader.string() + } + break + } + case 2: { + yield { + field: 'num', + value: reader.int32() + } + break + } + default: { + reader.skipType(tag & 7) + break + } + } + } + }) } return _codec } - export const encode = (obj: Partial): Uint8Array => { + export interface BasicFooFieldEvent { + field: 'foo' + value: string + } + + export interface BasicNumFieldEvent { + field: 'num' + value: number + } + + export type BasicStreamEvent = BasicFooFieldEvent | BasicNumFieldEvent + export type BasicStreamCollectionsEvent = {} + + export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, Basic.codec()) } - export const decode = (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Basic => { + export function decode (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Basic { return decodeMessage(buf, Basic.codec(), opts) } + + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + return streamMessage(buf, Basic.codec(), opts) + } } export interface Empty {} export namespace Empty { - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -104,17 +169,50 @@ export namespace Empty { } return obj + }, function * (reader, length, opts = {}) { + let obj: any + + if (opts.emitCollections === true) { + obj = {} + } else { + obj = {} + } + + const end = length == null ? reader.len : reader.pos + length + + while (reader.pos < end) { + const tag = reader.uint32() + + switch (tag >>> 3) { + default: { + reader.skipType(tag & 7) + break + } + } + } + }) } return _codec } - export const encode = (obj: Partial): Uint8Array => { + + + export type EmptyStreamEvent = {} + export type EmptyStreamCollectionsEvent = {} + + export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, Empty.codec()) } - export const decode = (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Empty => { + export function decode (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Empty { return decodeMessage(buf, Empty.codec(), opts) } + + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + return streamMessage(buf, Empty.codec(), opts) + } } diff --git a/packages/protons/test/fixtures/bitswap.ts b/packages/protons/test/fixtures/bitswap.ts index 2a9d20f..1ea8f38 100644 --- a/packages/protons/test/fixtures/bitswap.ts +++ b/packages/protons/test/fixtures/bitswap.ts @@ -1,8 +1,14 @@ +/* eslint-disable import/export */ /* eslint-disable complexity */ +/* eslint-disable @typescript-eslint/no-namespace */ +/* eslint-disable @typescript-eslint/no-unnecessary-boolean-literal-compare */ +/* eslint-disable @typescript-eslint/no-empty-interface */ +/* eslint-disable import/consistent-type-specifier-style */ +/* eslint-disable @typescript-eslint/no-unused-vars */ -import { decodeMessage, encodeMessage, enumeration, MaxLengthError, message } from 'protons-runtime' +import { decodeMessage, encodeMessage, enumeration, MaxLengthError, message, streamMessage } from 'protons-runtime' import { alloc as uint8ArrayAlloc } from 'uint8arrays/alloc' -import type { Codec, DecodeOptions } from 'protons-runtime' +import type { Codec, DecodeOptions, StreamingDecodeOptions, StreamingDecodeWithCollectionsOptions } from 'protons-runtime' import type { Uint8ArrayList } from 'uint8arraylist' export interface Message { @@ -31,7 +37,7 @@ export namespace Message { } export namespace WantType { - export const codec = (): Codec => { + export const codec = (): Codec => { return enumeration(__WantTypeValues) } } @@ -45,11 +51,11 @@ export namespace Message { } export namespace Entry { - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -124,26 +130,122 @@ export namespace Message { } return obj + }, function * (reader, length, opts = {}) { + let obj: any + + if (opts.emitCollections === true) { + obj = { + block: uint8ArrayAlloc(0), + priority: 0, + wantType: WantType.Block, + sendDontHave: false + } + } else { + obj = {} + } + + const end = length == null ? reader.len : reader.pos + length + + while (reader.pos < end) { + const tag = reader.uint32() + + switch (tag >>> 3) { + case 1: { + yield { + field: 'block', + value: reader.bytes() + } + break + } + case 2: { + yield { + field: 'priority', + value: reader.int32() + } + break + } + case 3: { + yield { + field: 'cancel', + value: reader.bool() + } + break + } + case 4: { + yield { + field: 'wantType', + value: Message.Wantlist.WantType.codec().decode(reader) + } + break + } + case 5: { + yield { + field: 'sendDontHave', + value: reader.bool() + } + break + } + default: { + reader.skipType(tag & 7) + break + } + } + } + }) } return _codec } - export const encode = (obj: Partial): Uint8Array => { + export interface EntryBlockFieldEvent { + field: 'block' + value: Uint8Array + } + + export interface EntryPriorityFieldEvent { + field: 'priority' + value: number + } + + export interface EntryCancelFieldEvent { + field: 'cancel' + value: boolean + } + + export interface EntryWantTypeFieldEvent { + field: 'wantType' + value: Message.Wantlist.WantType + } + + export interface EntrySendDontHaveFieldEvent { + field: 'sendDontHave' + value: boolean + } + + export type EntryStreamEvent = EntryBlockFieldEvent | EntryPriorityFieldEvent | EntryCancelFieldEvent | EntryWantTypeFieldEvent | EntrySendDontHaveFieldEvent + export type EntryStreamCollectionsEvent = {} + + export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, Entry.codec()) } - export const decode = (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Entry => { + export function decode (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Entry { return decodeMessage(buf, Entry.codec(), opts) } + + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + return streamMessage(buf, Entry.codec(), opts) + } } - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -197,19 +299,90 @@ export namespace Message { } return obj + }, function * (reader, length, opts = {}) { + let obj: any + + if (opts.emitCollections === true) { + obj = { + entries: [], + full: false + } + } else { + obj = {} + } + + const end = length == null ? reader.len : reader.pos + length + + while (reader.pos < end) { + const tag = reader.uint32() + + switch (tag >>> 3) { + case 1: { + if (opts.limits?.entries != null && obj.entries.length === opts.limits.entries) { + throw new MaxLengthError('Decode error - map field "entries" had too many elements') + } + + yield { + field: 'entries$value', + index: 0, + value: Message.Wantlist.Entry.codec().decode(reader, reader.uint32(), { + limits: opts.limits?.entries$ + }) + } + break + } + case 2: { + yield { + field: 'full', + value: reader.bool() + } + break + } + default: { + reader.skipType(tag & 7) + break + } + } + } + }) } return _codec } - export const encode = (obj: Partial): Uint8Array => { + export interface WantlistEntriesFieldEvent { + field: 'entries' + value: Message.Wantlist.Entry[] + } + + export interface WantlistEntriesValueEvent { + field: 'entries$value' + index: number + value: Message.Wantlist.Entry + } + + export interface WantlistFullFieldEvent { + field: 'full' + value: boolean + } + + export type WantlistStreamEvent = WantlistEntriesValueEvent | WantlistFullFieldEvent + export type WantlistStreamCollectionsEvent = WantlistEntriesFieldEvent + + export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, Wantlist.codec()) } - export const decode = (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Wantlist => { + export function decode (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Wantlist { return decodeMessage(buf, Wantlist.codec(), opts) } + + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + return streamMessage(buf, Wantlist.codec(), opts) + } } export interface Block { @@ -218,11 +391,11 @@ export namespace Message { } export namespace Block { - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -268,19 +441,77 @@ export namespace Message { } return obj + }, function * (reader, length, opts = {}) { + let obj: any + + if (opts.emitCollections === true) { + obj = { + prefix: uint8ArrayAlloc(0), + data: uint8ArrayAlloc(0) + } + } else { + obj = {} + } + + const end = length == null ? reader.len : reader.pos + length + + while (reader.pos < end) { + const tag = reader.uint32() + + switch (tag >>> 3) { + case 1: { + yield { + field: 'prefix', + value: reader.bytes() + } + break + } + case 2: { + yield { + field: 'data', + value: reader.bytes() + } + break + } + default: { + reader.skipType(tag & 7) + break + } + } + } + }) } return _codec } - export const encode = (obj: Partial): Uint8Array => { + export interface BlockPrefixFieldEvent { + field: 'prefix' + value: Uint8Array + } + + export interface BlockDataFieldEvent { + field: 'data' + value: Uint8Array + } + + export type BlockStreamEvent = BlockPrefixFieldEvent | BlockDataFieldEvent + export type BlockStreamCollectionsEvent = {} + + export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, Block.codec()) } - export const decode = (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Block => { + export function decode (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Block { return decodeMessage(buf, Block.codec(), opts) } + + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + return streamMessage(buf, Block.codec(), opts) + } } export enum BlockPresenceType { @@ -294,7 +525,7 @@ export namespace Message { } export namespace BlockPresenceType { - export const codec = (): Codec => { + export const codec = (): Codec => { return enumeration(__BlockPresenceTypeValues) } } @@ -305,11 +536,11 @@ export namespace Message { } export namespace BlockPresence { - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -355,26 +586,84 @@ export namespace Message { } return obj + }, function * (reader, length, opts = {}) { + let obj: any + + if (opts.emitCollections === true) { + obj = { + cid: uint8ArrayAlloc(0), + type: BlockPresenceType.Have + } + } else { + obj = {} + } + + const end = length == null ? reader.len : reader.pos + length + + while (reader.pos < end) { + const tag = reader.uint32() + + switch (tag >>> 3) { + case 1: { + yield { + field: 'cid', + value: reader.bytes() + } + break + } + case 2: { + yield { + field: 'type', + value: Message.BlockPresenceType.codec().decode(reader) + } + break + } + default: { + reader.skipType(tag & 7) + break + } + } + } + }) } return _codec } - export const encode = (obj: Partial): Uint8Array => { + export interface BlockPresenceCidFieldEvent { + field: 'cid' + value: Uint8Array + } + + export interface BlockPresenceTypeFieldEvent { + field: 'type' + value: Message.BlockPresenceType + } + + export type BlockPresenceStreamEvent = BlockPresenceCidFieldEvent | BlockPresenceTypeFieldEvent + export type BlockPresenceStreamCollectionsEvent = {} + + export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, BlockPresence.codec()) } - export const decode = (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): BlockPresence => { + export function decode (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): BlockPresence { return decodeMessage(buf, BlockPresence.codec(), opts) } + + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + return streamMessage(buf, BlockPresence.codec(), opts) + } } - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -473,17 +762,152 @@ export namespace Message { } return obj + }, function * (reader, length, opts = {}) { + let obj: any + + if (opts.emitCollections === true) { + obj = { + blocks: [], + payload: [], + blockPresences: [], + pendingBytes: 0 + } + } else { + obj = {} + } + + const end = length == null ? reader.len : reader.pos + length + + while (reader.pos < end) { + const tag = reader.uint32() + + switch (tag >>> 3) { + case 1: { + yield { + field: 'wantlist', + value: Message.Wantlist.codec().decode(reader, reader.uint32(), { + limits: opts.limits?.wantlist + }) + } + break + } + case 2: { + if (opts.limits?.blocks != null && obj.blocks.length === opts.limits.blocks) { + throw new MaxLengthError('Decode error - map field "blocks" had too many elements') + } + + yield { + field: 'blocks$value', + index: 0, + value: reader.bytes() + } + break + } + case 3: { + if (opts.limits?.payload != null && obj.payload.length === opts.limits.payload) { + throw new MaxLengthError('Decode error - map field "payload" had too many elements') + } + + yield { + field: 'payload$value', + index: 0, + value: Message.Block.codec().decode(reader, reader.uint32(), { + limits: opts.limits?.payload$ + }) + } + break + } + case 4: { + if (opts.limits?.blockPresences != null && obj.blockPresences.length === opts.limits.blockPresences) { + throw new MaxLengthError('Decode error - map field "blockPresences" had too many elements') + } + + yield { + field: 'blockPresences$value', + index: 0, + value: Message.BlockPresence.codec().decode(reader, reader.uint32(), { + limits: opts.limits?.blockPresences$ + }) + } + break + } + case 5: { + yield { + field: 'pendingBytes', + value: reader.int32() + } + break + } + default: { + reader.skipType(tag & 7) + break + } + } + } + }) } return _codec } - export const encode = (obj: Partial): Uint8Array => { + export interface MessageWantlistFieldEvent { + field: 'wantlist' + value: Message.Wantlist + } + + export interface MessageBlocksFieldEvent { + field: 'blocks' + value: Uint8Array[] + } + + export interface MessageBlocksValueEvent { + field: 'blocks$value' + index: number + value: Uint8Array + } + + export interface MessagePayloadFieldEvent { + field: 'payload' + value: Message.Block[] + } + + export interface MessagePayloadValueEvent { + field: 'payload$value' + index: number + value: Message.Block + } + + export interface MessageBlockPresencesFieldEvent { + field: 'blockPresences' + value: Message.BlockPresence[] + } + + export interface MessageBlockPresencesValueEvent { + field: 'blockPresences$value' + index: number + value: Message.BlockPresence + } + + export interface MessagePendingBytesFieldEvent { + field: 'pendingBytes' + value: number + } + + export type MessageStreamEvent = MessageWantlistFieldEvent | MessageBlocksValueEvent | MessagePayloadValueEvent | MessageBlockPresencesValueEvent | MessagePendingBytesFieldEvent + export type MessageStreamCollectionsEvent = MessageBlocksFieldEvent | MessagePayloadFieldEvent | MessageBlockPresencesFieldEvent + + export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, Message.codec()) } - export const decode = (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Message => { + export function decode (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Message { return decodeMessage(buf, Message.codec(), opts) } + + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + return streamMessage(buf, Message.codec(), opts) + } } diff --git a/packages/protons/test/fixtures/circuit.ts b/packages/protons/test/fixtures/circuit.ts index e5c5317..ed9a801 100644 --- a/packages/protons/test/fixtures/circuit.ts +++ b/packages/protons/test/fixtures/circuit.ts @@ -1,6 +1,14 @@ -import { decodeMessage, encodeMessage, enumeration, MaxLengthError, message } from 'protons-runtime' +/* eslint-disable import/export */ +/* eslint-disable complexity */ +/* eslint-disable @typescript-eslint/no-namespace */ +/* eslint-disable @typescript-eslint/no-unnecessary-boolean-literal-compare */ +/* eslint-disable @typescript-eslint/no-empty-interface */ +/* eslint-disable import/consistent-type-specifier-style */ +/* eslint-disable @typescript-eslint/no-unused-vars */ + +import { decodeMessage, encodeMessage, enumeration, MaxLengthError, message, streamMessage } from 'protons-runtime' import { alloc as uint8ArrayAlloc } from 'uint8arrays/alloc' -import type { Codec, DecodeOptions } from 'protons-runtime' +import type { Codec, DecodeOptions, StreamingDecodeOptions, StreamingDecodeWithCollectionsOptions } from 'protons-runtime' import type { Uint8ArrayList } from 'uint8arraylist' export interface CircuitRelay { @@ -50,7 +58,7 @@ export namespace CircuitRelay { } export namespace Status { - export const codec = (): Codec => { + export const codec = (): Codec => { return enumeration(__StatusValues) } } @@ -70,7 +78,7 @@ export namespace CircuitRelay { } export namespace Type { - export const codec = (): Codec => { + export const codec = (): Codec => { return enumeration(__TypeValues) } } @@ -81,11 +89,11 @@ export namespace CircuitRelay { } export namespace Peer { - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -137,26 +145,95 @@ export namespace CircuitRelay { } return obj + }, function * (reader, length, opts = {}) { + let obj: any + + if (opts.emitCollections === true) { + obj = { + id: uint8ArrayAlloc(0), + addrs: [] + } + } else { + obj = {} + } + + const end = length == null ? reader.len : reader.pos + length + + while (reader.pos < end) { + const tag = reader.uint32() + + switch (tag >>> 3) { + case 1: { + yield { + field: 'id', + value: reader.bytes() + } + break + } + case 2: { + if (opts.limits?.addrs != null && obj.addrs.length === opts.limits.addrs) { + throw new MaxLengthError('Decode error - map field "addrs" had too many elements') + } + + yield { + field: 'addrs$value', + index: 0, + value: reader.bytes() + } + break + } + default: { + reader.skipType(tag & 7) + break + } + } + } + }) } return _codec } - export const encode = (obj: Partial): Uint8Array => { + export interface PeerIdFieldEvent { + field: 'id' + value: Uint8Array + } + + export interface PeerAddrsFieldEvent { + field: 'addrs' + value: Uint8Array[] + } + + export interface PeerAddrsValueEvent { + field: 'addrs$value' + index: number + value: Uint8Array + } + + export type PeerStreamEvent = PeerIdFieldEvent | PeerAddrsValueEvent + export type PeerStreamCollectionsEvent = PeerAddrsFieldEvent + + export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, Peer.codec()) } - export const decode = (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Peer => { + export function decode (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Peer { return decodeMessage(buf, Peer.codec(), opts) } + + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + return streamMessage(buf, Peer.codec(), opts) + } } - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -221,17 +298,100 @@ export namespace CircuitRelay { } return obj + }, function * (reader, length, opts = {}) { + let obj: any + + if (opts.emitCollections === true) { + obj = {} + } else { + obj = {} + } + + const end = length == null ? reader.len : reader.pos + length + + while (reader.pos < end) { + const tag = reader.uint32() + + switch (tag >>> 3) { + case 1: { + yield { + field: 'type', + value: CircuitRelay.Type.codec().decode(reader) + } + break + } + case 2: { + yield { + field: 'srcPeer', + value: CircuitRelay.Peer.codec().decode(reader, reader.uint32(), { + limits: opts.limits?.srcPeer + }) + } + break + } + case 3: { + yield { + field: 'dstPeer', + value: CircuitRelay.Peer.codec().decode(reader, reader.uint32(), { + limits: opts.limits?.dstPeer + }) + } + break + } + case 4: { + yield { + field: 'code', + value: CircuitRelay.Status.codec().decode(reader) + } + break + } + default: { + reader.skipType(tag & 7) + break + } + } + } + }) } return _codec } - export const encode = (obj: Partial): Uint8Array => { + export interface CircuitRelayTypeFieldEvent { + field: 'type' + value: CircuitRelay.Type + } + + export interface CircuitRelaySrcPeerFieldEvent { + field: 'srcPeer' + value: CircuitRelay.Peer + } + + export interface CircuitRelayDstPeerFieldEvent { + field: 'dstPeer' + value: CircuitRelay.Peer + } + + export interface CircuitRelayCodeFieldEvent { + field: 'code' + value: CircuitRelay.Status + } + + export type CircuitRelayStreamEvent = CircuitRelayTypeFieldEvent | CircuitRelaySrcPeerFieldEvent | CircuitRelayDstPeerFieldEvent | CircuitRelayCodeFieldEvent + export type CircuitRelayStreamCollectionsEvent = {} + + export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, CircuitRelay.codec()) } - export const decode = (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): CircuitRelay => { + export function decode (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): CircuitRelay { return decodeMessage(buf, CircuitRelay.codec(), opts) } + + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + return streamMessage(buf, CircuitRelay.codec(), opts) + } } diff --git a/packages/protons/test/fixtures/custom-option-jstype.ts b/packages/protons/test/fixtures/custom-option-jstype.ts index 48806c7..58d3a4b 100644 --- a/packages/protons/test/fixtures/custom-option-jstype.ts +++ b/packages/protons/test/fixtures/custom-option-jstype.ts @@ -1,5 +1,13 @@ -import { decodeMessage, encodeMessage, message } from 'protons-runtime' -import type { Codec, DecodeOptions } from 'protons-runtime' +/* eslint-disable import/export */ +/* eslint-disable complexity */ +/* eslint-disable @typescript-eslint/no-namespace */ +/* eslint-disable @typescript-eslint/no-unnecessary-boolean-literal-compare */ +/* eslint-disable @typescript-eslint/no-empty-interface */ +/* eslint-disable import/consistent-type-specifier-style */ +/* eslint-disable @typescript-eslint/no-unused-vars */ + +import { decodeMessage, encodeMessage, message, streamMessage } from 'protons-runtime' +import type { Codec, DecodeOptions, StreamingDecodeOptions, StreamingDecodeWithCollectionsOptions } from 'protons-runtime' import type { Uint8ArrayList } from 'uint8arraylist' export interface CustomOptionNumber { @@ -12,11 +20,11 @@ export interface CustomOptionNumber { } export namespace CustomOptionNumber { - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -102,19 +110,129 @@ export namespace CustomOptionNumber { } return obj + }, function * (reader, length, opts = {}) { + let obj: any + + if (opts.emitCollections === true) { + obj = { + num: 0, + i64: 0, + ui64: 0, + si64: 0, + f64: 0, + sf64: 0 + } + } else { + obj = {} + } + + const end = length == null ? reader.len : reader.pos + length + + while (reader.pos < end) { + const tag = reader.uint32() + + switch (tag >>> 3) { + case 1: { + yield { + field: 'num', + value: reader.int32() + } + break + } + case 2: { + yield { + field: 'i64', + value: reader.int64Number() + } + break + } + case 3: { + yield { + field: 'ui64', + value: reader.uint64Number() + } + break + } + case 4: { + yield { + field: 'si64', + value: reader.sint64Number() + } + break + } + case 5: { + yield { + field: 'f64', + value: reader.fixed64Number() + } + break + } + case 6: { + yield { + field: 'sf64', + value: reader.sfixed64Number() + } + break + } + default: { + reader.skipType(tag & 7) + break + } + } + } + }) } return _codec } - export const encode = (obj: Partial): Uint8Array => { + export interface CustomOptionNumberNumFieldEvent { + field: 'num' + value: number + } + + export interface CustomOptionNumberI64FieldEvent { + field: 'i64' + value: number + } + + export interface CustomOptionNumberUi64FieldEvent { + field: 'ui64' + value: number + } + + export interface CustomOptionNumberSi64FieldEvent { + field: 'si64' + value: number + } + + export interface CustomOptionNumberF64FieldEvent { + field: 'f64' + value: number + } + + export interface CustomOptionNumberSf64FieldEvent { + field: 'sf64' + value: number + } + + export type CustomOptionNumberStreamEvent = CustomOptionNumberNumFieldEvent | CustomOptionNumberI64FieldEvent | CustomOptionNumberUi64FieldEvent | CustomOptionNumberSi64FieldEvent | CustomOptionNumberF64FieldEvent | CustomOptionNumberSf64FieldEvent + export type CustomOptionNumberStreamCollectionsEvent = {} + + export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, CustomOptionNumber.codec()) } - export const decode = (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): CustomOptionNumber => { + export function decode (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): CustomOptionNumber { return decodeMessage(buf, CustomOptionNumber.codec(), opts) } + + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + return streamMessage(buf, CustomOptionNumber.codec(), opts) + } } export interface CustomOptionString { @@ -127,11 +245,11 @@ export interface CustomOptionString { } export namespace CustomOptionString { - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -217,17 +335,127 @@ export namespace CustomOptionString { } return obj + }, function * (reader, length, opts = {}) { + let obj: any + + if (opts.emitCollections === true) { + obj = { + num: 0, + i64: '', + ui64: '', + si64: '', + f64: '', + sf64: '' + } + } else { + obj = {} + } + + const end = length == null ? reader.len : reader.pos + length + + while (reader.pos < end) { + const tag = reader.uint32() + + switch (tag >>> 3) { + case 1: { + yield { + field: 'num', + value: reader.int32() + } + break + } + case 2: { + yield { + field: 'i64', + value: reader.int64String() + } + break + } + case 3: { + yield { + field: 'ui64', + value: reader.uint64String() + } + break + } + case 4: { + yield { + field: 'si64', + value: reader.sint64String() + } + break + } + case 5: { + yield { + field: 'f64', + value: reader.fixed64String() + } + break + } + case 6: { + yield { + field: 'sf64', + value: reader.sfixed64String() + } + break + } + default: { + reader.skipType(tag & 7) + break + } + } + } + }) } return _codec } - export const encode = (obj: Partial): Uint8Array => { + export interface CustomOptionStringNumFieldEvent { + field: 'num' + value: number + } + + export interface CustomOptionStringI64FieldEvent { + field: 'i64' + value: string + } + + export interface CustomOptionStringUi64FieldEvent { + field: 'ui64' + value: string + } + + export interface CustomOptionStringSi64FieldEvent { + field: 'si64' + value: string + } + + export interface CustomOptionStringF64FieldEvent { + field: 'f64' + value: string + } + + export interface CustomOptionStringSf64FieldEvent { + field: 'sf64' + value: string + } + + export type CustomOptionStringStreamEvent = CustomOptionStringNumFieldEvent | CustomOptionStringI64FieldEvent | CustomOptionStringUi64FieldEvent | CustomOptionStringSi64FieldEvent | CustomOptionStringF64FieldEvent | CustomOptionStringSf64FieldEvent + export type CustomOptionStringStreamCollectionsEvent = {} + + export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, CustomOptionString.codec()) } - export const decode = (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): CustomOptionString => { + export function decode (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): CustomOptionString { return decodeMessage(buf, CustomOptionString.codec(), opts) } + + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + return streamMessage(buf, CustomOptionString.codec(), opts) + } } diff --git a/packages/protons/test/fixtures/daemon.ts b/packages/protons/test/fixtures/daemon.ts index 701a818..df02ed5 100644 --- a/packages/protons/test/fixtures/daemon.ts +++ b/packages/protons/test/fixtures/daemon.ts @@ -1,8 +1,14 @@ +/* eslint-disable import/export */ /* eslint-disable complexity */ +/* eslint-disable @typescript-eslint/no-namespace */ +/* eslint-disable @typescript-eslint/no-unnecessary-boolean-literal-compare */ +/* eslint-disable @typescript-eslint/no-empty-interface */ +/* eslint-disable import/consistent-type-specifier-style */ +/* eslint-disable @typescript-eslint/no-unused-vars */ -import { decodeMessage, encodeMessage, enumeration, MaxLengthError, message } from 'protons-runtime' +import { decodeMessage, encodeMessage, enumeration, MaxLengthError, message, streamMessage } from 'protons-runtime' import { alloc as uint8ArrayAlloc } from 'uint8arrays/alloc' -import type { Codec, DecodeOptions } from 'protons-runtime' +import type { Codec, DecodeOptions, StreamingDecodeOptions, StreamingDecodeWithCollectionsOptions } from 'protons-runtime' import type { Uint8ArrayList } from 'uint8arraylist' export interface Request { @@ -45,16 +51,16 @@ export namespace Request { } export namespace Type { - export const codec = (): Codec => { + export const codec = (): Codec => { return enumeration(__TypeValues) } } - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -178,19 +184,176 @@ export namespace Request { } return obj + }, function * (reader, length, opts = {}) { + let obj: any + + if (opts.emitCollections === true) { + obj = { + type: Type.IDENTIFY + } + } else { + obj = {} + } + + const end = length == null ? reader.len : reader.pos + length + + while (reader.pos < end) { + const tag = reader.uint32() + + switch (tag >>> 3) { + case 1: { + yield { + field: 'type', + value: Request.Type.codec().decode(reader) + } + break + } + case 2: { + yield { + field: 'connect', + value: ConnectRequest.codec().decode(reader, reader.uint32(), { + limits: opts.limits?.connect + }) + } + break + } + case 3: { + yield { + field: 'streamOpen', + value: StreamOpenRequest.codec().decode(reader, reader.uint32(), { + limits: opts.limits?.streamOpen + }) + } + break + } + case 4: { + yield { + field: 'streamHandler', + value: StreamHandlerRequest.codec().decode(reader, reader.uint32(), { + limits: opts.limits?.streamHandler + }) + } + break + } + case 5: { + yield { + field: 'dht', + value: DHTRequest.codec().decode(reader, reader.uint32(), { + limits: opts.limits?.dht + }) + } + break + } + case 6: { + yield { + field: 'connManager', + value: ConnManagerRequest.codec().decode(reader, reader.uint32(), { + limits: opts.limits?.connManager + }) + } + break + } + case 7: { + yield { + field: 'disconnect', + value: DisconnectRequest.codec().decode(reader, reader.uint32(), { + limits: opts.limits?.disconnect + }) + } + break + } + case 8: { + yield { + field: 'pubsub', + value: PSRequest.codec().decode(reader, reader.uint32(), { + limits: opts.limits?.pubsub + }) + } + break + } + case 9: { + yield { + field: 'peerStore', + value: PeerstoreRequest.codec().decode(reader, reader.uint32(), { + limits: opts.limits?.peerStore + }) + } + break + } + default: { + reader.skipType(tag & 7) + break + } + } + } + }) } return _codec } - export const encode = (obj: Partial): Uint8Array => { + export interface RequestTypeFieldEvent { + field: 'type' + value: Request.Type + } + + export interface RequestConnectFieldEvent { + field: 'connect' + value: ConnectRequest + } + + export interface RequestStreamOpenFieldEvent { + field: 'streamOpen' + value: StreamOpenRequest + } + + export interface RequestStreamHandlerFieldEvent { + field: 'streamHandler' + value: StreamHandlerRequest + } + + export interface RequestDhtFieldEvent { + field: 'dht' + value: DHTRequest + } + + export interface RequestConnManagerFieldEvent { + field: 'connManager' + value: ConnManagerRequest + } + + export interface RequestDisconnectFieldEvent { + field: 'disconnect' + value: DisconnectRequest + } + + export interface RequestPubsubFieldEvent { + field: 'pubsub' + value: PSRequest + } + + export interface RequestPeerStoreFieldEvent { + field: 'peerStore' + value: PeerstoreRequest + } + + export type RequestStreamEvent = RequestTypeFieldEvent | RequestConnectFieldEvent | RequestStreamOpenFieldEvent | RequestStreamHandlerFieldEvent | RequestDhtFieldEvent | RequestConnManagerFieldEvent | RequestDisconnectFieldEvent | RequestPubsubFieldEvent | RequestPeerStoreFieldEvent + export type RequestStreamCollectionsEvent = {} + + export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, Request.codec()) } - export const decode = (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Request => { + export function decode (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Request { return decodeMessage(buf, Request.codec(), opts) } + + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + return streamMessage(buf, Request.codec(), opts) + } } export interface Response { @@ -216,16 +379,16 @@ export namespace Response { } export namespace Type { - export const codec = (): Codec => { + export const codec = (): Codec => { return enumeration(__TypeValues) } } - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -345,19 +508,174 @@ export namespace Response { } return obj + }, function * (reader, length, opts = {}) { + let obj: any + + if (opts.emitCollections === true) { + obj = { + type: Type.OK, + peers: [] + } + } else { + obj = {} + } + + const end = length == null ? reader.len : reader.pos + length + + while (reader.pos < end) { + const tag = reader.uint32() + + switch (tag >>> 3) { + case 1: { + yield { + field: 'type', + value: Response.Type.codec().decode(reader) + } + break + } + case 2: { + yield { + field: 'error', + value: ErrorResponse.codec().decode(reader, reader.uint32(), { + limits: opts.limits?.error + }) + } + break + } + case 3: { + yield { + field: 'streamInfo', + value: StreamInfo.codec().decode(reader, reader.uint32(), { + limits: opts.limits?.streamInfo + }) + } + break + } + case 4: { + yield { + field: 'identify', + value: IdentifyResponse.codec().decode(reader, reader.uint32(), { + limits: opts.limits?.identify + }) + } + break + } + case 5: { + yield { + field: 'dht', + value: DHTResponse.codec().decode(reader, reader.uint32(), { + limits: opts.limits?.dht + }) + } + break + } + case 6: { + if (opts.limits?.peers != null && obj.peers.length === opts.limits.peers) { + throw new MaxLengthError('Decode error - map field "peers" had too many elements') + } + + yield { + field: 'peers$value', + index: 0, + value: PeerInfo.codec().decode(reader, reader.uint32(), { + limits: opts.limits?.peers$ + }) + } + break + } + case 7: { + yield { + field: 'pubsub', + value: PSResponse.codec().decode(reader, reader.uint32(), { + limits: opts.limits?.pubsub + }) + } + break + } + case 8: { + yield { + field: 'peerStore', + value: PeerstoreResponse.codec().decode(reader, reader.uint32(), { + limits: opts.limits?.peerStore + }) + } + break + } + default: { + reader.skipType(tag & 7) + break + } + } + } + }) } return _codec } - export const encode = (obj: Partial): Uint8Array => { + export interface ResponseTypeFieldEvent { + field: 'type' + value: Response.Type + } + + export interface ResponseErrorFieldEvent { + field: 'error' + value: ErrorResponse + } + + export interface ResponseStreamInfoFieldEvent { + field: 'streamInfo' + value: StreamInfo + } + + export interface ResponseIdentifyFieldEvent { + field: 'identify' + value: IdentifyResponse + } + + export interface ResponseDhtFieldEvent { + field: 'dht' + value: DHTResponse + } + + export interface ResponsePeersFieldEvent { + field: 'peers' + value: PeerInfo[] + } + + export interface ResponsePeersValueEvent { + field: 'peers$value' + index: number + value: PeerInfo + } + + export interface ResponsePubsubFieldEvent { + field: 'pubsub' + value: PSResponse + } + + export interface ResponsePeerStoreFieldEvent { + field: 'peerStore' + value: PeerstoreResponse + } + + export type ResponseStreamEvent = ResponseTypeFieldEvent | ResponseErrorFieldEvent | ResponseStreamInfoFieldEvent | ResponseIdentifyFieldEvent | ResponseDhtFieldEvent | ResponsePeersValueEvent | ResponsePubsubFieldEvent | ResponsePeerStoreFieldEvent + export type ResponseStreamCollectionsEvent = ResponsePeersFieldEvent + + export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, Response.codec()) } - export const decode = (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Response => { + export function decode (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Response { return decodeMessage(buf, Response.codec(), opts) } + + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + return streamMessage(buf, Response.codec(), opts) + } } export interface IdentifyResponse { @@ -366,11 +684,11 @@ export interface IdentifyResponse { } export namespace IdentifyResponse { - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -422,19 +740,88 @@ export namespace IdentifyResponse { } return obj + }, function * (reader, length, opts = {}) { + let obj: any + + if (opts.emitCollections === true) { + obj = { + id: uint8ArrayAlloc(0), + addrs: [] + } + } else { + obj = {} + } + + const end = length == null ? reader.len : reader.pos + length + + while (reader.pos < end) { + const tag = reader.uint32() + + switch (tag >>> 3) { + case 1: { + yield { + field: 'id', + value: reader.bytes() + } + break + } + case 2: { + if (opts.limits?.addrs != null && obj.addrs.length === opts.limits.addrs) { + throw new MaxLengthError('Decode error - map field "addrs" had too many elements') + } + + yield { + field: 'addrs$value', + index: 0, + value: reader.bytes() + } + break + } + default: { + reader.skipType(tag & 7) + break + } + } + } + }) } return _codec } - export const encode = (obj: Partial): Uint8Array => { + export interface IdentifyResponseIdFieldEvent { + field: 'id' + value: Uint8Array + } + + export interface IdentifyResponseAddrsFieldEvent { + field: 'addrs' + value: Uint8Array[] + } + + export interface IdentifyResponseAddrsValueEvent { + field: 'addrs$value' + index: number + value: Uint8Array + } + + export type IdentifyResponseStreamEvent = IdentifyResponseIdFieldEvent | IdentifyResponseAddrsValueEvent + export type IdentifyResponseStreamCollectionsEvent = IdentifyResponseAddrsFieldEvent + + export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, IdentifyResponse.codec()) } - export const decode = (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): IdentifyResponse => { + export function decode (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): IdentifyResponse { return decodeMessage(buf, IdentifyResponse.codec(), opts) } + + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + return streamMessage(buf, IdentifyResponse.codec(), opts) + } } export interface ConnectRequest { @@ -444,11 +831,11 @@ export interface ConnectRequest { } export namespace ConnectRequest { - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -509,19 +896,100 @@ export namespace ConnectRequest { } return obj + }, function * (reader, length, opts = {}) { + let obj: any + + if (opts.emitCollections === true) { + obj = { + peer: uint8ArrayAlloc(0), + addrs: [] + } + } else { + obj = {} + } + + const end = length == null ? reader.len : reader.pos + length + + while (reader.pos < end) { + const tag = reader.uint32() + + switch (tag >>> 3) { + case 1: { + yield { + field: 'peer', + value: reader.bytes() + } + break + } + case 2: { + if (opts.limits?.addrs != null && obj.addrs.length === opts.limits.addrs) { + throw new MaxLengthError('Decode error - map field "addrs" had too many elements') + } + + yield { + field: 'addrs$value', + index: 0, + value: reader.bytes() + } + break + } + case 3: { + yield { + field: 'timeout', + value: reader.int64() + } + break + } + default: { + reader.skipType(tag & 7) + break + } + } + } + }) } return _codec } - export const encode = (obj: Partial): Uint8Array => { + export interface ConnectRequestPeerFieldEvent { + field: 'peer' + value: Uint8Array + } + + export interface ConnectRequestAddrsFieldEvent { + field: 'addrs' + value: Uint8Array[] + } + + export interface ConnectRequestAddrsValueEvent { + field: 'addrs$value' + index: number + value: Uint8Array + } + + export interface ConnectRequestTimeoutFieldEvent { + field: 'timeout' + value: bigint + } + + export type ConnectRequestStreamEvent = ConnectRequestPeerFieldEvent | ConnectRequestAddrsValueEvent | ConnectRequestTimeoutFieldEvent + export type ConnectRequestStreamCollectionsEvent = ConnectRequestAddrsFieldEvent + + export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, ConnectRequest.codec()) } - export const decode = (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): ConnectRequest => { + export function decode (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): ConnectRequest { return decodeMessage(buf, ConnectRequest.codec(), opts) } + + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + return streamMessage(buf, ConnectRequest.codec(), opts) + } } export interface StreamOpenRequest { @@ -531,11 +999,11 @@ export interface StreamOpenRequest { } export namespace StreamOpenRequest { - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -596,19 +1064,100 @@ export namespace StreamOpenRequest { } return obj + }, function * (reader, length, opts = {}) { + let obj: any + + if (opts.emitCollections === true) { + obj = { + peer: uint8ArrayAlloc(0), + proto: [] + } + } else { + obj = {} + } + + const end = length == null ? reader.len : reader.pos + length + + while (reader.pos < end) { + const tag = reader.uint32() + + switch (tag >>> 3) { + case 1: { + yield { + field: 'peer', + value: reader.bytes() + } + break + } + case 2: { + if (opts.limits?.proto != null && obj.proto.length === opts.limits.proto) { + throw new MaxLengthError('Decode error - map field "proto" had too many elements') + } + + yield { + field: 'proto$value', + index: 0, + value: reader.string() + } + break + } + case 3: { + yield { + field: 'timeout', + value: reader.int64() + } + break + } + default: { + reader.skipType(tag & 7) + break + } + } + } + }) } return _codec } - export const encode = (obj: Partial): Uint8Array => { + export interface StreamOpenRequestPeerFieldEvent { + field: 'peer' + value: Uint8Array + } + + export interface StreamOpenRequestProtoFieldEvent { + field: 'proto' + value: string[] + } + + export interface StreamOpenRequestProtoValueEvent { + field: 'proto$value' + index: number + value: string + } + + export interface StreamOpenRequestTimeoutFieldEvent { + field: 'timeout' + value: bigint + } + + export type StreamOpenRequestStreamEvent = StreamOpenRequestPeerFieldEvent | StreamOpenRequestProtoValueEvent | StreamOpenRequestTimeoutFieldEvent + export type StreamOpenRequestStreamCollectionsEvent = StreamOpenRequestProtoFieldEvent + + export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, StreamOpenRequest.codec()) } - export const decode = (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): StreamOpenRequest => { + export function decode (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): StreamOpenRequest { return decodeMessage(buf, StreamOpenRequest.codec(), opts) } + + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + return streamMessage(buf, StreamOpenRequest.codec(), opts) + } } export interface StreamHandlerRequest { @@ -617,11 +1166,11 @@ export interface StreamHandlerRequest { } export namespace StreamHandlerRequest { - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -673,19 +1222,88 @@ export namespace StreamHandlerRequest { } return obj + }, function * (reader, length, opts = {}) { + let obj: any + + if (opts.emitCollections === true) { + obj = { + addr: uint8ArrayAlloc(0), + proto: [] + } + } else { + obj = {} + } + + const end = length == null ? reader.len : reader.pos + length + + while (reader.pos < end) { + const tag = reader.uint32() + + switch (tag >>> 3) { + case 1: { + yield { + field: 'addr', + value: reader.bytes() + } + break + } + case 2: { + if (opts.limits?.proto != null && obj.proto.length === opts.limits.proto) { + throw new MaxLengthError('Decode error - map field "proto" had too many elements') + } + + yield { + field: 'proto$value', + index: 0, + value: reader.string() + } + break + } + default: { + reader.skipType(tag & 7) + break + } + } + } + }) } return _codec } - export const encode = (obj: Partial): Uint8Array => { + export interface StreamHandlerRequestAddrFieldEvent { + field: 'addr' + value: Uint8Array + } + + export interface StreamHandlerRequestProtoFieldEvent { + field: 'proto' + value: string[] + } + + export interface StreamHandlerRequestProtoValueEvent { + field: 'proto$value' + index: number + value: string + } + + export type StreamHandlerRequestStreamEvent = StreamHandlerRequestAddrFieldEvent | StreamHandlerRequestProtoValueEvent + export type StreamHandlerRequestStreamCollectionsEvent = StreamHandlerRequestProtoFieldEvent + + export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, StreamHandlerRequest.codec()) } - export const decode = (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): StreamHandlerRequest => { + export function decode (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): StreamHandlerRequest { return decodeMessage(buf, StreamHandlerRequest.codec(), opts) } + + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + return streamMessage(buf, StreamHandlerRequest.codec(), opts) + } } export interface ErrorResponse { @@ -693,11 +1311,11 @@ export interface ErrorResponse { } export namespace ErrorResponse { - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -733,19 +1351,64 @@ export namespace ErrorResponse { } return obj + }, function * (reader, length, opts = {}) { + let obj: any + + if (opts.emitCollections === true) { + obj = { + msg: '' + } + } else { + obj = {} + } + + const end = length == null ? reader.len : reader.pos + length + + while (reader.pos < end) { + const tag = reader.uint32() + + switch (tag >>> 3) { + case 1: { + yield { + field: 'msg', + value: reader.string() + } + break + } + default: { + reader.skipType(tag & 7) + break + } + } + } + }) } return _codec } - export const encode = (obj: Partial): Uint8Array => { + export interface ErrorResponseMsgFieldEvent { + field: 'msg' + value: string + } + + export type ErrorResponseStreamEvent = ErrorResponseMsgFieldEvent + export type ErrorResponseStreamCollectionsEvent = {} + + export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, ErrorResponse.codec()) } - export const decode = (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): ErrorResponse => { + export function decode (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): ErrorResponse { return decodeMessage(buf, ErrorResponse.codec(), opts) } + + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + return streamMessage(buf, ErrorResponse.codec(), opts) + } } export interface StreamInfo { @@ -755,11 +1418,11 @@ export interface StreamInfo { } export namespace StreamInfo { - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -815,19 +1478,90 @@ export namespace StreamInfo { } return obj + }, function * (reader, length, opts = {}) { + let obj: any + + if (opts.emitCollections === true) { + obj = { + peer: uint8ArrayAlloc(0), + addr: uint8ArrayAlloc(0), + proto: '' + } + } else { + obj = {} + } + + const end = length == null ? reader.len : reader.pos + length + + while (reader.pos < end) { + const tag = reader.uint32() + + switch (tag >>> 3) { + case 1: { + yield { + field: 'peer', + value: reader.bytes() + } + break + } + case 2: { + yield { + field: 'addr', + value: reader.bytes() + } + break + } + case 3: { + yield { + field: 'proto', + value: reader.string() + } + break + } + default: { + reader.skipType(tag & 7) + break + } + } + } + }) } return _codec } - export const encode = (obj: Partial): Uint8Array => { + export interface StreamInfoPeerFieldEvent { + field: 'peer' + value: Uint8Array + } + + export interface StreamInfoAddrFieldEvent { + field: 'addr' + value: Uint8Array + } + + export interface StreamInfoProtoFieldEvent { + field: 'proto' + value: string + } + + export type StreamInfoStreamEvent = StreamInfoPeerFieldEvent | StreamInfoAddrFieldEvent | StreamInfoProtoFieldEvent + export type StreamInfoStreamCollectionsEvent = {} + + export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, StreamInfo.codec()) } - export const decode = (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): StreamInfo => { + export function decode (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): StreamInfo { return decodeMessage(buf, StreamInfo.codec(), opts) } + + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + return streamMessage(buf, StreamInfo.codec(), opts) + } } export interface DHTRequest { @@ -866,16 +1600,16 @@ export namespace DHTRequest { } export namespace Type { - export const codec = (): Codec => { + export const codec = (): Codec => { return enumeration(__TypeValues) } } - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -965,19 +1699,136 @@ export namespace DHTRequest { } return obj + }, function * (reader, length, opts = {}) { + let obj: any + + if (opts.emitCollections === true) { + obj = { + type: Type.FIND_PEER + } + } else { + obj = {} + } + + const end = length == null ? reader.len : reader.pos + length + + while (reader.pos < end) { + const tag = reader.uint32() + + switch (tag >>> 3) { + case 1: { + yield { + field: 'type', + value: DHTRequest.Type.codec().decode(reader) + } + break + } + case 2: { + yield { + field: 'peer', + value: reader.bytes() + } + break + } + case 3: { + yield { + field: 'cid', + value: reader.bytes() + } + break + } + case 4: { + yield { + field: 'key', + value: reader.bytes() + } + break + } + case 5: { + yield { + field: 'value', + value: reader.bytes() + } + break + } + case 6: { + yield { + field: 'count', + value: reader.int32() + } + break + } + case 7: { + yield { + field: 'timeout', + value: reader.int64() + } + break + } + default: { + reader.skipType(tag & 7) + break + } + } + } + }) } return _codec } - export const encode = (obj: Partial): Uint8Array => { + export interface DHTRequestTypeFieldEvent { + field: 'type' + value: DHTRequest.Type + } + + export interface DHTRequestPeerFieldEvent { + field: 'peer' + value: Uint8Array + } + + export interface DHTRequestCidFieldEvent { + field: 'cid' + value: Uint8Array + } + + export interface DHTRequestKeyFieldEvent { + field: 'key' + value: Uint8Array + } + + export interface DHTRequestValueFieldEvent { + field: 'value' + value: Uint8Array + } + + export interface DHTRequestCountFieldEvent { + field: 'count' + value: number + } + + export interface DHTRequestTimeoutFieldEvent { + field: 'timeout' + value: bigint + } + + export type DHTRequestStreamEvent = DHTRequestTypeFieldEvent | DHTRequestPeerFieldEvent | DHTRequestCidFieldEvent | DHTRequestKeyFieldEvent | DHTRequestValueFieldEvent | DHTRequestCountFieldEvent | DHTRequestTimeoutFieldEvent + export type DHTRequestStreamCollectionsEvent = {} + + export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, DHTRequest.codec()) } - export const decode = (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): DHTRequest => { + export function decode (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): DHTRequest { return decodeMessage(buf, DHTRequest.codec(), opts) } + + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + return streamMessage(buf, DHTRequest.codec(), opts) + } } export interface DHTResponse { @@ -1000,16 +1851,16 @@ export namespace DHTResponse { } export namespace Type { - export const codec = (): Codec => { + export const codec = (): Codec => { return enumeration(__TypeValues) } } - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -1065,19 +1916,90 @@ export namespace DHTResponse { } return obj + }, function * (reader, length, opts = {}) { + let obj: any + + if (opts.emitCollections === true) { + obj = { + type: Type.BEGIN + } + } else { + obj = {} + } + + const end = length == null ? reader.len : reader.pos + length + + while (reader.pos < end) { + const tag = reader.uint32() + + switch (tag >>> 3) { + case 1: { + yield { + field: 'type', + value: DHTResponse.Type.codec().decode(reader) + } + break + } + case 2: { + yield { + field: 'peer', + value: PeerInfo.codec().decode(reader, reader.uint32(), { + limits: opts.limits?.peer + }) + } + break + } + case 3: { + yield { + field: 'value', + value: reader.bytes() + } + break + } + default: { + reader.skipType(tag & 7) + break + } + } + } + }) } return _codec } - export const encode = (obj: Partial): Uint8Array => { + export interface DHTResponseTypeFieldEvent { + field: 'type' + value: DHTResponse.Type + } + + export interface DHTResponsePeerFieldEvent { + field: 'peer' + value: PeerInfo + } + + export interface DHTResponseValueFieldEvent { + field: 'value' + value: Uint8Array + } + + export type DHTResponseStreamEvent = DHTResponseTypeFieldEvent | DHTResponsePeerFieldEvent | DHTResponseValueFieldEvent + export type DHTResponseStreamCollectionsEvent = {} + + export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, DHTResponse.codec()) } - export const decode = (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): DHTResponse => { + export function decode (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): DHTResponse { return decodeMessage(buf, DHTResponse.codec(), opts) } + + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + return streamMessage(buf, DHTResponse.codec(), opts) + } } export interface PeerInfo { @@ -1086,11 +2008,11 @@ export interface PeerInfo { } export namespace PeerInfo { - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -1142,19 +2064,88 @@ export namespace PeerInfo { } return obj + }, function * (reader, length, opts = {}) { + let obj: any + + if (opts.emitCollections === true) { + obj = { + id: uint8ArrayAlloc(0), + addrs: [] + } + } else { + obj = {} + } + + const end = length == null ? reader.len : reader.pos + length + + while (reader.pos < end) { + const tag = reader.uint32() + + switch (tag >>> 3) { + case 1: { + yield { + field: 'id', + value: reader.bytes() + } + break + } + case 2: { + if (opts.limits?.addrs != null && obj.addrs.length === opts.limits.addrs) { + throw new MaxLengthError('Decode error - map field "addrs" had too many elements') + } + + yield { + field: 'addrs$value', + index: 0, + value: reader.bytes() + } + break + } + default: { + reader.skipType(tag & 7) + break + } + } + } + }) } return _codec } - export const encode = (obj: Partial): Uint8Array => { + export interface PeerInfoIdFieldEvent { + field: 'id' + value: Uint8Array + } + + export interface PeerInfoAddrsFieldEvent { + field: 'addrs' + value: Uint8Array[] + } + + export interface PeerInfoAddrsValueEvent { + field: 'addrs$value' + index: number + value: Uint8Array + } + + export type PeerInfoStreamEvent = PeerInfoIdFieldEvent | PeerInfoAddrsValueEvent + export type PeerInfoStreamCollectionsEvent = PeerInfoAddrsFieldEvent + + export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, PeerInfo.codec()) } - export const decode = (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): PeerInfo => { + export function decode (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): PeerInfo { return decodeMessage(buf, PeerInfo.codec(), opts) } + + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + return streamMessage(buf, PeerInfo.codec(), opts) + } } export interface ConnManagerRequest { @@ -1178,16 +2169,16 @@ export namespace ConnManagerRequest { } export namespace Type { - export const codec = (): Codec => { + export const codec = (): Codec => { return enumeration(__TypeValues) } } - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -1250,19 +2241,100 @@ export namespace ConnManagerRequest { } return obj + }, function * (reader, length, opts = {}) { + let obj: any + + if (opts.emitCollections === true) { + obj = { + type: Type.TAG_PEER + } + } else { + obj = {} + } + + const end = length == null ? reader.len : reader.pos + length + + while (reader.pos < end) { + const tag = reader.uint32() + + switch (tag >>> 3) { + case 1: { + yield { + field: 'type', + value: ConnManagerRequest.Type.codec().decode(reader) + } + break + } + case 2: { + yield { + field: 'peer', + value: reader.bytes() + } + break + } + case 3: { + yield { + field: 'tag', + value: reader.string() + } + break + } + case 4: { + yield { + field: 'weight', + value: reader.int64() + } + break + } + default: { + reader.skipType(tag & 7) + break + } + } + } + }) } return _codec } - export const encode = (obj: Partial): Uint8Array => { + export interface ConnManagerRequestTypeFieldEvent { + field: 'type' + value: ConnManagerRequest.Type + } + + export interface ConnManagerRequestPeerFieldEvent { + field: 'peer' + value: Uint8Array + } + + export interface ConnManagerRequestTagFieldEvent { + field: 'tag' + value: string + } + + export interface ConnManagerRequestWeightFieldEvent { + field: 'weight' + value: bigint + } + + export type ConnManagerRequestStreamEvent = ConnManagerRequestTypeFieldEvent | ConnManagerRequestPeerFieldEvent | ConnManagerRequestTagFieldEvent | ConnManagerRequestWeightFieldEvent + export type ConnManagerRequestStreamCollectionsEvent = {} + + export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, ConnManagerRequest.codec()) } - export const decode = (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): ConnManagerRequest => { + export function decode (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): ConnManagerRequest { return decodeMessage(buf, ConnManagerRequest.codec(), opts) } + + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + return streamMessage(buf, ConnManagerRequest.codec(), opts) + } } export interface DisconnectRequest { @@ -1270,27 +2342,56 @@ export interface DisconnectRequest { } export namespace DisconnectRequest { - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } - if ((obj.peer != null && obj.peer.byteLength > 0)) { - w.uint32(10) - w.bytes(obj.peer) - } + if ((obj.peer != null && obj.peer.byteLength > 0)) { + w.uint32(10) + w.bytes(obj.peer) + } + + if (opts.lengthDelimited !== false) { + w.ldelim() + } + }, (reader, length, opts = {}) => { + const obj: any = { + peer: uint8ArrayAlloc(0) + } + + const end = length == null ? reader.len : reader.pos + length + + while (reader.pos < end) { + const tag = reader.uint32() + + switch (tag >>> 3) { + case 1: { + obj.peer = reader.bytes() + break + } + default: { + reader.skipType(tag & 7) + break + } + } + } + + return obj + }, function * (reader, length, opts = {}) { + let obj: any - if (opts.lengthDelimited !== false) { - w.ldelim() - } - }, (reader, length, opts = {}) => { - const obj: any = { + if (opts.emitCollections === true) { + obj = { peer: uint8ArrayAlloc(0) } + } else { + obj = {} + } const end = length == null ? reader.len : reader.pos + length @@ -1299,7 +2400,10 @@ export namespace DisconnectRequest { switch (tag >>> 3) { case 1: { - obj.peer = reader.bytes() + yield { + field: 'peer', + value: reader.bytes() + } break } default: { @@ -1309,20 +2413,33 @@ export namespace DisconnectRequest { } } - return obj }) } return _codec } - export const encode = (obj: Partial): Uint8Array => { + export interface DisconnectRequestPeerFieldEvent { + field: 'peer' + value: Uint8Array + } + + export type DisconnectRequestStreamEvent = DisconnectRequestPeerFieldEvent + export type DisconnectRequestStreamCollectionsEvent = {} + + export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, DisconnectRequest.codec()) } - export const decode = (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): DisconnectRequest => { + export function decode (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): DisconnectRequest { return decodeMessage(buf, DisconnectRequest.codec(), opts) } + + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + return streamMessage(buf, DisconnectRequest.codec(), opts) + } } export interface PSRequest { @@ -1347,16 +2464,16 @@ export namespace PSRequest { } export namespace Type { - export const codec = (): Codec => { + export const codec = (): Codec => { return enumeration(__TypeValues) } } - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -1410,19 +2527,88 @@ export namespace PSRequest { } return obj + }, function * (reader, length, opts = {}) { + let obj: any + + if (opts.emitCollections === true) { + obj = { + type: Type.GET_TOPICS + } + } else { + obj = {} + } + + const end = length == null ? reader.len : reader.pos + length + + while (reader.pos < end) { + const tag = reader.uint32() + + switch (tag >>> 3) { + case 1: { + yield { + field: 'type', + value: PSRequest.Type.codec().decode(reader) + } + break + } + case 2: { + yield { + field: 'topic', + value: reader.string() + } + break + } + case 3: { + yield { + field: 'data', + value: reader.bytes() + } + break + } + default: { + reader.skipType(tag & 7) + break + } + } + } + }) } return _codec } - export const encode = (obj: Partial): Uint8Array => { + export interface PSRequestTypeFieldEvent { + field: 'type' + value: PSRequest.Type + } + + export interface PSRequestTopicFieldEvent { + field: 'topic' + value: string + } + + export interface PSRequestDataFieldEvent { + field: 'data' + value: Uint8Array + } + + export type PSRequestStreamEvent = PSRequestTypeFieldEvent | PSRequestTopicFieldEvent | PSRequestDataFieldEvent + export type PSRequestStreamCollectionsEvent = {} + + export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, PSRequest.codec()) } - export const decode = (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): PSRequest => { + export function decode (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): PSRequest { return decodeMessage(buf, PSRequest.codec(), opts) } + + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + return streamMessage(buf, PSRequest.codec(), opts) + } } export interface PSMessage { @@ -1435,11 +2621,11 @@ export interface PSMessage { } export namespace PSMessage { - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -1526,19 +2712,135 @@ export namespace PSMessage { } return obj + }, function * (reader, length, opts = {}) { + let obj: any + + if (opts.emitCollections === true) { + obj = { + topicIDs: [] + } + } else { + obj = {} + } + + const end = length == null ? reader.len : reader.pos + length + + while (reader.pos < end) { + const tag = reader.uint32() + + switch (tag >>> 3) { + case 1: { + yield { + field: 'from', + value: reader.bytes() + } + break + } + case 2: { + yield { + field: 'data', + value: reader.bytes() + } + break + } + case 3: { + yield { + field: 'seqno', + value: reader.bytes() + } + break + } + case 4: { + if (opts.limits?.topicIDs != null && obj.topicIDs.length === opts.limits.topicIDs) { + throw new MaxLengthError('Decode error - map field "topicIDs" had too many elements') + } + + yield { + field: 'topicIDs$value', + index: 0, + value: reader.string() + } + break + } + case 5: { + yield { + field: 'signature', + value: reader.bytes() + } + break + } + case 6: { + yield { + field: 'key', + value: reader.bytes() + } + break + } + default: { + reader.skipType(tag & 7) + break + } + } + } + }) } return _codec } - export const encode = (obj: Partial): Uint8Array => { + export interface PSMessageFromFieldEvent { + field: 'from' + value: Uint8Array + } + + export interface PSMessageDataFieldEvent { + field: 'data' + value: Uint8Array + } + + export interface PSMessageSeqnoFieldEvent { + field: 'seqno' + value: Uint8Array + } + + export interface PSMessageTopicIDsFieldEvent { + field: 'topicIDs' + value: string[] + } + + export interface PSMessageTopicIDsValueEvent { + field: 'topicIDs$value' + index: number + value: string + } + + export interface PSMessageSignatureFieldEvent { + field: 'signature' + value: Uint8Array + } + + export interface PSMessageKeyFieldEvent { + field: 'key' + value: Uint8Array + } + + export type PSMessageStreamEvent = PSMessageFromFieldEvent | PSMessageDataFieldEvent | PSMessageSeqnoFieldEvent | PSMessageTopicIDsValueEvent | PSMessageSignatureFieldEvent | PSMessageKeyFieldEvent + export type PSMessageStreamCollectionsEvent = PSMessageTopicIDsFieldEvent + + export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, PSMessage.codec()) } - export const decode = (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): PSMessage => { + export function decode (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): PSMessage { return decodeMessage(buf, PSMessage.codec(), opts) } + + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + return streamMessage(buf, PSMessage.codec(), opts) + } } export interface PSResponse { @@ -1547,11 +2849,11 @@ export interface PSResponse { } export namespace PSResponse { - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -1609,19 +2911,99 @@ export namespace PSResponse { } return obj + }, function * (reader, length, opts = {}) { + let obj: any + + if (opts.emitCollections === true) { + obj = { + topics: [], + peerIDs: [] + } + } else { + obj = {} + } + + const end = length == null ? reader.len : reader.pos + length + + while (reader.pos < end) { + const tag = reader.uint32() + + switch (tag >>> 3) { + case 1: { + if (opts.limits?.topics != null && obj.topics.length === opts.limits.topics) { + throw new MaxLengthError('Decode error - map field "topics" had too many elements') + } + + yield { + field: 'topics$value', + index: 0, + value: reader.string() + } + break + } + case 2: { + if (opts.limits?.peerIDs != null && obj.peerIDs.length === opts.limits.peerIDs) { + throw new MaxLengthError('Decode error - map field "peerIDs" had too many elements') + } + + yield { + field: 'peerIDs$value', + index: 0, + value: reader.bytes() + } + break + } + default: { + reader.skipType(tag & 7) + break + } + } + } + }) } return _codec } - export const encode = (obj: Partial): Uint8Array => { + export interface PSResponseTopicsFieldEvent { + field: 'topics' + value: string[] + } + + export interface PSResponseTopicsValueEvent { + field: 'topics$value' + index: number + value: string + } + + export interface PSResponsePeerIDsFieldEvent { + field: 'peerIDs' + value: Uint8Array[] + } + + export interface PSResponsePeerIDsValueEvent { + field: 'peerIDs$value' + index: number + value: Uint8Array + } + + export type PSResponseStreamEvent = PSResponseTopicsValueEvent | PSResponsePeerIDsValueEvent + export type PSResponseStreamCollectionsEvent = PSResponseTopicsFieldEvent | PSResponsePeerIDsFieldEvent + + export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, PSResponse.codec()) } - export const decode = (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): PSResponse => { + export function decode (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): PSResponse { return decodeMessage(buf, PSResponse.codec(), opts) } + + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + return streamMessage(buf, PSResponse.codec(), opts) + } } export interface PeerstoreRequest { @@ -1644,16 +3026,16 @@ export namespace PeerstoreRequest { } export namespace Type { - export const codec = (): Codec => { + export const codec = (): Codec => { return enumeration(__TypeValues) } } - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -1714,19 +3096,100 @@ export namespace PeerstoreRequest { } return obj + }, function * (reader, length, opts = {}) { + let obj: any + + if (opts.emitCollections === true) { + obj = { + type: Type.INVALID, + protos: [] + } + } else { + obj = {} + } + + const end = length == null ? reader.len : reader.pos + length + + while (reader.pos < end) { + const tag = reader.uint32() + + switch (tag >>> 3) { + case 1: { + yield { + field: 'type', + value: PeerstoreRequest.Type.codec().decode(reader) + } + break + } + case 2: { + yield { + field: 'id', + value: reader.bytes() + } + break + } + case 3: { + if (opts.limits?.protos != null && obj.protos.length === opts.limits.protos) { + throw new MaxLengthError('Decode error - map field "protos" had too many elements') + } + + yield { + field: 'protos$value', + index: 0, + value: reader.string() + } + break + } + default: { + reader.skipType(tag & 7) + break + } + } + } + }) } return _codec } - export const encode = (obj: Partial): Uint8Array => { + export interface PeerstoreRequestTypeFieldEvent { + field: 'type' + value: PeerstoreRequest.Type + } + + export interface PeerstoreRequestIdFieldEvent { + field: 'id' + value: Uint8Array + } + + export interface PeerstoreRequestProtosFieldEvent { + field: 'protos' + value: string[] + } + + export interface PeerstoreRequestProtosValueEvent { + field: 'protos$value' + index: number + value: string + } + + export type PeerstoreRequestStreamEvent = PeerstoreRequestTypeFieldEvent | PeerstoreRequestIdFieldEvent | PeerstoreRequestProtosValueEvent + export type PeerstoreRequestStreamCollectionsEvent = PeerstoreRequestProtosFieldEvent + + export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, PeerstoreRequest.codec()) } - export const decode = (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): PeerstoreRequest => { + export function decode (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): PeerstoreRequest { return decodeMessage(buf, PeerstoreRequest.codec(), opts) } + + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + return streamMessage(buf, PeerstoreRequest.codec(), opts) + } } export interface PeerstoreResponse { @@ -1735,11 +3198,11 @@ export interface PeerstoreResponse { } export namespace PeerstoreResponse { - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -1792,17 +3255,87 @@ export namespace PeerstoreResponse { } return obj + }, function * (reader, length, opts = {}) { + let obj: any + + if (opts.emitCollections === true) { + obj = { + protos: [] + } + } else { + obj = {} + } + + const end = length == null ? reader.len : reader.pos + length + + while (reader.pos < end) { + const tag = reader.uint32() + + switch (tag >>> 3) { + case 1: { + yield { + field: 'peer', + value: PeerInfo.codec().decode(reader, reader.uint32(), { + limits: opts.limits?.peer + }) + } + break + } + case 2: { + if (opts.limits?.protos != null && obj.protos.length === opts.limits.protos) { + throw new MaxLengthError('Decode error - map field "protos" had too many elements') + } + + yield { + field: 'protos$value', + index: 0, + value: reader.string() + } + break + } + default: { + reader.skipType(tag & 7) + break + } + } + } + }) } return _codec } - export const encode = (obj: Partial): Uint8Array => { + export interface PeerstoreResponsePeerFieldEvent { + field: 'peer' + value: PeerInfo + } + + export interface PeerstoreResponseProtosFieldEvent { + field: 'protos' + value: string[] + } + + export interface PeerstoreResponseProtosValueEvent { + field: 'protos$value' + index: number + value: string + } + + export type PeerstoreResponseStreamEvent = PeerstoreResponsePeerFieldEvent | PeerstoreResponseProtosValueEvent + export type PeerstoreResponseStreamCollectionsEvent = PeerstoreResponseProtosFieldEvent + + export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, PeerstoreResponse.codec()) } - export const decode = (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): PeerstoreResponse => { + export function decode (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): PeerstoreResponse { return decodeMessage(buf, PeerstoreResponse.codec(), opts) } + + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + return streamMessage(buf, PeerstoreResponse.codec(), opts) + } } diff --git a/packages/protons/test/fixtures/dht.ts b/packages/protons/test/fixtures/dht.ts index 3298357..d9cb584 100644 --- a/packages/protons/test/fixtures/dht.ts +++ b/packages/protons/test/fixtures/dht.ts @@ -1,5 +1,13 @@ -import { decodeMessage, encodeMessage, enumeration, MaxLengthError, message } from 'protons-runtime' -import type { Codec, DecodeOptions } from 'protons-runtime' +/* eslint-disable import/export */ +/* eslint-disable complexity */ +/* eslint-disable @typescript-eslint/no-namespace */ +/* eslint-disable @typescript-eslint/no-unnecessary-boolean-literal-compare */ +/* eslint-disable @typescript-eslint/no-empty-interface */ +/* eslint-disable import/consistent-type-specifier-style */ +/* eslint-disable @typescript-eslint/no-unused-vars */ + +import { decodeMessage, encodeMessage, enumeration, MaxLengthError, message, streamMessage } from 'protons-runtime' +import type { Codec, DecodeOptions, StreamingDecodeOptions, StreamingDecodeWithCollectionsOptions } from 'protons-runtime' import type { Uint8ArrayList } from 'uint8arraylist' export interface Record { @@ -11,11 +19,11 @@ export interface Record { } export namespace Record { - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -85,19 +93,110 @@ export namespace Record { } return obj + }, function * (reader, length, opts = {}) { + let obj: any + + if (opts.emitCollections === true) { + obj = {} + } else { + obj = {} + } + + const end = length == null ? reader.len : reader.pos + length + + while (reader.pos < end) { + const tag = reader.uint32() + + switch (tag >>> 3) { + case 1: { + yield { + field: 'key', + value: reader.bytes() + } + break + } + case 2: { + yield { + field: 'value', + value: reader.bytes() + } + break + } + case 3: { + yield { + field: 'author', + value: reader.bytes() + } + break + } + case 4: { + yield { + field: 'signature', + value: reader.bytes() + } + break + } + case 5: { + yield { + field: 'timeReceived', + value: reader.string() + } + break + } + default: { + reader.skipType(tag & 7) + break + } + } + } + }) } return _codec } - export const encode = (obj: Partial): Uint8Array => { + export interface RecordKeyFieldEvent { + field: 'key' + value: Uint8Array + } + + export interface RecordValueFieldEvent { + field: 'value' + value: Uint8Array + } + + export interface RecordAuthorFieldEvent { + field: 'author' + value: Uint8Array + } + + export interface RecordSignatureFieldEvent { + field: 'signature' + value: Uint8Array + } + + export interface RecordTimeReceivedFieldEvent { + field: 'timeReceived' + value: string + } + + export type RecordStreamEvent = RecordKeyFieldEvent | RecordValueFieldEvent | RecordAuthorFieldEvent | RecordSignatureFieldEvent | RecordTimeReceivedFieldEvent + export type RecordStreamCollectionsEvent = {} + + export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, Record.codec()) } - export const decode = (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Record => { + export function decode (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Record { return decodeMessage(buf, Record.codec(), opts) } + + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + return streamMessage(buf, Record.codec(), opts) + } } export interface Message { @@ -129,7 +228,7 @@ export namespace Message { } export namespace MessageType { - export const codec = (): Codec => { + export const codec = (): Codec => { return enumeration(__MessageTypeValues) } } @@ -149,7 +248,7 @@ export namespace Message { } export namespace ConnectionType { - export const codec = (): Codec => { + export const codec = (): Codec => { return enumeration(__ConnectionTypeValues) } } @@ -161,11 +260,11 @@ export namespace Message { } export namespace Peer { - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -225,26 +324,106 @@ export namespace Message { } return obj + }, function * (reader, length, opts = {}) { + let obj: any + + if (opts.emitCollections === true) { + obj = { + addrs: [] + } + } else { + obj = {} + } + + const end = length == null ? reader.len : reader.pos + length + + while (reader.pos < end) { + const tag = reader.uint32() + + switch (tag >>> 3) { + case 1: { + yield { + field: 'id', + value: reader.bytes() + } + break + } + case 2: { + if (opts.limits?.addrs != null && obj.addrs.length === opts.limits.addrs) { + throw new MaxLengthError('Decode error - map field "addrs" had too many elements') + } + + yield { + field: 'addrs$value', + index: 0, + value: reader.bytes() + } + break + } + case 3: { + yield { + field: 'connection', + value: Message.ConnectionType.codec().decode(reader) + } + break + } + default: { + reader.skipType(tag & 7) + break + } + } + } + }) } return _codec } - export const encode = (obj: Partial): Uint8Array => { + export interface PeerIdFieldEvent { + field: 'id' + value: Uint8Array + } + + export interface PeerAddrsFieldEvent { + field: 'addrs' + value: Uint8Array[] + } + + export interface PeerAddrsValueEvent { + field: 'addrs$value' + index: number + value: Uint8Array + } + + export interface PeerConnectionFieldEvent { + field: 'connection' + value: Message.ConnectionType + } + + export type PeerStreamEvent = PeerIdFieldEvent | PeerAddrsValueEvent | PeerConnectionFieldEvent + export type PeerStreamCollectionsEvent = PeerAddrsFieldEvent + + export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, Peer.codec()) } - export const decode = (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Peer => { + export function decode (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Peer { return decodeMessage(buf, Peer.codec(), opts) } + + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + return streamMessage(buf, Peer.codec(), opts) + } } - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -342,17 +521,149 @@ export namespace Message { } return obj + }, function * (reader, length, opts = {}) { + let obj: any + + if (opts.emitCollections === true) { + obj = { + closerPeers: [], + providerPeers: [] + } + } else { + obj = {} + } + + const end = length == null ? reader.len : reader.pos + length + + while (reader.pos < end) { + const tag = reader.uint32() + + switch (tag >>> 3) { + case 1: { + yield { + field: 'type', + value: Message.MessageType.codec().decode(reader) + } + break + } + case 10: { + yield { + field: 'clusterLevelRaw', + value: reader.int32() + } + break + } + case 2: { + yield { + field: 'key', + value: reader.bytes() + } + break + } + case 3: { + yield { + field: 'record', + value: reader.bytes() + } + break + } + case 8: { + if (opts.limits?.closerPeers != null && obj.closerPeers.length === opts.limits.closerPeers) { + throw new MaxLengthError('Decode error - map field "closerPeers" had too many elements') + } + + yield { + field: 'closerPeers$value', + index: 0, + value: Message.Peer.codec().decode(reader, reader.uint32(), { + limits: opts.limits?.closerPeers$ + }) + } + break + } + case 9: { + if (opts.limits?.providerPeers != null && obj.providerPeers.length === opts.limits.providerPeers) { + throw new MaxLengthError('Decode error - map field "providerPeers" had too many elements') + } + + yield { + field: 'providerPeers$value', + index: 0, + value: Message.Peer.codec().decode(reader, reader.uint32(), { + limits: opts.limits?.providerPeers$ + }) + } + break + } + default: { + reader.skipType(tag & 7) + break + } + } + } + }) } return _codec } - export const encode = (obj: Partial): Uint8Array => { + export interface MessageTypeFieldEvent { + field: 'type' + value: Message.MessageType + } + + export interface MessageClusterLevelRawFieldEvent { + field: 'clusterLevelRaw' + value: number + } + + export interface MessageKeyFieldEvent { + field: 'key' + value: Uint8Array + } + + export interface MessageRecordFieldEvent { + field: 'record' + value: Uint8Array + } + + export interface MessageCloserPeersFieldEvent { + field: 'closerPeers' + value: Message.Peer[] + } + + export interface MessageCloserPeersValueEvent { + field: 'closerPeers$value' + index: number + value: Message.Peer + } + + export interface MessageProviderPeersFieldEvent { + field: 'providerPeers' + value: Message.Peer[] + } + + export interface MessageProviderPeersValueEvent { + field: 'providerPeers$value' + index: number + value: Message.Peer + } + + export type MessageStreamEvent = MessageTypeFieldEvent | MessageClusterLevelRawFieldEvent | MessageKeyFieldEvent | MessageRecordFieldEvent | MessageCloserPeersValueEvent | MessageProviderPeersValueEvent + export type MessageStreamCollectionsEvent = MessageCloserPeersFieldEvent | MessageProviderPeersFieldEvent + + export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, Message.codec()) } - export const decode = (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Message => { + export function decode (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Message { return decodeMessage(buf, Message.codec(), opts) } + + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + return streamMessage(buf, Message.codec(), opts) + } } diff --git a/packages/protons/test/fixtures/maps.ts b/packages/protons/test/fixtures/maps.ts index 74f6f60..f742b90 100644 --- a/packages/protons/test/fixtures/maps.ts +++ b/packages/protons/test/fixtures/maps.ts @@ -1,7 +1,13 @@ +/* eslint-disable import/export */ /* eslint-disable complexity */ - -import { decodeMessage, encodeMessage, enumeration, MaxLengthError, MaxSizeError, message } from 'protons-runtime' -import type { Codec, DecodeOptions } from 'protons-runtime' +/* eslint-disable @typescript-eslint/no-namespace */ +/* eslint-disable @typescript-eslint/no-unnecessary-boolean-literal-compare */ +/* eslint-disable @typescript-eslint/no-empty-interface */ +/* eslint-disable import/consistent-type-specifier-style */ +/* eslint-disable @typescript-eslint/no-unused-vars */ + +import { decodeMessage, encodeMessage, enumeration, MaxLengthError, MaxSizeError, message, streamMessage } from 'protons-runtime' +import type { Codec, DecodeOptions, StreamingDecodeOptions, StreamingDecodeWithCollectionsOptions } from 'protons-runtime' import type { Uint8ArrayList } from 'uint8arraylist' export enum EnumValue { @@ -17,7 +23,7 @@ enum __EnumValueValues { } export namespace EnumValue { - export const codec = (): Codec => { + export const codec = (): Codec => { return enumeration(__EnumValueValues) } } @@ -28,11 +34,11 @@ export interface SubMessage { } export namespace SubMessage { - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -84,19 +90,88 @@ export namespace SubMessage { } return obj + }, function * (reader, length, opts = {}) { + let obj: any + + if (opts.emitCollections === true) { + obj = { + foo: '', + bar: [] + } + } else { + obj = {} + } + + const end = length == null ? reader.len : reader.pos + length + + while (reader.pos < end) { + const tag = reader.uint32() + + switch (tag >>> 3) { + case 1: { + yield { + field: 'foo', + value: reader.string() + } + break + } + case 2: { + if (opts.limits?.bar != null && obj.bar.length === opts.limits.bar) { + throw new MaxLengthError('Decode error - map field "bar" had too many elements') + } + + yield { + field: 'bar$value', + index: 0, + value: reader.uint32() + } + break + } + default: { + reader.skipType(tag & 7) + break + } + } + } + }) } return _codec } - export const encode = (obj: Partial): Uint8Array => { + export interface SubMessageFooFieldEvent { + field: 'foo' + value: string + } + + export interface SubMessageBarFieldEvent { + field: 'bar' + value: number[] + } + + export interface SubMessageBarValueEvent { + field: 'bar$value' + index: number + value: number + } + + export type SubMessageStreamEvent = SubMessageFooFieldEvent | SubMessageBarValueEvent + export type SubMessageStreamCollectionsEvent = SubMessageBarFieldEvent + + export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, SubMessage.codec()) } - export const decode = (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): SubMessage => { + export function decode (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): SubMessage { return decodeMessage(buf, SubMessage.codec(), opts) } + + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + return streamMessage(buf, SubMessage.codec(), opts) + } } export interface MapTypes { @@ -114,11 +189,11 @@ export namespace MapTypes { } export namespace MapTypes$stringMapEntry { - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -164,19 +239,77 @@ export namespace MapTypes { } return obj + }, function * (reader, length, opts = {}) { + let obj: any + + if (opts.emitCollections === true) { + obj = { + key: '', + value: '' + } + } else { + obj = {} + } + + const end = length == null ? reader.len : reader.pos + length + + while (reader.pos < end) { + const tag = reader.uint32() + + switch (tag >>> 3) { + case 1: { + yield { + field: 'key', + value: reader.string() + } + break + } + case 2: { + yield { + field: 'value', + value: reader.string() + } + break + } + default: { + reader.skipType(tag & 7) + break + } + } + } + }) } return _codec } - export const encode = (obj: Partial): Uint8Array => { + export interface MapTypes$stringMapEntryKeyFieldEvent { + field: 'key' + value: string + } + + export interface MapTypes$stringMapEntryValueFieldEvent { + field: 'value' + value: string + } + + export type MapTypes$stringMapEntryStreamEvent = MapTypes$stringMapEntryKeyFieldEvent | MapTypes$stringMapEntryValueFieldEvent + export type MapTypes$stringMapEntryStreamCollectionsEvent = {} + + export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, MapTypes$stringMapEntry.codec()) } - export const decode = (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): MapTypes$stringMapEntry => { + export function decode (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): MapTypes$stringMapEntry { return decodeMessage(buf, MapTypes$stringMapEntry.codec(), opts) } + + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + return streamMessage(buf, MapTypes$stringMapEntry.codec(), opts) + } } export interface MapTypes$intMapEntry { @@ -185,11 +318,11 @@ export namespace MapTypes { } export namespace MapTypes$intMapEntry { - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -235,19 +368,77 @@ export namespace MapTypes { } return obj + }, function * (reader, length, opts = {}) { + let obj: any + + if (opts.emitCollections === true) { + obj = { + key: 0, + value: 0 + } + } else { + obj = {} + } + + const end = length == null ? reader.len : reader.pos + length + + while (reader.pos < end) { + const tag = reader.uint32() + + switch (tag >>> 3) { + case 1: { + yield { + field: 'key', + value: reader.int32() + } + break + } + case 2: { + yield { + field: 'value', + value: reader.int32() + } + break + } + default: { + reader.skipType(tag & 7) + break + } + } + } + }) } return _codec } - export const encode = (obj: Partial): Uint8Array => { + export interface MapTypes$intMapEntryKeyFieldEvent { + field: 'key' + value: number + } + + export interface MapTypes$intMapEntryValueFieldEvent { + field: 'value' + value: number + } + + export type MapTypes$intMapEntryStreamEvent = MapTypes$intMapEntryKeyFieldEvent | MapTypes$intMapEntryValueFieldEvent + export type MapTypes$intMapEntryStreamCollectionsEvent = {} + + export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, MapTypes$intMapEntry.codec()) } - export const decode = (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): MapTypes$intMapEntry => { + export function decode (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): MapTypes$intMapEntry { return decodeMessage(buf, MapTypes$intMapEntry.codec(), opts) } + + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + return streamMessage(buf, MapTypes$intMapEntry.codec(), opts) + } } export interface MapTypes$boolMapEntry { @@ -256,11 +447,11 @@ export namespace MapTypes { } export namespace MapTypes$boolMapEntry { - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -306,19 +497,77 @@ export namespace MapTypes { } return obj + }, function * (reader, length, opts = {}) { + let obj: any + + if (opts.emitCollections === true) { + obj = { + key: false, + value: false + } + } else { + obj = {} + } + + const end = length == null ? reader.len : reader.pos + length + + while (reader.pos < end) { + const tag = reader.uint32() + + switch (tag >>> 3) { + case 1: { + yield { + field: 'key', + value: reader.bool() + } + break + } + case 2: { + yield { + field: 'value', + value: reader.bool() + } + break + } + default: { + reader.skipType(tag & 7) + break + } + } + } + }) } return _codec } - export const encode = (obj: Partial): Uint8Array => { + export interface MapTypes$boolMapEntryKeyFieldEvent { + field: 'key' + value: boolean + } + + export interface MapTypes$boolMapEntryValueFieldEvent { + field: 'value' + value: boolean + } + + export type MapTypes$boolMapEntryStreamEvent = MapTypes$boolMapEntryKeyFieldEvent | MapTypes$boolMapEntryValueFieldEvent + export type MapTypes$boolMapEntryStreamCollectionsEvent = {} + + export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, MapTypes$boolMapEntry.codec()) } - export const decode = (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): MapTypes$boolMapEntry => { + export function decode (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): MapTypes$boolMapEntry { return decodeMessage(buf, MapTypes$boolMapEntry.codec(), opts) } + + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + return streamMessage(buf, MapTypes$boolMapEntry.codec(), opts) + } } export interface MapTypes$messageMapEntry { @@ -327,11 +576,11 @@ export namespace MapTypes { } export namespace MapTypes$messageMapEntry { - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -378,19 +627,78 @@ export namespace MapTypes { } return obj + }, function * (reader, length, opts = {}) { + let obj: any + + if (opts.emitCollections === true) { + obj = { + key: '' + } + } else { + obj = {} + } + + const end = length == null ? reader.len : reader.pos + length + + while (reader.pos < end) { + const tag = reader.uint32() + + switch (tag >>> 3) { + case 1: { + yield { + field: 'key', + value: reader.string() + } + break + } + case 2: { + yield { + field: 'value', + value: SubMessage.codec().decode(reader, reader.uint32(), { + limits: opts.limits?.value + }) + } + break + } + default: { + reader.skipType(tag & 7) + break + } + } + } + }) } return _codec } - export const encode = (obj: Partial): Uint8Array => { + export interface MapTypes$messageMapEntryKeyFieldEvent { + field: 'key' + value: string + } + + export interface MapTypes$messageMapEntryValueFieldEvent { + field: 'value' + value: SubMessage + } + + export type MapTypes$messageMapEntryStreamEvent = MapTypes$messageMapEntryKeyFieldEvent | MapTypes$messageMapEntryValueFieldEvent + export type MapTypes$messageMapEntryStreamCollectionsEvent = {} + + export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, MapTypes$messageMapEntry.codec()) } - export const decode = (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): MapTypes$messageMapEntry => { + export function decode (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): MapTypes$messageMapEntry { return decodeMessage(buf, MapTypes$messageMapEntry.codec(), opts) } + + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + return streamMessage(buf, MapTypes$messageMapEntry.codec(), opts) + } } export interface MapTypes$enumMapEntry { @@ -399,11 +707,11 @@ export namespace MapTypes { } export namespace MapTypes$enumMapEntry { - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -449,26 +757,84 @@ export namespace MapTypes { } return obj + }, function * (reader, length, opts = {}) { + let obj: any + + if (opts.emitCollections === true) { + obj = { + key: '', + value: EnumValue.NO_VALUE + } + } else { + obj = {} + } + + const end = length == null ? reader.len : reader.pos + length + + while (reader.pos < end) { + const tag = reader.uint32() + + switch (tag >>> 3) { + case 1: { + yield { + field: 'key', + value: reader.string() + } + break + } + case 2: { + yield { + field: 'value', + value: EnumValue.codec().decode(reader) + } + break + } + default: { + reader.skipType(tag & 7) + break + } + } + } + }) } return _codec } - export const encode = (obj: Partial): Uint8Array => { + export interface MapTypes$enumMapEntryKeyFieldEvent { + field: 'key' + value: string + } + + export interface MapTypes$enumMapEntryValueFieldEvent { + field: 'value' + value: EnumValue + } + + export type MapTypes$enumMapEntryStreamEvent = MapTypes$enumMapEntryKeyFieldEvent | MapTypes$enumMapEntryValueFieldEvent + export type MapTypes$enumMapEntryStreamCollectionsEvent = {} + + export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, MapTypes$enumMapEntry.codec()) } - export const decode = (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): MapTypes$enumMapEntry => { + export function decode (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): MapTypes$enumMapEntry { return decodeMessage(buf, MapTypes$enumMapEntry.codec(), opts) } + + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + return streamMessage(buf, MapTypes$enumMapEntry.codec(), opts) + } } - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -583,17 +949,183 @@ export namespace MapTypes { } return obj + }, function * (reader, length, opts = {}) { + let obj: any + + if (opts.emitCollections === true) { + obj = { + stringMap: new Map(), + intMap: new Map(), + boolMap: new Map(), + messageMap: new Map(), + enumMap: new Map() + } + } else { + obj = {} + } + + const end = length == null ? reader.len : reader.pos + length + + while (reader.pos < end) { + const tag = reader.uint32() + + switch (tag >>> 3) { + case 1: { + if (opts.limits?.stringMap != null && obj.stringMap.size === opts.limits.stringMap) { + throw new MaxSizeError('Decode error - map field "stringMap" had too many elements') + } + + const entry = MapTypes.MapTypes$stringMapEntry.codec().decode(reader, reader.uint32()) + + yield { + field: 'stringMap', + key: entry.key, + value: entry.value + } + break + } + case 2: { + if (opts.limits?.intMap != null && obj.intMap.size === opts.limits.intMap) { + throw new MaxSizeError('Decode error - map field "intMap" had too many elements') + } + + const entry = MapTypes.MapTypes$intMapEntry.codec().decode(reader, reader.uint32()) + + yield { + field: 'intMap', + key: entry.key, + value: entry.value + } + break + } + case 3: { + if (opts.limits?.boolMap != null && obj.boolMap.size === opts.limits.boolMap) { + throw new MaxSizeError('Decode error - map field "boolMap" had too many elements') + } + + const entry = MapTypes.MapTypes$boolMapEntry.codec().decode(reader, reader.uint32()) + + yield { + field: 'boolMap', + key: entry.key, + value: entry.value + } + break + } + case 4: { + if (opts.limits?.messageMap != null && obj.messageMap.size === opts.limits.messageMap) { + throw new MaxSizeError('Decode error - map field "messageMap" had too many elements') + } + + const entry = MapTypes.MapTypes$messageMapEntry.codec().decode(reader, reader.uint32(), { + limits: { + value: opts.limits?.messageMap$value + } + }) + + yield { + field: 'messageMap', + key: entry.key, + value: entry.value + } + break + } + case 5: { + if (opts.limits?.enumMap != null && obj.enumMap.size === opts.limits.enumMap) { + throw new MaxSizeError('Decode error - map field "enumMap" had too many elements') + } + + const entry = MapTypes.MapTypes$enumMapEntry.codec().decode(reader, reader.uint32()) + + yield { + field: 'enumMap', + key: entry.key, + value: entry.value + } + break + } + default: { + reader.skipType(tag & 7) + break + } + } + } + }) } return _codec } - export const encode = (obj: Partial): Uint8Array => { + export interface MapTypesStringMapFieldEvent { + field: 'stringMap' + value: Map + } + + export interface MapTypesStringMapEntryEvent { + field: 'stringMap$entry' + key: string + value: string + } + + export interface MapTypesIntMapFieldEvent { + field: 'intMap' + value: Map + } + + export interface MapTypesIntMapEntryEvent { + field: 'intMap$entry' + key: number + value: number + } + + export interface MapTypesBoolMapFieldEvent { + field: 'boolMap' + value: Map + } + + export interface MapTypesBoolMapEntryEvent { + field: 'boolMap$entry' + key: boolean + value: boolean + } + + export interface MapTypesMessageMapFieldEvent { + field: 'messageMap' + value: Map + } + + export interface MapTypesMessageMapEntryEvent { + field: 'messageMap$entry' + key: string + value: SubMessage + } + + export interface MapTypesEnumMapFieldEvent { + field: 'enumMap' + value: Map + } + + export interface MapTypesEnumMapEntryEvent { + field: 'enumMap$entry' + key: string + value: EnumValue + } + + export type MapTypesStreamEvent = MapTypesStringMapEntryEvent | MapTypesIntMapEntryEvent | MapTypesBoolMapEntryEvent | MapTypesMessageMapEntryEvent | MapTypesEnumMapEntryEvent + export type MapTypesStreamCollectionsEvent = MapTypesStringMapFieldEvent | MapTypesIntMapFieldEvent | MapTypesBoolMapFieldEvent | MapTypesMessageMapFieldEvent | MapTypesEnumMapFieldEvent + + export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, MapTypes.codec()) } - export const decode = (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): MapTypes => { + export function decode (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): MapTypes { return decodeMessage(buf, MapTypes.codec(), opts) } + + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + return streamMessage(buf, MapTypes.codec(), opts) + } } diff --git a/packages/protons/test/fixtures/noise.ts b/packages/protons/test/fixtures/noise.ts index 73e4545..130dabb 100644 --- a/packages/protons/test/fixtures/noise.ts +++ b/packages/protons/test/fixtures/noise.ts @@ -1,6 +1,14 @@ -import { decodeMessage, encodeMessage, message } from 'protons-runtime' +/* eslint-disable import/export */ +/* eslint-disable complexity */ +/* eslint-disable @typescript-eslint/no-namespace */ +/* eslint-disable @typescript-eslint/no-unnecessary-boolean-literal-compare */ +/* eslint-disable @typescript-eslint/no-empty-interface */ +/* eslint-disable import/consistent-type-specifier-style */ +/* eslint-disable @typescript-eslint/no-unused-vars */ + +import { decodeMessage, encodeMessage, message, streamMessage } from 'protons-runtime' import { alloc as uint8ArrayAlloc } from 'uint8arrays/alloc' -import type { Codec, DecodeOptions } from 'protons-runtime' +import type { Codec, DecodeOptions, StreamingDecodeOptions, StreamingDecodeWithCollectionsOptions } from 'protons-runtime' import type { Uint8ArrayList } from 'uint8arraylist' export interface pb {} @@ -13,11 +21,11 @@ export namespace pb { } export namespace NoiseHandshakePayload { - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -73,26 +81,97 @@ export namespace pb { } return obj + }, function * (reader, length, opts = {}) { + let obj: any + + if (opts.emitCollections === true) { + obj = { + identityKey: uint8ArrayAlloc(0), + identitySig: uint8ArrayAlloc(0), + data: uint8ArrayAlloc(0) + } + } else { + obj = {} + } + + const end = length == null ? reader.len : reader.pos + length + + while (reader.pos < end) { + const tag = reader.uint32() + + switch (tag >>> 3) { + case 1: { + yield { + field: 'identityKey', + value: reader.bytes() + } + break + } + case 2: { + yield { + field: 'identitySig', + value: reader.bytes() + } + break + } + case 3: { + yield { + field: 'data', + value: reader.bytes() + } + break + } + default: { + reader.skipType(tag & 7) + break + } + } + } + }) } return _codec } - export const encode = (obj: Partial): Uint8Array => { + export interface NoiseHandshakePayloadIdentityKeyFieldEvent { + field: 'identityKey' + value: Uint8Array + } + + export interface NoiseHandshakePayloadIdentitySigFieldEvent { + field: 'identitySig' + value: Uint8Array + } + + export interface NoiseHandshakePayloadDataFieldEvent { + field: 'data' + value: Uint8Array + } + + export type NoiseHandshakePayloadStreamEvent = NoiseHandshakePayloadIdentityKeyFieldEvent | NoiseHandshakePayloadIdentitySigFieldEvent | NoiseHandshakePayloadDataFieldEvent + export type NoiseHandshakePayloadStreamCollectionsEvent = {} + + export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, NoiseHandshakePayload.codec()) } - export const decode = (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): NoiseHandshakePayload => { + export function decode (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): NoiseHandshakePayload { return decodeMessage(buf, NoiseHandshakePayload.codec(), opts) } + + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + return streamMessage(buf, NoiseHandshakePayload.codec(), opts) + } } - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -117,17 +196,50 @@ export namespace pb { } return obj + }, function * (reader, length, opts = {}) { + let obj: any + + if (opts.emitCollections === true) { + obj = {} + } else { + obj = {} + } + + const end = length == null ? reader.len : reader.pos + length + + while (reader.pos < end) { + const tag = reader.uint32() + + switch (tag >>> 3) { + default: { + reader.skipType(tag & 7) + break + } + } + } + }) } return _codec } - export const encode = (obj: Partial): Uint8Array => { + + + export type pbStreamEvent = {} + export type pbStreamCollectionsEvent = {} + + export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, pb.codec()) } - export const decode = (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): pb => { + export function decode (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): pb { return decodeMessage(buf, pb.codec(), opts) } + + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + return streamMessage(buf, pb.codec(), opts) + } } diff --git a/packages/protons/test/fixtures/oneof.ts b/packages/protons/test/fixtures/oneof.ts index 71e2ef6..98b0415 100644 --- a/packages/protons/test/fixtures/oneof.ts +++ b/packages/protons/test/fixtures/oneof.ts @@ -1,5 +1,13 @@ -import { decodeMessage, encodeMessage, enumeration, message } from 'protons-runtime' -import type { Codec, DecodeOptions } from 'protons-runtime' +/* eslint-disable import/export */ +/* eslint-disable complexity */ +/* eslint-disable @typescript-eslint/no-namespace */ +/* eslint-disable @typescript-eslint/no-unnecessary-boolean-literal-compare */ +/* eslint-disable @typescript-eslint/no-empty-interface */ +/* eslint-disable import/consistent-type-specifier-style */ +/* eslint-disable @typescript-eslint/no-unused-vars */ + +import { decodeMessage, encodeMessage, enumeration, message, streamMessage } from 'protons-runtime' +import type { Codec, DecodeOptions, StreamingDecodeOptions, StreamingDecodeWithCollectionsOptions } from 'protons-runtime' import type { Uint8ArrayList } from 'uint8arraylist' export enum EnumType { @@ -13,7 +21,7 @@ enum __EnumTypeValues { } export namespace EnumType { - export const codec = (): Codec => { + export const codec = (): Codec => { return enumeration(__EnumTypeValues) } } @@ -27,11 +35,11 @@ export interface OneOfMessage { } export namespace OneOfMessage { - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -137,19 +145,128 @@ export namespace OneOfMessage { } return obj + }, function * (reader, length, opts = {}) { + let obj: any + + if (opts.emitCollections === true) { + obj = { + fieldFive: '' + } + } else { + obj = {} + } + + const end = length == null ? reader.len : reader.pos + length + + while (reader.pos < end) { + const tag = reader.uint32() + + switch (tag >>> 3) { + case 1: { + yield { + field: 'fieldOne', + value: reader.string() + } + break + } + case 2: { + yield { + field: 'fieldTwo', + value: reader.string() + } + break + } + case 3: { + yield { + field: 'fieldThree', + value: EnumType.codec().decode(reader) + } + break + } + case 4: { + yield { + field: 'fieldFour', + value: EnumType.codec().decode(reader) + } + break + } + case 5: { + yield { + field: 'fieldFive', + value: reader.string() + } + break + } + default: { + reader.skipType(tag & 7) + break + } + } + } + + if (obj.fieldTwo != null) { + delete obj.fieldOne + } + + if (obj.fieldOne != null) { + delete obj.fieldTwo + } + + if (obj.fieldFour != null) { + delete obj.fieldThree + } + + if (obj.fieldThree != null) { + delete obj.fieldFour + } + }) } return _codec } - export const encode = (obj: Partial): Uint8Array => { + export interface OneOfMessageFieldOneFieldEvent { + field: 'fieldOne' + value: string + } + + export interface OneOfMessageFieldTwoFieldEvent { + field: 'fieldTwo' + value: string + } + + export interface OneOfMessageFieldThreeFieldEvent { + field: 'fieldThree' + value: EnumType + } + + export interface OneOfMessageFieldFourFieldEvent { + field: 'fieldFour' + value: EnumType + } + + export interface OneOfMessageFieldFiveFieldEvent { + field: 'fieldFive' + value: string + } + + export type OneOfMessageStreamEvent = OneOfMessageFieldOneFieldEvent | OneOfMessageFieldTwoFieldEvent | OneOfMessageFieldThreeFieldEvent | OneOfMessageFieldFourFieldEvent | OneOfMessageFieldFiveFieldEvent + export type OneOfMessageStreamCollectionsEvent = {} + + export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, OneOfMessage.codec()) } - export const decode = (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): OneOfMessage => { + export function decode (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): OneOfMessage { return decodeMessage(buf, OneOfMessage.codec(), opts) } + + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + return streamMessage(buf, OneOfMessage.codec(), opts) + } } export interface MessageWithoutOneOfs { @@ -161,11 +278,11 @@ export interface MessageWithoutOneOfs { } export namespace MessageWithoutOneOfs { - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -241,17 +358,114 @@ export namespace MessageWithoutOneOfs { } return obj + }, function * (reader, length, opts = {}) { + let obj: any + + if (opts.emitCollections === true) { + obj = { + fieldOne: '', + fieldTwo: '', + fieldThree: EnumType.Val1, + fieldFour: EnumType.Val1, + fieldFive: '' + } + } else { + obj = {} + } + + const end = length == null ? reader.len : reader.pos + length + + while (reader.pos < end) { + const tag = reader.uint32() + + switch (tag >>> 3) { + case 1: { + yield { + field: 'fieldOne', + value: reader.string() + } + break + } + case 2: { + yield { + field: 'fieldTwo', + value: reader.string() + } + break + } + case 3: { + yield { + field: 'fieldThree', + value: EnumType.codec().decode(reader) + } + break + } + case 4: { + yield { + field: 'fieldFour', + value: EnumType.codec().decode(reader) + } + break + } + case 5: { + yield { + field: 'fieldFive', + value: reader.string() + } + break + } + default: { + reader.skipType(tag & 7) + break + } + } + } + }) } return _codec } - export const encode = (obj: Partial): Uint8Array => { + export interface MessageWithoutOneOfsFieldOneFieldEvent { + field: 'fieldOne' + value: string + } + + export interface MessageWithoutOneOfsFieldTwoFieldEvent { + field: 'fieldTwo' + value: string + } + + export interface MessageWithoutOneOfsFieldThreeFieldEvent { + field: 'fieldThree' + value: EnumType + } + + export interface MessageWithoutOneOfsFieldFourFieldEvent { + field: 'fieldFour' + value: EnumType + } + + export interface MessageWithoutOneOfsFieldFiveFieldEvent { + field: 'fieldFive' + value: string + } + + export type MessageWithoutOneOfsStreamEvent = MessageWithoutOneOfsFieldOneFieldEvent | MessageWithoutOneOfsFieldTwoFieldEvent | MessageWithoutOneOfsFieldThreeFieldEvent | MessageWithoutOneOfsFieldFourFieldEvent | MessageWithoutOneOfsFieldFiveFieldEvent + export type MessageWithoutOneOfsStreamCollectionsEvent = {} + + export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, MessageWithoutOneOfs.codec()) } - export const decode = (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): MessageWithoutOneOfs => { + export function decode (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): MessageWithoutOneOfs { return decodeMessage(buf, MessageWithoutOneOfs.codec(), opts) } + + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + return streamMessage(buf, MessageWithoutOneOfs.codec(), opts) + } } diff --git a/packages/protons/test/fixtures/optional.ts b/packages/protons/test/fixtures/optional.ts index ff7a99e..4b6ccf7 100644 --- a/packages/protons/test/fixtures/optional.ts +++ b/packages/protons/test/fixtures/optional.ts @@ -1,7 +1,13 @@ +/* eslint-disable import/export */ /* eslint-disable complexity */ - -import { decodeMessage, encodeMessage, enumeration, message } from 'protons-runtime' -import type { Codec, DecodeOptions } from 'protons-runtime' +/* eslint-disable @typescript-eslint/no-namespace */ +/* eslint-disable @typescript-eslint/no-unnecessary-boolean-literal-compare */ +/* eslint-disable @typescript-eslint/no-empty-interface */ +/* eslint-disable import/consistent-type-specifier-style */ +/* eslint-disable @typescript-eslint/no-unused-vars */ + +import { decodeMessage, encodeMessage, enumeration, message, streamMessage } from 'protons-runtime' +import type { Codec, DecodeOptions, StreamingDecodeOptions, StreamingDecodeWithCollectionsOptions } from 'protons-runtime' import type { Uint8ArrayList } from 'uint8arraylist' export enum OptionalEnum { @@ -17,7 +23,7 @@ enum __OptionalEnumValues { } export namespace OptionalEnum { - export const codec = (): Codec => { + export const codec = (): Codec => { return enumeration(__OptionalEnumValues) } } @@ -28,11 +34,11 @@ export interface OptionalSubMessage { } export namespace OptionalSubMessage { - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -75,19 +81,74 @@ export namespace OptionalSubMessage { } return obj + }, function * (reader, length, opts = {}) { + let obj: any + + if (opts.emitCollections === true) { + obj = {} + } else { + obj = {} + } + + const end = length == null ? reader.len : reader.pos + length + + while (reader.pos < end) { + const tag = reader.uint32() + + switch (tag >>> 3) { + case 1: { + yield { + field: 'foo', + value: reader.string() + } + break + } + case 2: { + yield { + field: 'bar', + value: reader.int32() + } + break + } + default: { + reader.skipType(tag & 7) + break + } + } + } + }) } return _codec } - export const encode = (obj: Partial): Uint8Array => { + export interface OptionalSubMessageFooFieldEvent { + field: 'foo' + value: string + } + + export interface OptionalSubMessageBarFieldEvent { + field: 'bar' + value: number + } + + export type OptionalSubMessageStreamEvent = OptionalSubMessageFooFieldEvent | OptionalSubMessageBarFieldEvent + export type OptionalSubMessageStreamCollectionsEvent = {} + + export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, OptionalSubMessage.codec()) } - export const decode = (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): OptionalSubMessage => { + export function decode (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): OptionalSubMessage { return decodeMessage(buf, OptionalSubMessage.codec(), opts) } + + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + return streamMessage(buf, OptionalSubMessage.codec(), opts) + } } export interface Optional { @@ -111,11 +172,11 @@ export interface Optional { } export namespace Optional { - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -295,17 +356,254 @@ export namespace Optional { } return obj + }, function * (reader, length, opts = {}) { + let obj: any + + if (opts.emitCollections === true) { + obj = {} + } else { + obj = {} + } + + const end = length == null ? reader.len : reader.pos + length + + while (reader.pos < end) { + const tag = reader.uint32() + + switch (tag >>> 3) { + case 1: { + yield { + field: 'double', + value: reader.double() + } + break + } + case 2: { + yield { + field: 'float', + value: reader.float() + } + break + } + case 3: { + yield { + field: 'int32', + value: reader.int32() + } + break + } + case 4: { + yield { + field: 'int64', + value: reader.int64() + } + break + } + case 5: { + yield { + field: 'uint32', + value: reader.uint32() + } + break + } + case 6: { + yield { + field: 'uint64', + value: reader.uint64() + } + break + } + case 7: { + yield { + field: 'sint32', + value: reader.sint32() + } + break + } + case 8: { + yield { + field: 'sint64', + value: reader.sint64() + } + break + } + case 9: { + yield { + field: 'fixed32', + value: reader.fixed32() + } + break + } + case 10: { + yield { + field: 'fixed64', + value: reader.fixed64() + } + break + } + case 11: { + yield { + field: 'sfixed32', + value: reader.sfixed32() + } + break + } + case 12: { + yield { + field: 'sfixed64', + value: reader.sfixed64() + } + break + } + case 13: { + yield { + field: 'bool', + value: reader.bool() + } + break + } + case 14: { + yield { + field: 'string', + value: reader.string() + } + break + } + case 15: { + yield { + field: 'bytes', + value: reader.bytes() + } + break + } + case 16: { + yield { + field: 'enum', + value: OptionalEnum.codec().decode(reader) + } + break + } + case 17: { + yield { + field: 'subMessage', + value: OptionalSubMessage.codec().decode(reader, reader.uint32(), { + limits: opts.limits?.subMessage + }) + } + break + } + default: { + reader.skipType(tag & 7) + break + } + } + } + }) } return _codec } - export const encode = (obj: Partial): Uint8Array => { + export interface OptionalDoubleFieldEvent { + field: 'double' + value: number + } + + export interface OptionalFloatFieldEvent { + field: 'float' + value: number + } + + export interface OptionalInt32FieldEvent { + field: 'int32' + value: number + } + + export interface OptionalInt64FieldEvent { + field: 'int64' + value: bigint + } + + export interface OptionalUint32FieldEvent { + field: 'uint32' + value: number + } + + export interface OptionalUint64FieldEvent { + field: 'uint64' + value: bigint + } + + export interface OptionalSint32FieldEvent { + field: 'sint32' + value: number + } + + export interface OptionalSint64FieldEvent { + field: 'sint64' + value: bigint + } + + export interface OptionalFixed32FieldEvent { + field: 'fixed32' + value: number + } + + export interface OptionalFixed64FieldEvent { + field: 'fixed64' + value: bigint + } + + export interface OptionalSfixed32FieldEvent { + field: 'sfixed32' + value: number + } + + export interface OptionalSfixed64FieldEvent { + field: 'sfixed64' + value: bigint + } + + export interface OptionalBoolFieldEvent { + field: 'bool' + value: boolean + } + + export interface OptionalStringFieldEvent { + field: 'string' + value: string + } + + export interface OptionalBytesFieldEvent { + field: 'bytes' + value: Uint8Array + } + + export interface OptionalEnumFieldEvent { + field: 'enum' + value: OptionalEnum + } + + export interface OptionalSubMessageFieldEvent { + field: 'subMessage' + value: OptionalSubMessage + } + + export type OptionalStreamEvent = OptionalDoubleFieldEvent | OptionalFloatFieldEvent | OptionalInt32FieldEvent | OptionalInt64FieldEvent | OptionalUint32FieldEvent | OptionalUint64FieldEvent | OptionalSint32FieldEvent | OptionalSint64FieldEvent | OptionalFixed32FieldEvent | OptionalFixed64FieldEvent | OptionalSfixed32FieldEvent | OptionalSfixed64FieldEvent | OptionalBoolFieldEvent | OptionalStringFieldEvent | OptionalBytesFieldEvent | OptionalEnumFieldEvent | OptionalSubMessageFieldEvent + export type OptionalStreamCollectionsEvent = {} + + export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, Optional.codec()) } - export const decode = (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Optional => { + export function decode (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Optional { return decodeMessage(buf, Optional.codec(), opts) } + + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + return streamMessage(buf, Optional.codec(), opts) + } } diff --git a/packages/protons/test/fixtures/peer.ts b/packages/protons/test/fixtures/peer.ts index 69c2716..0df907b 100644 --- a/packages/protons/test/fixtures/peer.ts +++ b/packages/protons/test/fixtures/peer.ts @@ -1,6 +1,14 @@ -import { decodeMessage, encodeMessage, MaxLengthError, message } from 'protons-runtime' +/* eslint-disable import/export */ +/* eslint-disable complexity */ +/* eslint-disable @typescript-eslint/no-namespace */ +/* eslint-disable @typescript-eslint/no-unnecessary-boolean-literal-compare */ +/* eslint-disable @typescript-eslint/no-empty-interface */ +/* eslint-disable import/consistent-type-specifier-style */ +/* eslint-disable @typescript-eslint/no-unused-vars */ + +import { decodeMessage, encodeMessage, MaxLengthError, message, streamMessage } from 'protons-runtime' import { alloc as uint8ArrayAlloc } from 'uint8arrays/alloc' -import type { Codec, DecodeOptions } from 'protons-runtime' +import type { Codec, DecodeOptions, StreamingDecodeOptions, StreamingDecodeWithCollectionsOptions } from 'protons-runtime' import type { Uint8ArrayList } from 'uint8arraylist' export interface Peer { @@ -12,11 +20,11 @@ export interface Peer { } export namespace Peer { - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -112,19 +120,151 @@ export namespace Peer { } return obj + }, function * (reader, length, opts = {}) { + let obj: any + + if (opts.emitCollections === true) { + obj = { + addresses: [], + protocols: [], + metadata: [] + } + } else { + obj = {} + } + + const end = length == null ? reader.len : reader.pos + length + + while (reader.pos < end) { + const tag = reader.uint32() + + switch (tag >>> 3) { + case 1: { + if (opts.limits?.addresses != null && obj.addresses.length === opts.limits.addresses) { + throw new MaxLengthError('Decode error - map field "addresses" had too many elements') + } + + yield { + field: 'addresses$value', + index: 0, + value: Address.codec().decode(reader, reader.uint32(), { + limits: opts.limits?.addresses$ + }) + } + break + } + case 2: { + if (opts.limits?.protocols != null && obj.protocols.length === opts.limits.protocols) { + throw new MaxLengthError('Decode error - map field "protocols" had too many elements') + } + + yield { + field: 'protocols$value', + index: 0, + value: reader.string() + } + break + } + case 3: { + if (opts.limits?.metadata != null && obj.metadata.length === opts.limits.metadata) { + throw new MaxLengthError('Decode error - map field "metadata" had too many elements') + } + + yield { + field: 'metadata$value', + index: 0, + value: Metadata.codec().decode(reader, reader.uint32(), { + limits: opts.limits?.metadata$ + }) + } + break + } + case 4: { + yield { + field: 'pubKey', + value: reader.bytes() + } + break + } + case 5: { + yield { + field: 'peerRecordEnvelope', + value: reader.bytes() + } + break + } + default: { + reader.skipType(tag & 7) + break + } + } + } + }) } return _codec } - export const encode = (obj: Partial): Uint8Array => { + export interface PeerAddressesFieldEvent { + field: 'addresses' + value: Address[] + } + + export interface PeerAddressesValueEvent { + field: 'addresses$value' + index: number + value: Address + } + + export interface PeerProtocolsFieldEvent { + field: 'protocols' + value: string[] + } + + export interface PeerProtocolsValueEvent { + field: 'protocols$value' + index: number + value: string + } + + export interface PeerMetadataFieldEvent { + field: 'metadata' + value: Metadata[] + } + + export interface PeerMetadataValueEvent { + field: 'metadata$value' + index: number + value: Metadata + } + + export interface PeerPubKeyFieldEvent { + field: 'pubKey' + value: Uint8Array + } + + export interface PeerPeerRecordEnvelopeFieldEvent { + field: 'peerRecordEnvelope' + value: Uint8Array + } + + export type PeerStreamEvent = PeerAddressesValueEvent | PeerProtocolsValueEvent | PeerMetadataValueEvent | PeerPubKeyFieldEvent | PeerPeerRecordEnvelopeFieldEvent + export type PeerStreamCollectionsEvent = PeerAddressesFieldEvent | PeerProtocolsFieldEvent | PeerMetadataFieldEvent + + export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, Peer.codec()) } - export const decode = (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Peer => { + export function decode (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Peer { return decodeMessage(buf, Peer.codec(), opts) } + + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + return streamMessage(buf, Peer.codec(), opts) + } } export interface Address { @@ -133,11 +273,11 @@ export interface Address { } export namespace Address { - let _codec: Codec
+ let _codec: Codec - export const codec = (): Codec
=> { + export const codec = (): Codec => { if (_codec == null) { - _codec = message
((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -182,19 +322,76 @@ export namespace Address { } return obj + }, function * (reader, length, opts = {}) { + let obj: any + + if (opts.emitCollections === true) { + obj = { + multiaddr: uint8ArrayAlloc(0) + } + } else { + obj = {} + } + + const end = length == null ? reader.len : reader.pos + length + + while (reader.pos < end) { + const tag = reader.uint32() + + switch (tag >>> 3) { + case 1: { + yield { + field: 'multiaddr', + value: reader.bytes() + } + break + } + case 2: { + yield { + field: 'isCertified', + value: reader.bool() + } + break + } + default: { + reader.skipType(tag & 7) + break + } + } + } + }) } return _codec } - export const encode = (obj: Partial
): Uint8Array => { + export interface AddressMultiaddrFieldEvent { + field: 'multiaddr' + value: Uint8Array + } + + export interface AddressIsCertifiedFieldEvent { + field: 'isCertified' + value: boolean + } + + export type AddressStreamEvent = AddressMultiaddrFieldEvent | AddressIsCertifiedFieldEvent + export type AddressStreamCollectionsEvent = {} + + export function encode (obj: Partial
): Uint8Array { return encodeMessage(obj, Address.codec()) } - export const decode = (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions
): Address => { + export function decode (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions
): Address { return decodeMessage(buf, Address.codec(), opts) } + + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions
): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions
): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + return streamMessage(buf, Address.codec(), opts) + } } export interface Metadata { @@ -203,11 +400,11 @@ export interface Metadata { } export namespace Metadata { - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -253,17 +450,75 @@ export namespace Metadata { } return obj + }, function * (reader, length, opts = {}) { + let obj: any + + if (opts.emitCollections === true) { + obj = { + key: '', + value: uint8ArrayAlloc(0) + } + } else { + obj = {} + } + + const end = length == null ? reader.len : reader.pos + length + + while (reader.pos < end) { + const tag = reader.uint32() + + switch (tag >>> 3) { + case 1: { + yield { + field: 'key', + value: reader.string() + } + break + } + case 2: { + yield { + field: 'value', + value: reader.bytes() + } + break + } + default: { + reader.skipType(tag & 7) + break + } + } + } + }) } return _codec } - export const encode = (obj: Partial): Uint8Array => { + export interface MetadataKeyFieldEvent { + field: 'key' + value: string + } + + export interface MetadataValueFieldEvent { + field: 'value' + value: Uint8Array + } + + export type MetadataStreamEvent = MetadataKeyFieldEvent | MetadataValueFieldEvent + export type MetadataStreamCollectionsEvent = {} + + export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, Metadata.codec()) } - export const decode = (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Metadata => { + export function decode (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Metadata { return decodeMessage(buf, Metadata.codec(), opts) } + + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + return streamMessage(buf, Metadata.codec(), opts) + } } diff --git a/packages/protons/test/fixtures/proto2.ts b/packages/protons/test/fixtures/proto2.ts index 9392d43..21431d8 100644 --- a/packages/protons/test/fixtures/proto2.ts +++ b/packages/protons/test/fixtures/proto2.ts @@ -1,5 +1,13 @@ -import { decodeMessage, encodeMessage, message } from 'protons-runtime' -import type { Codec, DecodeOptions } from 'protons-runtime' +/* eslint-disable import/export */ +/* eslint-disable complexity */ +/* eslint-disable @typescript-eslint/no-namespace */ +/* eslint-disable @typescript-eslint/no-unnecessary-boolean-literal-compare */ +/* eslint-disable @typescript-eslint/no-empty-interface */ +/* eslint-disable import/consistent-type-specifier-style */ +/* eslint-disable @typescript-eslint/no-unused-vars */ + +import { decodeMessage, encodeMessage, message, streamMessage } from 'protons-runtime' +import type { Codec, DecodeOptions, StreamingDecodeOptions, StreamingDecodeWithCollectionsOptions } from 'protons-runtime' import type { Uint8ArrayList } from 'uint8arraylist' export interface MessageWithRequired { @@ -7,11 +15,11 @@ export interface MessageWithRequired { } export namespace MessageWithRequired { - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -47,17 +55,62 @@ export namespace MessageWithRequired { } return obj + }, function * (reader, length, opts = {}) { + let obj: any + + if (opts.emitCollections === true) { + obj = { + scalarField: 0 + } + } else { + obj = {} + } + + const end = length == null ? reader.len : reader.pos + length + + while (reader.pos < end) { + const tag = reader.uint32() + + switch (tag >>> 3) { + case 1: { + yield { + field: 'scalarField', + value: reader.int32() + } + break + } + default: { + reader.skipType(tag & 7) + break + } + } + } + }) } return _codec } - export const encode = (obj: Partial): Uint8Array => { + export interface MessageWithRequiredScalarFieldFieldEvent { + field: 'scalarField' + value: number + } + + export type MessageWithRequiredStreamEvent = MessageWithRequiredScalarFieldFieldEvent + export type MessageWithRequiredStreamCollectionsEvent = {} + + export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, MessageWithRequired.codec()) } - export const decode = (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): MessageWithRequired => { + export function decode (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): MessageWithRequired { return decodeMessage(buf, MessageWithRequired.codec(), opts) } + + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + return streamMessage(buf, MessageWithRequired.codec(), opts) + } } diff --git a/packages/protons/test/fixtures/protons-options.ts b/packages/protons/test/fixtures/protons-options.ts index 3ed8c10..dab94f1 100644 --- a/packages/protons/test/fixtures/protons-options.ts +++ b/packages/protons/test/fixtures/protons-options.ts @@ -1,5 +1,13 @@ -import { decodeMessage, encodeMessage, MaxLengthError, MaxSizeError, message } from 'protons-runtime' -import type { Codec, DecodeOptions } from 'protons-runtime' +/* eslint-disable import/export */ +/* eslint-disable complexity */ +/* eslint-disable @typescript-eslint/no-namespace */ +/* eslint-disable @typescript-eslint/no-unnecessary-boolean-literal-compare */ +/* eslint-disable @typescript-eslint/no-empty-interface */ +/* eslint-disable import/consistent-type-specifier-style */ +/* eslint-disable @typescript-eslint/no-unused-vars */ + +import { decodeMessage, encodeMessage, MaxLengthError, MaxSizeError, message, streamMessage } from 'protons-runtime' +import type { Codec, DecodeOptions, StreamingDecodeOptions, StreamingDecodeWithCollectionsOptions } from 'protons-runtime' import type { Uint8ArrayList } from 'uint8arraylist' export interface MessageWithSizeLimitedRepeatedField { @@ -7,11 +15,11 @@ export interface MessageWithSizeLimitedRepeatedField { } export namespace MessageWithSizeLimitedRepeatedField { - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -57,19 +65,79 @@ export namespace MessageWithSizeLimitedRepeatedField { } return obj + }, function * (reader, length, opts = {}) { + let obj: any + + if (opts.emitCollections === true) { + obj = { + repeatedField: [] + } + } else { + obj = {} + } + + const end = length == null ? reader.len : reader.pos + length + + while (reader.pos < end) { + const tag = reader.uint32() + + switch (tag >>> 3) { + case 1: { + if (opts.limits?.repeatedField != null && obj.repeatedField.length === opts.limits.repeatedField) { + throw new MaxLengthError('Decode error - map field "repeatedField" had too many elements') + } + + if (obj.repeatedField.length === 1) { + throw new MaxLengthError('Decode error - repeated field "repeatedField" had too many elements') + } + + yield { + field: 'repeatedField$value', + index: 0, + value: reader.string() + } + break + } + default: { + reader.skipType(tag & 7) + break + } + } + } + }) } return _codec } - export const encode = (obj: Partial): Uint8Array => { + export interface MessageWithSizeLimitedRepeatedFieldRepeatedFieldFieldEvent { + field: 'repeatedField' + value: string[] + } + + export interface MessageWithSizeLimitedRepeatedFieldRepeatedFieldValueEvent { + field: 'repeatedField$value' + index: number + value: string + } + + export type MessageWithSizeLimitedRepeatedFieldStreamEvent = MessageWithSizeLimitedRepeatedFieldRepeatedFieldValueEvent + export type MessageWithSizeLimitedRepeatedFieldStreamCollectionsEvent = MessageWithSizeLimitedRepeatedFieldRepeatedFieldFieldEvent + + export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, MessageWithSizeLimitedRepeatedField.codec()) } - export const decode = (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): MessageWithSizeLimitedRepeatedField => { + export function decode (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): MessageWithSizeLimitedRepeatedField { return decodeMessage(buf, MessageWithSizeLimitedRepeatedField.codec(), opts) } + + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + return streamMessage(buf, MessageWithSizeLimitedRepeatedField.codec(), opts) + } } export interface MessageWithSizeLimitedMap { @@ -83,11 +151,11 @@ export namespace MessageWithSizeLimitedMap { } export namespace MessageWithSizeLimitedMap$mapFieldEntry { - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -133,26 +201,84 @@ export namespace MessageWithSizeLimitedMap { } return obj + }, function * (reader, length, opts = {}) { + let obj: any + + if (opts.emitCollections === true) { + obj = { + key: '', + value: '' + } + } else { + obj = {} + } + + const end = length == null ? reader.len : reader.pos + length + + while (reader.pos < end) { + const tag = reader.uint32() + + switch (tag >>> 3) { + case 1: { + yield { + field: 'key', + value: reader.string() + } + break + } + case 2: { + yield { + field: 'value', + value: reader.string() + } + break + } + default: { + reader.skipType(tag & 7) + break + } + } + } + }) } return _codec } - export const encode = (obj: Partial): Uint8Array => { + export interface MessageWithSizeLimitedMap$mapFieldEntryKeyFieldEvent { + field: 'key' + value: string + } + + export interface MessageWithSizeLimitedMap$mapFieldEntryValueFieldEvent { + field: 'value' + value: string + } + + export type MessageWithSizeLimitedMap$mapFieldEntryStreamEvent = MessageWithSizeLimitedMap$mapFieldEntryKeyFieldEvent | MessageWithSizeLimitedMap$mapFieldEntryValueFieldEvent + export type MessageWithSizeLimitedMap$mapFieldEntryStreamCollectionsEvent = {} + + export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, MessageWithSizeLimitedMap$mapFieldEntry.codec()) } - export const decode = (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): MessageWithSizeLimitedMap$mapFieldEntry => { + export function decode (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): MessageWithSizeLimitedMap$mapFieldEntry { return decodeMessage(buf, MessageWithSizeLimitedMap$mapFieldEntry.codec(), opts) } + + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + return streamMessage(buf, MessageWithSizeLimitedMap$mapFieldEntry.codec(), opts) + } } - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -199,17 +325,79 @@ export namespace MessageWithSizeLimitedMap { } return obj + }, function * (reader, length, opts = {}) { + let obj: any + + if (opts.emitCollections === true) { + obj = { + mapField: new Map() + } + } else { + obj = {} + } + + const end = length == null ? reader.len : reader.pos + length + + while (reader.pos < end) { + const tag = reader.uint32() + + switch (tag >>> 3) { + case 1: { + if (opts.limits?.mapField != null && obj.mapField.size === opts.limits.mapField) { + throw new MaxSizeError('Decode error - map field "mapField" had too many elements') + } + + if (obj.mapField.size === 1) { + throw new MaxSizeError('Decode error - map field "mapField" had too many elements') + } + + const entry = MessageWithSizeLimitedMap.MessageWithSizeLimitedMap$mapFieldEntry.codec().decode(reader, reader.uint32()) + + yield { + field: 'mapField', + key: entry.key, + value: entry.value + } + break + } + default: { + reader.skipType(tag & 7) + break + } + } + } + }) } return _codec } - export const encode = (obj: Partial): Uint8Array => { + export interface MessageWithSizeLimitedMapMapFieldFieldEvent { + field: 'mapField' + value: Map + } + + export interface MessageWithSizeLimitedMapMapFieldEntryEvent { + field: 'mapField$entry' + key: string + value: string + } + + export type MessageWithSizeLimitedMapStreamEvent = MessageWithSizeLimitedMapMapFieldEntryEvent + export type MessageWithSizeLimitedMapStreamCollectionsEvent = MessageWithSizeLimitedMapMapFieldFieldEvent + + export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, MessageWithSizeLimitedMap.codec()) } - export const decode = (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): MessageWithSizeLimitedMap => { + export function decode (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): MessageWithSizeLimitedMap { return decodeMessage(buf, MessageWithSizeLimitedMap.codec(), opts) } + + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + return streamMessage(buf, MessageWithSizeLimitedMap.codec(), opts) + } } diff --git a/packages/protons/test/fixtures/repeated.ts b/packages/protons/test/fixtures/repeated.ts index e971889..05c2ea9 100644 --- a/packages/protons/test/fixtures/repeated.ts +++ b/packages/protons/test/fixtures/repeated.ts @@ -1,7 +1,13 @@ +/* eslint-disable import/export */ /* eslint-disable complexity */ - -import { decodeMessage, encodeMessage, MaxLengthError, message } from 'protons-runtime' -import type { Codec, DecodeOptions } from 'protons-runtime' +/* eslint-disable @typescript-eslint/no-namespace */ +/* eslint-disable @typescript-eslint/no-unnecessary-boolean-literal-compare */ +/* eslint-disable @typescript-eslint/no-empty-interface */ +/* eslint-disable import/consistent-type-specifier-style */ +/* eslint-disable @typescript-eslint/no-unused-vars */ + +import { decodeMessage, encodeMessage, MaxLengthError, message, streamMessage } from 'protons-runtime' +import type { Codec, DecodeOptions, StreamingDecodeOptions, StreamingDecodeWithCollectionsOptions } from 'protons-runtime' import type { Uint8ArrayList } from 'uint8arraylist' export interface SubSubMessage { @@ -10,11 +16,11 @@ export interface SubSubMessage { } export namespace SubSubMessage { - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -65,19 +71,108 @@ export namespace SubSubMessage { } return obj + }, function * (reader, length, opts = {}) { + let obj: any + + if (opts.emitCollections === true) { + obj = { + foo: [] + } + } else { + obj = { + foo: 0 + } + } + + const end = length == null ? reader.len : reader.pos + length + + while (reader.pos < end) { + const tag = reader.uint32() + + switch (tag >>> 3) { + case 1: { + if (opts.limits?.foo != null && (opts.emitCollections === true ? obj.foo.length === opts.limits.foo : obj.foo === opts.limits.foo)) { + throw new MaxLengthError('Decode error - map field "foo" had too many elements') + } + + const value = reader.string() + + yield { + field: 'foo$value', + index: opts.emitCollections === true ? obj.foo.length : obj.foo, + value + } + + if (opts.emitCollections === true) { + obj.foo.push(value) + } else { + obj.foo++ + } + + break + } + case 2: { + yield { + field: 'nonRepeating', + value: reader.uint32() + } + break + } + default: { + reader.skipType(tag & 7) + break + } + } + } + + if (opts.emitCollections === true) { + for (const [key, value] of Object.entries(obj)) { + if (Array.isArray(value) || value instanceof Map) { + yield { + field: key, + value + } + } + } + } }) } return _codec } - export const encode = (obj: Partial): Uint8Array => { + export interface SubSubMessageFooFieldEvent { + field: 'foo' + value: string[] + } + + export interface SubSubMessageFooValueEvent { + field: 'foo$value' + index: number + value: string + } + + export interface SubSubMessageNonRepeatingFieldEvent { + field: 'nonRepeating' + value: number + } + + export type SubSubMessageStreamEvent = SubSubMessageFooValueEvent | SubSubMessageNonRepeatingFieldEvent + export type SubSubMessageStreamCollectionsEvent = SubSubMessageFooFieldEvent + + export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, SubSubMessage.codec()) } - export const decode = (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): SubSubMessage => { + export function decode (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): SubSubMessage { return decodeMessage(buf, SubSubMessage.codec(), opts) } + + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + return streamMessage(buf, SubSubMessage.codec(), opts) + } } export interface SubMessage { @@ -88,11 +183,11 @@ export interface SubMessage { } export namespace SubMessage { - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -172,19 +267,158 @@ export namespace SubMessage { } return obj + }, function * (reader, length, opts = {}) { + let obj: any + + if (opts.emitCollections === true) { + obj = { + foo: [], + messages: [] + } + } else { + obj = { + foo: 0, + messages: 0 + } + } + + const end = length == null ? reader.len : reader.pos + length + + while (reader.pos < end) { + const tag = reader.uint32() + + switch (tag >>> 3) { + case 1: { + if (opts.limits?.foo != null && (opts.emitCollections === true ? obj.foo.length === opts.limits.foo : obj.foo === opts.limits.foo)) { + throw new MaxLengthError('Decode error - map field "foo" had too many elements') + } + + const value = reader.string() + + yield { + field: 'foo$value', + index: opts.emitCollections === true ? obj.foo.length : obj.foo, + value + } + + if (opts.emitCollections === true) { + obj.foo.push(value) + } else { + obj.foo++ + } + + break + } + case 2: { + yield { + field: 'nonRepeating', + value: reader.uint32() + } + break + } + case 3: { + yield { + field: 'message', + value: SubSubMessage.codec().decode(reader, reader.uint32(), { + limits: opts.limits?.message + }) + } + break + } + case 4: { + if (opts.limits?.messages != null && (opts.emitCollections === true ? obj.messages.length === opts.limits.messages : obj.messages === opts.limits.messages)) { + throw new MaxLengthError('Decode error - map field "messages" had too many elements') + } + + const value = SubSubMessage.codec().decode(reader, reader.uint32(), { + limits: opts.limits?.messages$ + }) + + yield { + field: 'messages$value', + index: opts.emitCollections === true ? obj.messages.length : obj.messages, + value + } + + if (opts.emitCollections === true) { + obj.messages.push(value) + } else { + obj.messages++ + } + + break + } + default: { + reader.skipType(tag & 7) + break + } + } + } + + if (opts.emitCollections === true) { + for (const [key, value] of Object.entries(obj)) { + if (Array.isArray(value) || value instanceof Map) { + yield { + field: key, + value + } + } + } + } }) } return _codec } - export const encode = (obj: Partial): Uint8Array => { + export interface SubMessageFooFieldEvent { + field: 'foo' + value: string[] + } + + export interface SubMessageFooValueEvent { + field: 'foo$value' + index: number + value: string + } + + export interface SubMessageNonRepeatingFieldEvent { + field: 'nonRepeating' + value: number + } + + export interface SubMessageMessageFieldEvent { + field: 'message' + value: SubSubMessage + } + + export interface SubMessageMessagesFieldEvent { + field: 'messages' + value: SubSubMessage[] + } + + export interface SubMessageMessagesValueEvent { + field: 'messages$value' + index: number + value: SubSubMessage + } + + export type SubMessageStreamEvent = SubMessageFooValueEvent | SubMessageNonRepeatingFieldEvent | SubMessageMessageFieldEvent | SubMessageMessagesValueEvent + export type SubMessageStreamCollectionsEvent = SubMessageFooFieldEvent | SubMessageMessagesFieldEvent + + export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, SubMessage.codec()) } - export const decode = (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): SubMessage => { + export function decode (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): SubMessage { return decodeMessage(buf, SubMessage.codec(), opts) } + + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + return streamMessage(buf, SubMessage.codec(), opts) + } } export interface RepeatedTypes { @@ -196,11 +430,11 @@ export interface RepeatedTypes { } export namespace RepeatedTypes { - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -300,17 +534,194 @@ export namespace RepeatedTypes { } return obj + }, function * (reader, length, opts = {}) { + let obj: any + + if (opts.emitCollections === true) { + obj = { + number: [], + limitedNumber: [], + messages: [] + } + } else { + obj = { + number: 0, + limitedNumber: 0, + messages: 0 + } + } + + const end = length == null ? reader.len : reader.pos + length + + while (reader.pos < end) { + const tag = reader.uint32() + + switch (tag >>> 3) { + case 1: { + if (opts.limits?.number != null && (opts.emitCollections === true ? obj.number.length === opts.limits.number : obj.number === opts.limits.number)) { + throw new MaxLengthError('Decode error - map field "number" had too many elements') + } + + const value = reader.uint32() + + yield { + field: 'number$value', + index: opts.emitCollections === true ? obj.number.length : obj.number, + value + } + + if (opts.emitCollections === true) { + obj.number.push(value) + } else { + obj.number++ + } + + break + } + case 2: { + if (opts.limits?.limitedNumber != null && (opts.emitCollections === true ? obj.limitedNumber.length === opts.limits.limitedNumber : obj.limitedNumber === opts.limits.limitedNumber)) { + throw new MaxLengthError('Decode error - map field "limitedNumber" had too many elements') + } + + if (opts.emitCollections === true ? obj.limitedNumber.length === 1 : obj.limitedNumber === 1) { + throw new MaxLengthError('Decode error - repeated field "limitedNumber" had too many elements') + } + + const value = reader.uint32() + + yield { + field: 'limitedNumber$value', + index: opts.emitCollections === true ? obj.limitedNumber.length : obj.limitedNumber, + value + } + + if (opts.emitCollections === true) { + obj.limitedNumber.push(value) + } else { + obj.limitedNumber++ + } + + break + } + case 3: { + if (opts.limits?.messages != null && (opts.emitCollections === true ? obj.messages.length === opts.limits.messages : obj.messages === opts.limits.messages)) { + throw new MaxLengthError('Decode error - map field "messages" had too many elements') + } + + const value = SubMessage.codec().decode(reader, reader.uint32(), { + limits: opts.limits?.messages$ + }) + + yield { + field: 'messages$value', + index: opts.emitCollections === true ? obj.messages.length : obj.messages, + value + } + + if (opts.emitCollections === true) { + obj.messages.push(value) + } else { + obj.messages++ + } + + break + } + case 4: { + yield { + field: 'message', + value: SubMessage.codec().decode(reader, reader.uint32(), { + limits: opts.limits?.message + }) + } + break + } + case 5: { + yield { + field: 'nonRepeating', + value: reader.uint32() + } + break + } + default: { + reader.skipType(tag & 7) + break + } + } + } + + if (opts.emitCollections === true) { + for (const [key, value] of Object.entries(obj)) { + if (Array.isArray(value) || value instanceof Map) { + yield { + field: key, + value + } + } + } + } }) } return _codec } - export const encode = (obj: Partial): Uint8Array => { + export interface RepeatedTypesNumberFieldEvent { + field: 'number' + value: number[] + } + + export interface RepeatedTypesNumberValueEvent { + field: 'number$value' + index: number + value: number + } + + export interface RepeatedTypesLimitedNumberFieldEvent { + field: 'limitedNumber' + value: number[] + } + + export interface RepeatedTypesLimitedNumberValueEvent { + field: 'limitedNumber$value' + index: number + value: number + } + + export interface RepeatedTypesMessagesFieldEvent { + field: 'messages' + value: SubMessage[] + } + + export interface RepeatedTypesMessagesValueEvent { + field: 'messages$value' + index: number + value: SubMessage + } + + export interface RepeatedTypesMessageFieldEvent { + field: 'message' + value: SubMessage + } + + export interface RepeatedTypesNonRepeatingFieldEvent { + field: 'nonRepeating' + value: number + } + + export type RepeatedTypesStreamEvent = RepeatedTypesNumberValueEvent | RepeatedTypesLimitedNumberValueEvent | RepeatedTypesMessagesValueEvent | RepeatedTypesMessageFieldEvent | RepeatedTypesNonRepeatingFieldEvent + export type RepeatedTypesStreamCollectionsEvent = RepeatedTypesNumberFieldEvent | RepeatedTypesLimitedNumberFieldEvent | RepeatedTypesMessagesFieldEvent + + export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, RepeatedTypes.codec()) } - export const decode = (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): RepeatedTypes => { + export function decode (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): RepeatedTypes { return decodeMessage(buf, RepeatedTypes.codec(), opts) } + + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + return streamMessage(buf, RepeatedTypes.codec(), opts) + } } diff --git a/packages/protons/test/fixtures/singular.ts b/packages/protons/test/fixtures/singular.ts index f8e5238..4e67d46 100644 --- a/packages/protons/test/fixtures/singular.ts +++ b/packages/protons/test/fixtures/singular.ts @@ -1,8 +1,14 @@ +/* eslint-disable import/export */ /* eslint-disable complexity */ +/* eslint-disable @typescript-eslint/no-namespace */ +/* eslint-disable @typescript-eslint/no-unnecessary-boolean-literal-compare */ +/* eslint-disable @typescript-eslint/no-empty-interface */ +/* eslint-disable import/consistent-type-specifier-style */ +/* eslint-disable @typescript-eslint/no-unused-vars */ -import { decodeMessage, encodeMessage, enumeration, message } from 'protons-runtime' +import { decodeMessage, encodeMessage, enumeration, message, streamMessage } from 'protons-runtime' import { alloc as uint8ArrayAlloc } from 'uint8arrays/alloc' -import type { Codec, DecodeOptions } from 'protons-runtime' +import type { Codec, DecodeOptions, StreamingDecodeOptions, StreamingDecodeWithCollectionsOptions } from 'protons-runtime' import type { Uint8ArrayList } from 'uint8arraylist' export enum SingularEnum { @@ -18,7 +24,7 @@ enum __SingularEnumValues { } export namespace SingularEnum { - export const codec = (): Codec => { + export const codec = (): Codec => { return enumeration(__SingularEnumValues) } } @@ -29,11 +35,11 @@ export interface SingularSubMessage { } export namespace SingularSubMessage { - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -79,19 +85,77 @@ export namespace SingularSubMessage { } return obj + }, function * (reader, length, opts = {}) { + let obj: any + + if (opts.emitCollections === true) { + obj = { + foo: '', + bar: 0 + } + } else { + obj = {} + } + + const end = length == null ? reader.len : reader.pos + length + + while (reader.pos < end) { + const tag = reader.uint32() + + switch (tag >>> 3) { + case 1: { + yield { + field: 'foo', + value: reader.string() + } + break + } + case 2: { + yield { + field: 'bar', + value: reader.int32() + } + break + } + default: { + reader.skipType(tag & 7) + break + } + } + } + }) } return _codec } - export const encode = (obj: Partial): Uint8Array => { + export interface SingularSubMessageFooFieldEvent { + field: 'foo' + value: string + } + + export interface SingularSubMessageBarFieldEvent { + field: 'bar' + value: number + } + + export type SingularSubMessageStreamEvent = SingularSubMessageFooFieldEvent | SingularSubMessageBarFieldEvent + export type SingularSubMessageStreamCollectionsEvent = {} + + export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, SingularSubMessage.codec()) } - export const decode = (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): SingularSubMessage => { + export function decode (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): SingularSubMessage { return decodeMessage(buf, SingularSubMessage.codec(), opts) } + + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + return streamMessage(buf, SingularSubMessage.codec(), opts) + } } export interface Singular { @@ -115,11 +179,11 @@ export interface Singular { } export namespace Singular { - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -316,17 +380,271 @@ export namespace Singular { } return obj + }, function * (reader, length, opts = {}) { + let obj: any + + if (opts.emitCollections === true) { + obj = { + double: 0, + float: 0, + int32: 0, + int64: 0n, + uint32: 0, + uint64: 0n, + sint32: 0, + sint64: 0n, + fixed32: 0, + fixed64: 0n, + sfixed32: 0, + sfixed64: 0n, + bool: false, + string: '', + bytes: uint8ArrayAlloc(0), + enum: SingularEnum.NO_VALUE + } + } else { + obj = {} + } + + const end = length == null ? reader.len : reader.pos + length + + while (reader.pos < end) { + const tag = reader.uint32() + + switch (tag >>> 3) { + case 1: { + yield { + field: 'double', + value: reader.double() + } + break + } + case 2: { + yield { + field: 'float', + value: reader.float() + } + break + } + case 3: { + yield { + field: 'int32', + value: reader.int32() + } + break + } + case 4: { + yield { + field: 'int64', + value: reader.int64() + } + break + } + case 5: { + yield { + field: 'uint32', + value: reader.uint32() + } + break + } + case 6: { + yield { + field: 'uint64', + value: reader.uint64() + } + break + } + case 7: { + yield { + field: 'sint32', + value: reader.sint32() + } + break + } + case 8: { + yield { + field: 'sint64', + value: reader.sint64() + } + break + } + case 9: { + yield { + field: 'fixed32', + value: reader.fixed32() + } + break + } + case 10: { + yield { + field: 'fixed64', + value: reader.fixed64() + } + break + } + case 11: { + yield { + field: 'sfixed32', + value: reader.sfixed32() + } + break + } + case 12: { + yield { + field: 'sfixed64', + value: reader.sfixed64() + } + break + } + case 13: { + yield { + field: 'bool', + value: reader.bool() + } + break + } + case 14: { + yield { + field: 'string', + value: reader.string() + } + break + } + case 15: { + yield { + field: 'bytes', + value: reader.bytes() + } + break + } + case 16: { + yield { + field: 'enum', + value: SingularEnum.codec().decode(reader) + } + break + } + case 17: { + yield { + field: 'subMessage', + value: SingularSubMessage.codec().decode(reader, reader.uint32(), { + limits: opts.limits?.subMessage + }) + } + break + } + default: { + reader.skipType(tag & 7) + break + } + } + } + }) } return _codec } - export const encode = (obj: Partial): Uint8Array => { + export interface SingularDoubleFieldEvent { + field: 'double' + value: number + } + + export interface SingularFloatFieldEvent { + field: 'float' + value: number + } + + export interface SingularInt32FieldEvent { + field: 'int32' + value: number + } + + export interface SingularInt64FieldEvent { + field: 'int64' + value: bigint + } + + export interface SingularUint32FieldEvent { + field: 'uint32' + value: number + } + + export interface SingularUint64FieldEvent { + field: 'uint64' + value: bigint + } + + export interface SingularSint32FieldEvent { + field: 'sint32' + value: number + } + + export interface SingularSint64FieldEvent { + field: 'sint64' + value: bigint + } + + export interface SingularFixed32FieldEvent { + field: 'fixed32' + value: number + } + + export interface SingularFixed64FieldEvent { + field: 'fixed64' + value: bigint + } + + export interface SingularSfixed32FieldEvent { + field: 'sfixed32' + value: number + } + + export interface SingularSfixed64FieldEvent { + field: 'sfixed64' + value: bigint + } + + export interface SingularBoolFieldEvent { + field: 'bool' + value: boolean + } + + export interface SingularStringFieldEvent { + field: 'string' + value: string + } + + export interface SingularBytesFieldEvent { + field: 'bytes' + value: Uint8Array + } + + export interface SingularEnumFieldEvent { + field: 'enum' + value: SingularEnum + } + + export interface SingularSubMessageFieldEvent { + field: 'subMessage' + value: SingularSubMessage + } + + export type SingularStreamEvent = SingularDoubleFieldEvent | SingularFloatFieldEvent | SingularInt32FieldEvent | SingularInt64FieldEvent | SingularUint32FieldEvent | SingularUint64FieldEvent | SingularSint32FieldEvent | SingularSint64FieldEvent | SingularFixed32FieldEvent | SingularFixed64FieldEvent | SingularSfixed32FieldEvent | SingularSfixed64FieldEvent | SingularBoolFieldEvent | SingularStringFieldEvent | SingularBytesFieldEvent | SingularEnumFieldEvent | SingularSubMessageFieldEvent + export type SingularStreamCollectionsEvent = {} + + export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, Singular.codec()) } - export const decode = (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Singular => { + export function decode (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Singular { return decodeMessage(buf, Singular.codec(), opts) } + + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + return streamMessage(buf, Singular.codec(), opts) + } } diff --git a/packages/protons/test/fixtures/test.ts b/packages/protons/test/fixtures/test.ts index 5fc17f6..1598084 100644 --- a/packages/protons/test/fixtures/test.ts +++ b/packages/protons/test/fixtures/test.ts @@ -1,7 +1,13 @@ +/* eslint-disable import/export */ /* eslint-disable complexity */ - -import { decodeMessage, encodeMessage, enumeration, MaxLengthError, message } from 'protons-runtime' -import type { Codec, DecodeOptions } from 'protons-runtime' +/* eslint-disable @typescript-eslint/no-namespace */ +/* eslint-disable @typescript-eslint/no-unnecessary-boolean-literal-compare */ +/* eslint-disable @typescript-eslint/no-empty-interface */ +/* eslint-disable import/consistent-type-specifier-style */ +/* eslint-disable @typescript-eslint/no-unused-vars */ + +import { decodeMessage, encodeMessage, enumeration, MaxLengthError, message, streamMessage } from 'protons-runtime' +import type { Codec, DecodeOptions, StreamingDecodeOptions, StreamingDecodeWithCollectionsOptions } from 'protons-runtime' import type { Uint8ArrayList } from 'uint8arraylist' export enum AnEnum { @@ -15,7 +21,7 @@ enum __AnEnumValues { } export namespace AnEnum { - export const codec = (): Codec => { + export const codec = (): Codec => { return enumeration(__AnEnumValues) } } @@ -25,11 +31,11 @@ export interface SubMessage { } export namespace SubMessage { - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -65,19 +71,74 @@ export namespace SubMessage { } return obj + }, function * (reader, length, opts = {}) { + let obj: any + + if (opts.emitCollections === true) { + obj = { + foo: '' + } + } else { + obj = {} + } + + const end = length == null ? reader.len : reader.pos + length + + while (reader.pos < end) { + const tag = reader.uint32() + + switch (tag >>> 3) { + case 1: { + yield { + field: 'foo', + value: reader.string() + } + break + } + default: { + reader.skipType(tag & 7) + break + } + } + } + + if (opts.emitCollections === true) { + for (const [key, value] of Object.entries(obj)) { + if (Array.isArray(value) || value instanceof Map) { + yield { + field: key, + value + } + } + } + } }) } return _codec } - export const encode = (obj: Partial): Uint8Array => { + export interface SubMessageFooFieldEvent { + field: 'foo' + value: string + } + + export type SubMessageStreamEvent = SubMessageFooFieldEvent + export type SubMessageStreamCollectionsEvent = {} + + export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, SubMessage.codec()) } - export const decode = (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): SubMessage => { + export function decode (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): SubMessage { return decodeMessage(buf, SubMessage.codec(), opts) } + + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + return streamMessage(buf, SubMessage.codec(), opts) + } } export interface AllTheTypes { @@ -102,11 +163,11 @@ export interface AllTheTypes { } export namespace AllTheTypes { - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -303,17 +364,300 @@ export namespace AllTheTypes { } return obj + }, function * (reader, length, opts = {}) { + let obj: any + + if (opts.emitCollections === true) { + obj = { + field14: [] + } + } else { + obj = { + field14: 0 + } + } + + const end = length == null ? reader.len : reader.pos + length + + while (reader.pos < end) { + const tag = reader.uint32() + + switch (tag >>> 3) { + case 1: { + yield { + field: 'field1', + value: reader.bool() + } + break + } + case 2: { + yield { + field: 'field2', + value: reader.int32() + } + break + } + case 3: { + yield { + field: 'field3', + value: reader.int64() + } + break + } + case 4: { + yield { + field: 'field4', + value: reader.uint32() + } + break + } + case 5: { + yield { + field: 'field5', + value: reader.uint64() + } + break + } + case 6: { + yield { + field: 'field6', + value: reader.sint32() + } + break + } + case 7: { + yield { + field: 'field7', + value: reader.sint64() + } + break + } + case 8: { + yield { + field: 'field8', + value: reader.double() + } + break + } + case 9: { + yield { + field: 'field9', + value: reader.float() + } + break + } + case 10: { + yield { + field: 'field10', + value: reader.string() + } + break + } + case 11: { + yield { + field: 'field11', + value: reader.bytes() + } + break + } + case 12: { + yield { + field: 'field12', + value: AnEnum.codec().decode(reader) + } + break + } + case 13: { + yield { + field: 'field13', + value: SubMessage.codec().decode(reader, reader.uint32(), { + limits: opts.limits?.field13 + }) + } + break + } + case 14: { + if (opts.limits?.field14 != null && (opts.emitCollections === true ? obj.field14.length === opts.limits.field14 : obj.field14 === opts.limits.field14)) { + throw new MaxLengthError('Decode error - map field "field14" had too many elements') + } + + const value = reader.string() + + yield { + field: 'field14$value', + index: opts.emitCollections === true ? obj.field14.length : obj.field14, + value + } + + if (opts.emitCollections === true) { + obj.field14.push(value) + } else { + obj.field14++ + } + + break + } + case 15: { + yield { + field: 'field15', + value: reader.fixed32() + } + break + } + case 16: { + yield { + field: 'field16', + value: reader.fixed64() + } + break + } + case 17: { + yield { + field: 'field17', + value: reader.sfixed32() + } + break + } + case 18: { + yield { + field: 'field18', + value: reader.sfixed64() + } + break + } + default: { + reader.skipType(tag & 7) + break + } + } + } + + if (opts.emitCollections === true) { + for (const [key, value] of Object.entries(obj)) { + if (Array.isArray(value) || value instanceof Map) { + yield { + field: key, + value + } + } + } + } }) } return _codec } - export const encode = (obj: Partial): Uint8Array => { + export interface AllTheTypesField1FieldEvent { + field: 'field1' + value: boolean + } + + export interface AllTheTypesField2FieldEvent { + field: 'field2' + value: number + } + + export interface AllTheTypesField3FieldEvent { + field: 'field3' + value: bigint + } + + export interface AllTheTypesField4FieldEvent { + field: 'field4' + value: number + } + + export interface AllTheTypesField5FieldEvent { + field: 'field5' + value: bigint + } + + export interface AllTheTypesField6FieldEvent { + field: 'field6' + value: number + } + + export interface AllTheTypesField7FieldEvent { + field: 'field7' + value: bigint + } + + export interface AllTheTypesField8FieldEvent { + field: 'field8' + value: number + } + + export interface AllTheTypesField9FieldEvent { + field: 'field9' + value: number + } + + export interface AllTheTypesField10FieldEvent { + field: 'field10' + value: string + } + + export interface AllTheTypesField11FieldEvent { + field: 'field11' + value: Uint8Array + } + + export interface AllTheTypesField12FieldEvent { + field: 'field12' + value: AnEnum + } + + export interface AllTheTypesField13FieldEvent { + field: 'field13' + value: SubMessage + } + + export interface AllTheTypesField14FieldEvent { + field: 'field14' + value: string[] + } + + export interface AllTheTypesField14ValueEvent { + field: 'field14$value' + index: number + value: string + } + + export interface AllTheTypesField15FieldEvent { + field: 'field15' + value: number + } + + export interface AllTheTypesField16FieldEvent { + field: 'field16' + value: bigint + } + + export interface AllTheTypesField17FieldEvent { + field: 'field17' + value: number + } + + export interface AllTheTypesField18FieldEvent { + field: 'field18' + value: bigint + } + + export type AllTheTypesStreamEvent = AllTheTypesField1FieldEvent | AllTheTypesField2FieldEvent | AllTheTypesField3FieldEvent | AllTheTypesField4FieldEvent | AllTheTypesField5FieldEvent | AllTheTypesField6FieldEvent | AllTheTypesField7FieldEvent | AllTheTypesField8FieldEvent | AllTheTypesField9FieldEvent | AllTheTypesField10FieldEvent | AllTheTypesField11FieldEvent | AllTheTypesField12FieldEvent | AllTheTypesField13FieldEvent | AllTheTypesField14ValueEvent | AllTheTypesField15FieldEvent | AllTheTypesField16FieldEvent | AllTheTypesField17FieldEvent | AllTheTypesField18FieldEvent + export type AllTheTypesStreamCollectionsEvent = AllTheTypesField14FieldEvent + + export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, AllTheTypes.codec()) } - export const decode = (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): AllTheTypes => { + export function decode (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): AllTheTypes { return decodeMessage(buf, AllTheTypes.codec(), opts) } + + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + return streamMessage(buf, AllTheTypes.codec(), opts) + } } diff --git a/packages/protons/test/streaming-decode.spec.ts b/packages/protons/test/streaming-decode.spec.ts new file mode 100644 index 0000000..a9220c3 --- /dev/null +++ b/packages/protons/test/streaming-decode.spec.ts @@ -0,0 +1,103 @@ +import { expect } from 'aegir/chai' +import { AllTheTypes, AnEnum } from './fixtures/test.ts' +import all from 'it-all' + +describe('streaming-decode', () => { + it('should yield collections when asked to', async () => { + const values = { + field1: true, + field2: 2, + field3: 3n, + field4: 4, + field5: 5n, + field6: 6, + field7: 7n, + field8: 8, + field9: 9, + field10: '10', + field11: Uint8Array.from([11]), + field12: AnEnum.DERP, + field13: { + foo: '13' + }, + field14: [ + '14' + ], + field15: 15, + field16: 16n, + field17: 17, + field18: 18n + } + const input = AllTheTypes.encode(values) + + const events = all(AllTheTypes.stream(input, { + emitCollections: false + })) + + expect(events).to.have.lengthOf(Object.entries(values).length) + + const eventsWithCollections = all(AllTheTypes.stream(input, { + emitCollections: true + })) + + expect(eventsWithCollections).to.have.lengthOf(Object.entries(values).length + 1) + }) + + it('should include indexes in field values', async () => { + const input = AllTheTypes.encode({ + field14: [ + '1', '2', '3' + ] + }) + + const output = all(AllTheTypes.stream(input)) + + expect(output).to.deep.equal([{ + field: 'field14$value', + index: 0, + value: '1' + }, { + field: 'field14$value', + index: 1, + value: '2' + }, { + field: 'field14$value', + index: 2, + value: '3' + }]) + }) + + it('should not parse input after exiting loop', () => { + const input = AllTheTypes.encode({ + field1: true, + field2: 5, + field14: [ + '1', '2', '3' + ] + }) + + const output = [] + + // make input invalid + input[9] = 0 + input[10] = 0 + input[11] = 0 + input[12] = 0 + + // cannot read input to completion + expect(() => { + all(AllTheTypes.stream(input)) + }).to.throw().with.property('name', 'RangeError') + + // can read first couple of values + for (const evt of AllTheTypes.stream(input)) { + output.push(evt) + + if (evt.field === 'field2') { + break + } + } + + expect(output).to.have.lengthOf(2) + }) +}) From b9144d99b41032054ca0692be2f89257e205ec64 Mon Sep 17 00:00:00 2001 From: achingbrain Date: Wed, 18 Mar 2026 16:00:19 +0100 Subject: [PATCH 2/4] chore: linting --- .../src/implementations/protobufjs/rpc.d.ts | 1009 ------- .../src/implementations/protobufjs/rpc.js | 2643 ----------------- .../src/implementations/protons/bench.ts | 490 ++- .../src/implementations/protons/rpc.ts | 734 ----- packages/protons/src/index.ts | 3 +- packages/protons/test/fixtures/basic.ts | 34 +- packages/protons/test/fixtures/bitswap.ts | 176 +- packages/protons/test/fixtures/circuit.ts | 53 +- .../test/fixtures/custom-option-jstype.ts | 56 +- packages/protons/test/fixtures/daemon.ts | 488 ++- packages/protons/test/fixtures/dht.ts | 108 +- packages/protons/test/fixtures/maps.ts | 202 +- packages/protons/test/fixtures/noise.ts | 38 +- packages/protons/test/fixtures/oneof.ts | 44 +- packages/protons/test/fixtures/optional.ts | 26 +- packages/protons/test/fixtures/peer.ts | 113 +- packages/protons/test/fixtures/proto2.ts | 22 +- .../protons/test/fixtures/protons-options.ts | 88 +- packages/protons/test/fixtures/repeated.ts | 32 +- packages/protons/test/fixtures/singular.ts | 66 +- packages/protons/test/fixtures/test.ts | 14 +- .../protons/test/streaming-decode.spec.ts | 2 +- 22 files changed, 1576 insertions(+), 4865 deletions(-) delete mode 100644 packages/protons-benchmark/src/implementations/protobufjs/rpc.d.ts delete mode 100644 packages/protons-benchmark/src/implementations/protobufjs/rpc.js delete mode 100644 packages/protons-benchmark/src/implementations/protons/rpc.ts diff --git a/packages/protons-benchmark/src/implementations/protobufjs/rpc.d.ts b/packages/protons-benchmark/src/implementations/protobufjs/rpc.d.ts deleted file mode 100644 index fafe66e..0000000 --- a/packages/protons-benchmark/src/implementations/protobufjs/rpc.d.ts +++ /dev/null @@ -1,1009 +0,0 @@ -/* eslint-disable */ -import * as $protobuf from "protobufjs"; -/** Properties of a RPC. */ -export interface IRPC { - - /** RPC subscriptions */ - subscriptions?: (RPC.ISubOpts[]|null); - - /** RPC messages */ - messages?: (RPC.IMessage[]|null); - - /** RPC control */ - control?: (RPC.IControlMessage|null); -} - -/** Represents a RPC. */ -export class RPC implements IRPC { - - /** - * Constructs a new RPC. - * @param [properties] Properties to set - */ - constructor(properties?: IRPC); - - /** RPC subscriptions. */ - public subscriptions: RPC.ISubOpts[]; - - /** RPC messages. */ - public messages: RPC.IMessage[]; - - /** RPC control. */ - public control?: (RPC.IControlMessage|null); - - /** RPC _control. */ - public _control?: "control"; - - /** - * Creates a new RPC instance using the specified properties. - * @param [properties] Properties to set - * @returns RPC instance - */ - public static create(properties?: IRPC): RPC; - - /** - * Encodes the specified RPC message. Does not implicitly {@link RPC.verify|verify} messages. - * @param message RPC message or plain object to encode - * @param [writer] Writer to encode to - * @returns Writer - */ - public static encode(message: IRPC, writer?: $protobuf.Writer): $protobuf.Writer; - - /** - * Encodes the specified RPC message, length delimited. Does not implicitly {@link RPC.verify|verify} messages. - * @param message RPC message or plain object to encode - * @param [writer] Writer to encode to - * @returns Writer - */ - public static encodeDelimited(message: IRPC, writer?: $protobuf.Writer): $protobuf.Writer; - - /** - * Decodes a RPC message from the specified reader or buffer. - * @param reader Reader or buffer to decode from - * @param [length] Message length if known beforehand - * @returns RPC - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): RPC; - - /** - * Decodes a RPC message from the specified reader or buffer, length delimited. - * @param reader Reader or buffer to decode from - * @returns RPC - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): RPC; - - /** - * Verifies a RPC message. - * @param message Plain object to verify - * @returns `null` if valid, otherwise the reason why it is not - */ - public static verify(message: { [k: string]: any }): (string|null); - - /** - * Creates a RPC message from a plain object. Also converts values to their respective internal types. - * @param object Plain object - * @returns RPC - */ - public static fromObject(object: { [k: string]: any }): RPC; - - /** - * Creates a plain object from a RPC message. Also converts values to other types if specified. - * @param message RPC - * @param [options] Conversion options - * @returns Plain object - */ - public static toObject(message: RPC, options?: $protobuf.IConversionOptions): { [k: string]: any }; - - /** - * Converts this RPC to JSON. - * @returns JSON object - */ - public toJSON(): { [k: string]: any }; - - /** - * Gets the default type url for RPC - * @param [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") - * @returns The default type url - */ - public static getTypeUrl(typeUrlPrefix?: string): string; -} - -export namespace RPC { - - /** Properties of a SubOpts. */ - interface ISubOpts { - - /** SubOpts subscribe */ - subscribe?: (boolean|null); - - /** SubOpts topic */ - topic?: (string|null); - } - - /** Represents a SubOpts. */ - class SubOpts implements ISubOpts { - - /** - * Constructs a new SubOpts. - * @param [properties] Properties to set - */ - constructor(properties?: RPC.ISubOpts); - - /** SubOpts subscribe. */ - public subscribe?: (boolean|null); - - /** SubOpts topic. */ - public topic?: (string|null); - - /** SubOpts _subscribe. */ - public _subscribe?: "subscribe"; - - /** SubOpts _topic. */ - public _topic?: "topic"; - - /** - * Creates a new SubOpts instance using the specified properties. - * @param [properties] Properties to set - * @returns SubOpts instance - */ - public static create(properties?: RPC.ISubOpts): RPC.SubOpts; - - /** - * Encodes the specified SubOpts message. Does not implicitly {@link RPC.SubOpts.verify|verify} messages. - * @param message SubOpts message or plain object to encode - * @param [writer] Writer to encode to - * @returns Writer - */ - public static encode(message: RPC.ISubOpts, writer?: $protobuf.Writer): $protobuf.Writer; - - /** - * Encodes the specified SubOpts message, length delimited. Does not implicitly {@link RPC.SubOpts.verify|verify} messages. - * @param message SubOpts message or plain object to encode - * @param [writer] Writer to encode to - * @returns Writer - */ - public static encodeDelimited(message: RPC.ISubOpts, writer?: $protobuf.Writer): $protobuf.Writer; - - /** - * Decodes a SubOpts message from the specified reader or buffer. - * @param reader Reader or buffer to decode from - * @param [length] Message length if known beforehand - * @returns SubOpts - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): RPC.SubOpts; - - /** - * Decodes a SubOpts message from the specified reader or buffer, length delimited. - * @param reader Reader or buffer to decode from - * @returns SubOpts - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): RPC.SubOpts; - - /** - * Verifies a SubOpts message. - * @param message Plain object to verify - * @returns `null` if valid, otherwise the reason why it is not - */ - public static verify(message: { [k: string]: any }): (string|null); - - /** - * Creates a SubOpts message from a plain object. Also converts values to their respective internal types. - * @param object Plain object - * @returns SubOpts - */ - public static fromObject(object: { [k: string]: any }): RPC.SubOpts; - - /** - * Creates a plain object from a SubOpts message. Also converts values to other types if specified. - * @param message SubOpts - * @param [options] Conversion options - * @returns Plain object - */ - public static toObject(message: RPC.SubOpts, options?: $protobuf.IConversionOptions): { [k: string]: any }; - - /** - * Converts this SubOpts to JSON. - * @returns JSON object - */ - public toJSON(): { [k: string]: any }; - - /** - * Gets the default type url for SubOpts - * @param [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") - * @returns The default type url - */ - public static getTypeUrl(typeUrlPrefix?: string): string; - } - - /** Properties of a Message. */ - interface IMessage { - - /** Message from */ - from?: (Uint8Array|null); - - /** Message data */ - data?: (Uint8Array|null); - - /** Message seqno */ - seqno?: (Uint8Array|null); - - /** Message topic */ - topic: string; - - /** Message signature */ - signature?: (Uint8Array|null); - - /** Message key */ - key?: (Uint8Array|null); - } - - /** Represents a Message. */ - class Message implements IMessage { - - /** - * Constructs a new Message. - * @param [properties] Properties to set - */ - constructor(properties?: RPC.IMessage); - - /** Message from. */ - public from?: (Uint8Array|null); - - /** Message data. */ - public data?: (Uint8Array|null); - - /** Message seqno. */ - public seqno?: (Uint8Array|null); - - /** Message topic. */ - public topic: string; - - /** Message signature. */ - public signature?: (Uint8Array|null); - - /** Message key. */ - public key?: (Uint8Array|null); - - /** Message _from. */ - public _from?: "from"; - - /** Message _data. */ - public _data?: "data"; - - /** Message _seqno. */ - public _seqno?: "seqno"; - - /** Message _signature. */ - public _signature?: "signature"; - - /** Message _key. */ - public _key?: "key"; - - /** - * Creates a new Message instance using the specified properties. - * @param [properties] Properties to set - * @returns Message instance - */ - public static create(properties?: RPC.IMessage): RPC.Message; - - /** - * Encodes the specified Message message. Does not implicitly {@link RPC.Message.verify|verify} messages. - * @param message Message message or plain object to encode - * @param [writer] Writer to encode to - * @returns Writer - */ - public static encode(message: RPC.IMessage, writer?: $protobuf.Writer): $protobuf.Writer; - - /** - * Encodes the specified Message message, length delimited. Does not implicitly {@link RPC.Message.verify|verify} messages. - * @param message Message message or plain object to encode - * @param [writer] Writer to encode to - * @returns Writer - */ - public static encodeDelimited(message: RPC.IMessage, writer?: $protobuf.Writer): $protobuf.Writer; - - /** - * Decodes a Message message from the specified reader or buffer. - * @param reader Reader or buffer to decode from - * @param [length] Message length if known beforehand - * @returns Message - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): RPC.Message; - - /** - * Decodes a Message message from the specified reader or buffer, length delimited. - * @param reader Reader or buffer to decode from - * @returns Message - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): RPC.Message; - - /** - * Verifies a Message message. - * @param message Plain object to verify - * @returns `null` if valid, otherwise the reason why it is not - */ - public static verify(message: { [k: string]: any }): (string|null); - - /** - * Creates a Message message from a plain object. Also converts values to their respective internal types. - * @param object Plain object - * @returns Message - */ - public static fromObject(object: { [k: string]: any }): RPC.Message; - - /** - * Creates a plain object from a Message message. Also converts values to other types if specified. - * @param message Message - * @param [options] Conversion options - * @returns Plain object - */ - public static toObject(message: RPC.Message, options?: $protobuf.IConversionOptions): { [k: string]: any }; - - /** - * Converts this Message to JSON. - * @returns JSON object - */ - public toJSON(): { [k: string]: any }; - - /** - * Gets the default type url for Message - * @param [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") - * @returns The default type url - */ - public static getTypeUrl(typeUrlPrefix?: string): string; - } - - /** Properties of a ControlMessage. */ - interface IControlMessage { - - /** ControlMessage ihave */ - ihave?: (RPC.IControlIHave[]|null); - - /** ControlMessage iwant */ - iwant?: (RPC.IControlIWant[]|null); - - /** ControlMessage graft */ - graft?: (RPC.IControlGraft[]|null); - - /** ControlMessage prune */ - prune?: (RPC.IControlPrune[]|null); - } - - /** Represents a ControlMessage. */ - class ControlMessage implements IControlMessage { - - /** - * Constructs a new ControlMessage. - * @param [properties] Properties to set - */ - constructor(properties?: RPC.IControlMessage); - - /** ControlMessage ihave. */ - public ihave: RPC.IControlIHave[]; - - /** ControlMessage iwant. */ - public iwant: RPC.IControlIWant[]; - - /** ControlMessage graft. */ - public graft: RPC.IControlGraft[]; - - /** ControlMessage prune. */ - public prune: RPC.IControlPrune[]; - - /** - * Creates a new ControlMessage instance using the specified properties. - * @param [properties] Properties to set - * @returns ControlMessage instance - */ - public static create(properties?: RPC.IControlMessage): RPC.ControlMessage; - - /** - * Encodes the specified ControlMessage message. Does not implicitly {@link RPC.ControlMessage.verify|verify} messages. - * @param message ControlMessage message or plain object to encode - * @param [writer] Writer to encode to - * @returns Writer - */ - public static encode(message: RPC.IControlMessage, writer?: $protobuf.Writer): $protobuf.Writer; - - /** - * Encodes the specified ControlMessage message, length delimited. Does not implicitly {@link RPC.ControlMessage.verify|verify} messages. - * @param message ControlMessage message or plain object to encode - * @param [writer] Writer to encode to - * @returns Writer - */ - public static encodeDelimited(message: RPC.IControlMessage, writer?: $protobuf.Writer): $protobuf.Writer; - - /** - * Decodes a ControlMessage message from the specified reader or buffer. - * @param reader Reader or buffer to decode from - * @param [length] Message length if known beforehand - * @returns ControlMessage - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): RPC.ControlMessage; - - /** - * Decodes a ControlMessage message from the specified reader or buffer, length delimited. - * @param reader Reader or buffer to decode from - * @returns ControlMessage - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): RPC.ControlMessage; - - /** - * Verifies a ControlMessage message. - * @param message Plain object to verify - * @returns `null` if valid, otherwise the reason why it is not - */ - public static verify(message: { [k: string]: any }): (string|null); - - /** - * Creates a ControlMessage message from a plain object. Also converts values to their respective internal types. - * @param object Plain object - * @returns ControlMessage - */ - public static fromObject(object: { [k: string]: any }): RPC.ControlMessage; - - /** - * Creates a plain object from a ControlMessage message. Also converts values to other types if specified. - * @param message ControlMessage - * @param [options] Conversion options - * @returns Plain object - */ - public static toObject(message: RPC.ControlMessage, options?: $protobuf.IConversionOptions): { [k: string]: any }; - - /** - * Converts this ControlMessage to JSON. - * @returns JSON object - */ - public toJSON(): { [k: string]: any }; - - /** - * Gets the default type url for ControlMessage - * @param [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") - * @returns The default type url - */ - public static getTypeUrl(typeUrlPrefix?: string): string; - } - - /** Properties of a ControlIHave. */ - interface IControlIHave { - - /** ControlIHave topicID */ - topicID?: (string|null); - - /** ControlIHave messageIDs */ - messageIDs?: (Uint8Array[]|null); - } - - /** Represents a ControlIHave. */ - class ControlIHave implements IControlIHave { - - /** - * Constructs a new ControlIHave. - * @param [properties] Properties to set - */ - constructor(properties?: RPC.IControlIHave); - - /** ControlIHave topicID. */ - public topicID?: (string|null); - - /** ControlIHave messageIDs. */ - public messageIDs: Uint8Array[]; - - /** ControlIHave _topicID. */ - public _topicID?: "topicID"; - - /** - * Creates a new ControlIHave instance using the specified properties. - * @param [properties] Properties to set - * @returns ControlIHave instance - */ - public static create(properties?: RPC.IControlIHave): RPC.ControlIHave; - - /** - * Encodes the specified ControlIHave message. Does not implicitly {@link RPC.ControlIHave.verify|verify} messages. - * @param message ControlIHave message or plain object to encode - * @param [writer] Writer to encode to - * @returns Writer - */ - public static encode(message: RPC.IControlIHave, writer?: $protobuf.Writer): $protobuf.Writer; - - /** - * Encodes the specified ControlIHave message, length delimited. Does not implicitly {@link RPC.ControlIHave.verify|verify} messages. - * @param message ControlIHave message or plain object to encode - * @param [writer] Writer to encode to - * @returns Writer - */ - public static encodeDelimited(message: RPC.IControlIHave, writer?: $protobuf.Writer): $protobuf.Writer; - - /** - * Decodes a ControlIHave message from the specified reader or buffer. - * @param reader Reader or buffer to decode from - * @param [length] Message length if known beforehand - * @returns ControlIHave - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): RPC.ControlIHave; - - /** - * Decodes a ControlIHave message from the specified reader or buffer, length delimited. - * @param reader Reader or buffer to decode from - * @returns ControlIHave - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): RPC.ControlIHave; - - /** - * Verifies a ControlIHave message. - * @param message Plain object to verify - * @returns `null` if valid, otherwise the reason why it is not - */ - public static verify(message: { [k: string]: any }): (string|null); - - /** - * Creates a ControlIHave message from a plain object. Also converts values to their respective internal types. - * @param object Plain object - * @returns ControlIHave - */ - public static fromObject(object: { [k: string]: any }): RPC.ControlIHave; - - /** - * Creates a plain object from a ControlIHave message. Also converts values to other types if specified. - * @param message ControlIHave - * @param [options] Conversion options - * @returns Plain object - */ - public static toObject(message: RPC.ControlIHave, options?: $protobuf.IConversionOptions): { [k: string]: any }; - - /** - * Converts this ControlIHave to JSON. - * @returns JSON object - */ - public toJSON(): { [k: string]: any }; - - /** - * Gets the default type url for ControlIHave - * @param [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") - * @returns The default type url - */ - public static getTypeUrl(typeUrlPrefix?: string): string; - } - - /** Properties of a ControlIWant. */ - interface IControlIWant { - - /** ControlIWant messageIDs */ - messageIDs?: (Uint8Array[]|null); - } - - /** Represents a ControlIWant. */ - class ControlIWant implements IControlIWant { - - /** - * Constructs a new ControlIWant. - * @param [properties] Properties to set - */ - constructor(properties?: RPC.IControlIWant); - - /** ControlIWant messageIDs. */ - public messageIDs: Uint8Array[]; - - /** - * Creates a new ControlIWant instance using the specified properties. - * @param [properties] Properties to set - * @returns ControlIWant instance - */ - public static create(properties?: RPC.IControlIWant): RPC.ControlIWant; - - /** - * Encodes the specified ControlIWant message. Does not implicitly {@link RPC.ControlIWant.verify|verify} messages. - * @param message ControlIWant message or plain object to encode - * @param [writer] Writer to encode to - * @returns Writer - */ - public static encode(message: RPC.IControlIWant, writer?: $protobuf.Writer): $protobuf.Writer; - - /** - * Encodes the specified ControlIWant message, length delimited. Does not implicitly {@link RPC.ControlIWant.verify|verify} messages. - * @param message ControlIWant message or plain object to encode - * @param [writer] Writer to encode to - * @returns Writer - */ - public static encodeDelimited(message: RPC.IControlIWant, writer?: $protobuf.Writer): $protobuf.Writer; - - /** - * Decodes a ControlIWant message from the specified reader or buffer. - * @param reader Reader or buffer to decode from - * @param [length] Message length if known beforehand - * @returns ControlIWant - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): RPC.ControlIWant; - - /** - * Decodes a ControlIWant message from the specified reader or buffer, length delimited. - * @param reader Reader or buffer to decode from - * @returns ControlIWant - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): RPC.ControlIWant; - - /** - * Verifies a ControlIWant message. - * @param message Plain object to verify - * @returns `null` if valid, otherwise the reason why it is not - */ - public static verify(message: { [k: string]: any }): (string|null); - - /** - * Creates a ControlIWant message from a plain object. Also converts values to their respective internal types. - * @param object Plain object - * @returns ControlIWant - */ - public static fromObject(object: { [k: string]: any }): RPC.ControlIWant; - - /** - * Creates a plain object from a ControlIWant message. Also converts values to other types if specified. - * @param message ControlIWant - * @param [options] Conversion options - * @returns Plain object - */ - public static toObject(message: RPC.ControlIWant, options?: $protobuf.IConversionOptions): { [k: string]: any }; - - /** - * Converts this ControlIWant to JSON. - * @returns JSON object - */ - public toJSON(): { [k: string]: any }; - - /** - * Gets the default type url for ControlIWant - * @param [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") - * @returns The default type url - */ - public static getTypeUrl(typeUrlPrefix?: string): string; - } - - /** Properties of a ControlGraft. */ - interface IControlGraft { - - /** ControlGraft topicID */ - topicID?: (string|null); - } - - /** Represents a ControlGraft. */ - class ControlGraft implements IControlGraft { - - /** - * Constructs a new ControlGraft. - * @param [properties] Properties to set - */ - constructor(properties?: RPC.IControlGraft); - - /** ControlGraft topicID. */ - public topicID?: (string|null); - - /** ControlGraft _topicID. */ - public _topicID?: "topicID"; - - /** - * Creates a new ControlGraft instance using the specified properties. - * @param [properties] Properties to set - * @returns ControlGraft instance - */ - public static create(properties?: RPC.IControlGraft): RPC.ControlGraft; - - /** - * Encodes the specified ControlGraft message. Does not implicitly {@link RPC.ControlGraft.verify|verify} messages. - * @param message ControlGraft message or plain object to encode - * @param [writer] Writer to encode to - * @returns Writer - */ - public static encode(message: RPC.IControlGraft, writer?: $protobuf.Writer): $protobuf.Writer; - - /** - * Encodes the specified ControlGraft message, length delimited. Does not implicitly {@link RPC.ControlGraft.verify|verify} messages. - * @param message ControlGraft message or plain object to encode - * @param [writer] Writer to encode to - * @returns Writer - */ - public static encodeDelimited(message: RPC.IControlGraft, writer?: $protobuf.Writer): $protobuf.Writer; - - /** - * Decodes a ControlGraft message from the specified reader or buffer. - * @param reader Reader or buffer to decode from - * @param [length] Message length if known beforehand - * @returns ControlGraft - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): RPC.ControlGraft; - - /** - * Decodes a ControlGraft message from the specified reader or buffer, length delimited. - * @param reader Reader or buffer to decode from - * @returns ControlGraft - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): RPC.ControlGraft; - - /** - * Verifies a ControlGraft message. - * @param message Plain object to verify - * @returns `null` if valid, otherwise the reason why it is not - */ - public static verify(message: { [k: string]: any }): (string|null); - - /** - * Creates a ControlGraft message from a plain object. Also converts values to their respective internal types. - * @param object Plain object - * @returns ControlGraft - */ - public static fromObject(object: { [k: string]: any }): RPC.ControlGraft; - - /** - * Creates a plain object from a ControlGraft message. Also converts values to other types if specified. - * @param message ControlGraft - * @param [options] Conversion options - * @returns Plain object - */ - public static toObject(message: RPC.ControlGraft, options?: $protobuf.IConversionOptions): { [k: string]: any }; - - /** - * Converts this ControlGraft to JSON. - * @returns JSON object - */ - public toJSON(): { [k: string]: any }; - - /** - * Gets the default type url for ControlGraft - * @param [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") - * @returns The default type url - */ - public static getTypeUrl(typeUrlPrefix?: string): string; - } - - /** Properties of a ControlPrune. */ - interface IControlPrune { - - /** ControlPrune topicID */ - topicID?: (string|null); - - /** ControlPrune peers */ - peers?: (RPC.IPeerInfo[]|null); - - /** ControlPrune backoff */ - backoff?: (number|Long|null); - } - - /** Represents a ControlPrune. */ - class ControlPrune implements IControlPrune { - - /** - * Constructs a new ControlPrune. - * @param [properties] Properties to set - */ - constructor(properties?: RPC.IControlPrune); - - /** ControlPrune topicID. */ - public topicID?: (string|null); - - /** ControlPrune peers. */ - public peers: RPC.IPeerInfo[]; - - /** ControlPrune backoff. */ - public backoff?: (number|Long|null); - - /** ControlPrune _topicID. */ - public _topicID?: "topicID"; - - /** ControlPrune _backoff. */ - public _backoff?: "backoff"; - - /** - * Creates a new ControlPrune instance using the specified properties. - * @param [properties] Properties to set - * @returns ControlPrune instance - */ - public static create(properties?: RPC.IControlPrune): RPC.ControlPrune; - - /** - * Encodes the specified ControlPrune message. Does not implicitly {@link RPC.ControlPrune.verify|verify} messages. - * @param message ControlPrune message or plain object to encode - * @param [writer] Writer to encode to - * @returns Writer - */ - public static encode(message: RPC.IControlPrune, writer?: $protobuf.Writer): $protobuf.Writer; - - /** - * Encodes the specified ControlPrune message, length delimited. Does not implicitly {@link RPC.ControlPrune.verify|verify} messages. - * @param message ControlPrune message or plain object to encode - * @param [writer] Writer to encode to - * @returns Writer - */ - public static encodeDelimited(message: RPC.IControlPrune, writer?: $protobuf.Writer): $protobuf.Writer; - - /** - * Decodes a ControlPrune message from the specified reader or buffer. - * @param reader Reader or buffer to decode from - * @param [length] Message length if known beforehand - * @returns ControlPrune - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): RPC.ControlPrune; - - /** - * Decodes a ControlPrune message from the specified reader or buffer, length delimited. - * @param reader Reader or buffer to decode from - * @returns ControlPrune - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): RPC.ControlPrune; - - /** - * Verifies a ControlPrune message. - * @param message Plain object to verify - * @returns `null` if valid, otherwise the reason why it is not - */ - public static verify(message: { [k: string]: any }): (string|null); - - /** - * Creates a ControlPrune message from a plain object. Also converts values to their respective internal types. - * @param object Plain object - * @returns ControlPrune - */ - public static fromObject(object: { [k: string]: any }): RPC.ControlPrune; - - /** - * Creates a plain object from a ControlPrune message. Also converts values to other types if specified. - * @param message ControlPrune - * @param [options] Conversion options - * @returns Plain object - */ - public static toObject(message: RPC.ControlPrune, options?: $protobuf.IConversionOptions): { [k: string]: any }; - - /** - * Converts this ControlPrune to JSON. - * @returns JSON object - */ - public toJSON(): { [k: string]: any }; - - /** - * Gets the default type url for ControlPrune - * @param [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") - * @returns The default type url - */ - public static getTypeUrl(typeUrlPrefix?: string): string; - } - - /** Properties of a PeerInfo. */ - interface IPeerInfo { - - /** PeerInfo peerID */ - peerID?: (Uint8Array|null); - - /** PeerInfo signedPeerRecord */ - signedPeerRecord?: (Uint8Array|null); - } - - /** Represents a PeerInfo. */ - class PeerInfo implements IPeerInfo { - - /** - * Constructs a new PeerInfo. - * @param [properties] Properties to set - */ - constructor(properties?: RPC.IPeerInfo); - - /** PeerInfo peerID. */ - public peerID?: (Uint8Array|null); - - /** PeerInfo signedPeerRecord. */ - public signedPeerRecord?: (Uint8Array|null); - - /** PeerInfo _peerID. */ - public _peerID?: "peerID"; - - /** PeerInfo _signedPeerRecord. */ - public _signedPeerRecord?: "signedPeerRecord"; - - /** - * Creates a new PeerInfo instance using the specified properties. - * @param [properties] Properties to set - * @returns PeerInfo instance - */ - public static create(properties?: RPC.IPeerInfo): RPC.PeerInfo; - - /** - * Encodes the specified PeerInfo message. Does not implicitly {@link RPC.PeerInfo.verify|verify} messages. - * @param message PeerInfo message or plain object to encode - * @param [writer] Writer to encode to - * @returns Writer - */ - public static encode(message: RPC.IPeerInfo, writer?: $protobuf.Writer): $protobuf.Writer; - - /** - * Encodes the specified PeerInfo message, length delimited. Does not implicitly {@link RPC.PeerInfo.verify|verify} messages. - * @param message PeerInfo message or plain object to encode - * @param [writer] Writer to encode to - * @returns Writer - */ - public static encodeDelimited(message: RPC.IPeerInfo, writer?: $protobuf.Writer): $protobuf.Writer; - - /** - * Decodes a PeerInfo message from the specified reader or buffer. - * @param reader Reader or buffer to decode from - * @param [length] Message length if known beforehand - * @returns PeerInfo - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): RPC.PeerInfo; - - /** - * Decodes a PeerInfo message from the specified reader or buffer, length delimited. - * @param reader Reader or buffer to decode from - * @returns PeerInfo - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): RPC.PeerInfo; - - /** - * Verifies a PeerInfo message. - * @param message Plain object to verify - * @returns `null` if valid, otherwise the reason why it is not - */ - public static verify(message: { [k: string]: any }): (string|null); - - /** - * Creates a PeerInfo message from a plain object. Also converts values to their respective internal types. - * @param object Plain object - * @returns PeerInfo - */ - public static fromObject(object: { [k: string]: any }): RPC.PeerInfo; - - /** - * Creates a plain object from a PeerInfo message. Also converts values to other types if specified. - * @param message PeerInfo - * @param [options] Conversion options - * @returns Plain object - */ - public static toObject(message: RPC.PeerInfo, options?: $protobuf.IConversionOptions): { [k: string]: any }; - - /** - * Converts this PeerInfo to JSON. - * @returns JSON object - */ - public toJSON(): { [k: string]: any }; - - /** - * Gets the default type url for PeerInfo - * @param [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") - * @returns The default type url - */ - public static getTypeUrl(typeUrlPrefix?: string): string; - } -} diff --git a/packages/protons-benchmark/src/implementations/protobufjs/rpc.js b/packages/protons-benchmark/src/implementations/protobufjs/rpc.js deleted file mode 100644 index 9f6c59a..0000000 --- a/packages/protons-benchmark/src/implementations/protobufjs/rpc.js +++ /dev/null @@ -1,2643 +0,0 @@ -/*eslint-disable*/ -// @ts-nocheck - -import $protobuf from "protobufjs/minimal.js"; - -// Common aliases -const $Reader = $protobuf.Reader, $Writer = $protobuf.Writer, $util = $protobuf.util; - -// Exported root namespace -const $root = $protobuf.roots["default"] || ($protobuf.roots["default"] = {}); - -export const RPC = $root.RPC = (() => { - - /** - * Properties of a RPC. - * @exports IRPC - * @interface IRPC - * @property {Array.|null} [subscriptions] RPC subscriptions - * @property {Array.|null} [messages] RPC messages - * @property {RPC.IControlMessage|null} [control] RPC control - */ - - /** - * Constructs a new RPC. - * @exports RPC - * @classdesc Represents a RPC. - * @implements IRPC - * @constructor - * @param {IRPC=} [properties] Properties to set - */ - function RPC(properties) { - this.subscriptions = []; - this.messages = []; - if (properties) - for (let keys = Object.keys(properties), i = 0; i < keys.length; ++i) - if (properties[keys[i]] != null) - this[keys[i]] = properties[keys[i]]; - } - - /** - * RPC subscriptions. - * @member {Array.} subscriptions - * @memberof RPC - * @instance - */ - RPC.prototype.subscriptions = $util.emptyArray; - - /** - * RPC messages. - * @member {Array.} messages - * @memberof RPC - * @instance - */ - RPC.prototype.messages = $util.emptyArray; - - /** - * RPC control. - * @member {RPC.IControlMessage|null|undefined} control - * @memberof RPC - * @instance - */ - RPC.prototype.control = null; - - // OneOf field names bound to virtual getters and setters - let $oneOfFields; - - /** - * RPC _control. - * @member {"control"|undefined} _control - * @memberof RPC - * @instance - */ - Object.defineProperty(RPC.prototype, "_control", { - get: $util.oneOfGetter($oneOfFields = ["control"]), - set: $util.oneOfSetter($oneOfFields) - }); - - /** - * Creates a new RPC instance using the specified properties. - * @function create - * @memberof RPC - * @static - * @param {IRPC=} [properties] Properties to set - * @returns {RPC} RPC instance - */ - RPC.create = function create(properties) { - return new RPC(properties); - }; - - /** - * Encodes the specified RPC message. Does not implicitly {@link RPC.verify|verify} messages. - * @function encode - * @memberof RPC - * @static - * @param {IRPC} message RPC message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - RPC.encode = function encode(message, writer) { - if (!writer) - writer = $Writer.create(); - if (message.subscriptions != null && message.subscriptions.length) - for (let i = 0; i < message.subscriptions.length; ++i) - $root.RPC.SubOpts.encode(message.subscriptions[i], writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim(); - if (message.messages != null && message.messages.length) - for (let i = 0; i < message.messages.length; ++i) - $root.RPC.Message.encode(message.messages[i], writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim(); - if (message.control != null && Object.hasOwnProperty.call(message, "control")) - $root.RPC.ControlMessage.encode(message.control, writer.uint32(/* id 3, wireType 2 =*/26).fork()).ldelim(); - return writer; - }; - - /** - * Encodes the specified RPC message, length delimited. Does not implicitly {@link RPC.verify|verify} messages. - * @function encodeDelimited - * @memberof RPC - * @static - * @param {IRPC} message RPC message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - RPC.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes a RPC message from the specified reader or buffer. - * @function decode - * @memberof RPC - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @param {number} [length] Message length if known beforehand - * @returns {RPC} RPC - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - RPC.decode = function decode(reader, length) { - if (!(reader instanceof $Reader)) - reader = $Reader.create(reader); - let end = length === undefined ? reader.len : reader.pos + length, message = new $root.RPC(); - while (reader.pos < end) { - let tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - if (!(message.subscriptions && message.subscriptions.length)) - message.subscriptions = []; - message.subscriptions.push($root.RPC.SubOpts.decode(reader, reader.uint32())); - break; - } - case 2: { - if (!(message.messages && message.messages.length)) - message.messages = []; - message.messages.push($root.RPC.Message.decode(reader, reader.uint32())); - break; - } - case 3: { - message.control = $root.RPC.ControlMessage.decode(reader, reader.uint32()); - break; - } - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }; - - /** - * Decodes a RPC message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof RPC - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {RPC} RPC - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - RPC.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies a RPC message. - * @function verify - * @memberof RPC - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - RPC.verify = function verify(message) { - if (typeof message !== "object" || message === null) - return "object expected"; - let properties = {}; - if (message.subscriptions != null && message.hasOwnProperty("subscriptions")) { - if (!Array.isArray(message.subscriptions)) - return "subscriptions: array expected"; - for (let i = 0; i < message.subscriptions.length; ++i) { - let error = $root.RPC.SubOpts.verify(message.subscriptions[i]); - if (error) - return "subscriptions." + error; - } - } - if (message.messages != null && message.hasOwnProperty("messages")) { - if (!Array.isArray(message.messages)) - return "messages: array expected"; - for (let i = 0; i < message.messages.length; ++i) { - let error = $root.RPC.Message.verify(message.messages[i]); - if (error) - return "messages." + error; - } - } - if (message.control != null && message.hasOwnProperty("control")) { - properties._control = 1; - { - let error = $root.RPC.ControlMessage.verify(message.control); - if (error) - return "control." + error; - } - } - return null; - }; - - /** - * Creates a RPC message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof RPC - * @static - * @param {Object.} object Plain object - * @returns {RPC} RPC - */ - RPC.fromObject = function fromObject(object) { - if (object instanceof $root.RPC) - return object; - let message = new $root.RPC(); - if (object.subscriptions) { - if (!Array.isArray(object.subscriptions)) - throw TypeError(".RPC.subscriptions: array expected"); - message.subscriptions = []; - for (let i = 0; i < object.subscriptions.length; ++i) { - if (typeof object.subscriptions[i] !== "object") - throw TypeError(".RPC.subscriptions: object expected"); - message.subscriptions[i] = $root.RPC.SubOpts.fromObject(object.subscriptions[i]); - } - } - if (object.messages) { - if (!Array.isArray(object.messages)) - throw TypeError(".RPC.messages: array expected"); - message.messages = []; - for (let i = 0; i < object.messages.length; ++i) { - if (typeof object.messages[i] !== "object") - throw TypeError(".RPC.messages: object expected"); - message.messages[i] = $root.RPC.Message.fromObject(object.messages[i]); - } - } - if (object.control != null) { - if (typeof object.control !== "object") - throw TypeError(".RPC.control: object expected"); - message.control = $root.RPC.ControlMessage.fromObject(object.control); - } - return message; - }; - - /** - * Creates a plain object from a RPC message. Also converts values to other types if specified. - * @function toObject - * @memberof RPC - * @static - * @param {RPC} message RPC - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - RPC.toObject = function toObject(message, options) { - if (!options) - options = {}; - let object = {}; - if (options.arrays || options.defaults) { - object.subscriptions = []; - object.messages = []; - } - if (message.subscriptions && message.subscriptions.length) { - object.subscriptions = []; - for (let j = 0; j < message.subscriptions.length; ++j) - object.subscriptions[j] = $root.RPC.SubOpts.toObject(message.subscriptions[j], options); - } - if (message.messages && message.messages.length) { - object.messages = []; - for (let j = 0; j < message.messages.length; ++j) - object.messages[j] = $root.RPC.Message.toObject(message.messages[j], options); - } - if (message.control != null && message.hasOwnProperty("control")) { - object.control = $root.RPC.ControlMessage.toObject(message.control, options); - if (options.oneofs) - object._control = "control"; - } - return object; - }; - - /** - * Converts this RPC to JSON. - * @function toJSON - * @memberof RPC - * @instance - * @returns {Object.} JSON object - */ - RPC.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - /** - * Gets the default type url for RPC - * @function getTypeUrl - * @memberof RPC - * @static - * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") - * @returns {string} The default type url - */ - RPC.getTypeUrl = function getTypeUrl(typeUrlPrefix) { - if (typeUrlPrefix === undefined) { - typeUrlPrefix = "type.googleapis.com"; - } - return typeUrlPrefix + "/RPC"; - }; - - RPC.SubOpts = (function() { - - /** - * Properties of a SubOpts. - * @memberof RPC - * @interface ISubOpts - * @property {boolean|null} [subscribe] SubOpts subscribe - * @property {string|null} [topic] SubOpts topic - */ - - /** - * Constructs a new SubOpts. - * @memberof RPC - * @classdesc Represents a SubOpts. - * @implements ISubOpts - * @constructor - * @param {RPC.ISubOpts=} [properties] Properties to set - */ - function SubOpts(properties) { - if (properties) - for (let keys = Object.keys(properties), i = 0; i < keys.length; ++i) - if (properties[keys[i]] != null) - this[keys[i]] = properties[keys[i]]; - } - - /** - * SubOpts subscribe. - * @member {boolean|null|undefined} subscribe - * @memberof RPC.SubOpts - * @instance - */ - SubOpts.prototype.subscribe = null; - - /** - * SubOpts topic. - * @member {string|null|undefined} topic - * @memberof RPC.SubOpts - * @instance - */ - SubOpts.prototype.topic = null; - - // OneOf field names bound to virtual getters and setters - let $oneOfFields; - - /** - * SubOpts _subscribe. - * @member {"subscribe"|undefined} _subscribe - * @memberof RPC.SubOpts - * @instance - */ - Object.defineProperty(SubOpts.prototype, "_subscribe", { - get: $util.oneOfGetter($oneOfFields = ["subscribe"]), - set: $util.oneOfSetter($oneOfFields) - }); - - /** - * SubOpts _topic. - * @member {"topic"|undefined} _topic - * @memberof RPC.SubOpts - * @instance - */ - Object.defineProperty(SubOpts.prototype, "_topic", { - get: $util.oneOfGetter($oneOfFields = ["topic"]), - set: $util.oneOfSetter($oneOfFields) - }); - - /** - * Creates a new SubOpts instance using the specified properties. - * @function create - * @memberof RPC.SubOpts - * @static - * @param {RPC.ISubOpts=} [properties] Properties to set - * @returns {RPC.SubOpts} SubOpts instance - */ - SubOpts.create = function create(properties) { - return new SubOpts(properties); - }; - - /** - * Encodes the specified SubOpts message. Does not implicitly {@link RPC.SubOpts.verify|verify} messages. - * @function encode - * @memberof RPC.SubOpts - * @static - * @param {RPC.ISubOpts} message SubOpts message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - SubOpts.encode = function encode(message, writer) { - if (!writer) - writer = $Writer.create(); - if (message.subscribe != null && Object.hasOwnProperty.call(message, "subscribe")) - writer.uint32(/* id 1, wireType 0 =*/8).bool(message.subscribe); - if (message.topic != null && Object.hasOwnProperty.call(message, "topic")) - writer.uint32(/* id 2, wireType 2 =*/18).string(message.topic); - return writer; - }; - - /** - * Encodes the specified SubOpts message, length delimited. Does not implicitly {@link RPC.SubOpts.verify|verify} messages. - * @function encodeDelimited - * @memberof RPC.SubOpts - * @static - * @param {RPC.ISubOpts} message SubOpts message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - SubOpts.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes a SubOpts message from the specified reader or buffer. - * @function decode - * @memberof RPC.SubOpts - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @param {number} [length] Message length if known beforehand - * @returns {RPC.SubOpts} SubOpts - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - SubOpts.decode = function decode(reader, length) { - if (!(reader instanceof $Reader)) - reader = $Reader.create(reader); - let end = length === undefined ? reader.len : reader.pos + length, message = new $root.RPC.SubOpts(); - while (reader.pos < end) { - let tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - message.subscribe = reader.bool(); - break; - } - case 2: { - message.topic = reader.string(); - break; - } - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }; - - /** - * Decodes a SubOpts message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof RPC.SubOpts - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {RPC.SubOpts} SubOpts - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - SubOpts.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies a SubOpts message. - * @function verify - * @memberof RPC.SubOpts - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - SubOpts.verify = function verify(message) { - if (typeof message !== "object" || message === null) - return "object expected"; - let properties = {}; - if (message.subscribe != null && message.hasOwnProperty("subscribe")) { - properties._subscribe = 1; - if (typeof message.subscribe !== "boolean") - return "subscribe: boolean expected"; - } - if (message.topic != null && message.hasOwnProperty("topic")) { - properties._topic = 1; - if (!$util.isString(message.topic)) - return "topic: string expected"; - } - return null; - }; - - /** - * Creates a SubOpts message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof RPC.SubOpts - * @static - * @param {Object.} object Plain object - * @returns {RPC.SubOpts} SubOpts - */ - SubOpts.fromObject = function fromObject(object) { - if (object instanceof $root.RPC.SubOpts) - return object; - let message = new $root.RPC.SubOpts(); - if (object.subscribe != null) - message.subscribe = Boolean(object.subscribe); - if (object.topic != null) - message.topic = String(object.topic); - return message; - }; - - /** - * Creates a plain object from a SubOpts message. Also converts values to other types if specified. - * @function toObject - * @memberof RPC.SubOpts - * @static - * @param {RPC.SubOpts} message SubOpts - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - SubOpts.toObject = function toObject(message, options) { - if (!options) - options = {}; - let object = {}; - if (message.subscribe != null && message.hasOwnProperty("subscribe")) { - object.subscribe = message.subscribe; - if (options.oneofs) - object._subscribe = "subscribe"; - } - if (message.topic != null && message.hasOwnProperty("topic")) { - object.topic = message.topic; - if (options.oneofs) - object._topic = "topic"; - } - return object; - }; - - /** - * Converts this SubOpts to JSON. - * @function toJSON - * @memberof RPC.SubOpts - * @instance - * @returns {Object.} JSON object - */ - SubOpts.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - /** - * Gets the default type url for SubOpts - * @function getTypeUrl - * @memberof RPC.SubOpts - * @static - * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") - * @returns {string} The default type url - */ - SubOpts.getTypeUrl = function getTypeUrl(typeUrlPrefix) { - if (typeUrlPrefix === undefined) { - typeUrlPrefix = "type.googleapis.com"; - } - return typeUrlPrefix + "/RPC.SubOpts"; - }; - - return SubOpts; - })(); - - RPC.Message = (function() { - - /** - * Properties of a Message. - * @memberof RPC - * @interface IMessage - * @property {Uint8Array|null} [from] Message from - * @property {Uint8Array|null} [data] Message data - * @property {Uint8Array|null} [seqno] Message seqno - * @property {string} topic Message topic - * @property {Uint8Array|null} [signature] Message signature - * @property {Uint8Array|null} [key] Message key - */ - - /** - * Constructs a new Message. - * @memberof RPC - * @classdesc Represents a Message. - * @implements IMessage - * @constructor - * @param {RPC.IMessage=} [properties] Properties to set - */ - function Message(properties) { - if (properties) - for (let keys = Object.keys(properties), i = 0; i < keys.length; ++i) - if (properties[keys[i]] != null) - this[keys[i]] = properties[keys[i]]; - } - - /** - * Message from. - * @member {Uint8Array|null|undefined} from - * @memberof RPC.Message - * @instance - */ - Message.prototype.from = null; - - /** - * Message data. - * @member {Uint8Array|null|undefined} data - * @memberof RPC.Message - * @instance - */ - Message.prototype.data = null; - - /** - * Message seqno. - * @member {Uint8Array|null|undefined} seqno - * @memberof RPC.Message - * @instance - */ - Message.prototype.seqno = null; - - /** - * Message topic. - * @member {string} topic - * @memberof RPC.Message - * @instance - */ - Message.prototype.topic = ""; - - /** - * Message signature. - * @member {Uint8Array|null|undefined} signature - * @memberof RPC.Message - * @instance - */ - Message.prototype.signature = null; - - /** - * Message key. - * @member {Uint8Array|null|undefined} key - * @memberof RPC.Message - * @instance - */ - Message.prototype.key = null; - - // OneOf field names bound to virtual getters and setters - let $oneOfFields; - - /** - * Message _from. - * @member {"from"|undefined} _from - * @memberof RPC.Message - * @instance - */ - Object.defineProperty(Message.prototype, "_from", { - get: $util.oneOfGetter($oneOfFields = ["from"]), - set: $util.oneOfSetter($oneOfFields) - }); - - /** - * Message _data. - * @member {"data"|undefined} _data - * @memberof RPC.Message - * @instance - */ - Object.defineProperty(Message.prototype, "_data", { - get: $util.oneOfGetter($oneOfFields = ["data"]), - set: $util.oneOfSetter($oneOfFields) - }); - - /** - * Message _seqno. - * @member {"seqno"|undefined} _seqno - * @memberof RPC.Message - * @instance - */ - Object.defineProperty(Message.prototype, "_seqno", { - get: $util.oneOfGetter($oneOfFields = ["seqno"]), - set: $util.oneOfSetter($oneOfFields) - }); - - /** - * Message _signature. - * @member {"signature"|undefined} _signature - * @memberof RPC.Message - * @instance - */ - Object.defineProperty(Message.prototype, "_signature", { - get: $util.oneOfGetter($oneOfFields = ["signature"]), - set: $util.oneOfSetter($oneOfFields) - }); - - /** - * Message _key. - * @member {"key"|undefined} _key - * @memberof RPC.Message - * @instance - */ - Object.defineProperty(Message.prototype, "_key", { - get: $util.oneOfGetter($oneOfFields = ["key"]), - set: $util.oneOfSetter($oneOfFields) - }); - - /** - * Creates a new Message instance using the specified properties. - * @function create - * @memberof RPC.Message - * @static - * @param {RPC.IMessage=} [properties] Properties to set - * @returns {RPC.Message} Message instance - */ - Message.create = function create(properties) { - return new Message(properties); - }; - - /** - * Encodes the specified Message message. Does not implicitly {@link RPC.Message.verify|verify} messages. - * @function encode - * @memberof RPC.Message - * @static - * @param {RPC.IMessage} message Message message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - Message.encode = function encode(message, writer) { - if (!writer) - writer = $Writer.create(); - if (message.from != null && Object.hasOwnProperty.call(message, "from")) - writer.uint32(/* id 1, wireType 2 =*/10).bytes(message.from); - if (message.data != null && Object.hasOwnProperty.call(message, "data")) - writer.uint32(/* id 2, wireType 2 =*/18).bytes(message.data); - if (message.seqno != null && Object.hasOwnProperty.call(message, "seqno")) - writer.uint32(/* id 3, wireType 2 =*/26).bytes(message.seqno); - writer.uint32(/* id 4, wireType 2 =*/34).string(message.topic); - if (message.signature != null && Object.hasOwnProperty.call(message, "signature")) - writer.uint32(/* id 5, wireType 2 =*/42).bytes(message.signature); - if (message.key != null && Object.hasOwnProperty.call(message, "key")) - writer.uint32(/* id 6, wireType 2 =*/50).bytes(message.key); - return writer; - }; - - /** - * Encodes the specified Message message, length delimited. Does not implicitly {@link RPC.Message.verify|verify} messages. - * @function encodeDelimited - * @memberof RPC.Message - * @static - * @param {RPC.IMessage} message Message message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - Message.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes a Message message from the specified reader or buffer. - * @function decode - * @memberof RPC.Message - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @param {number} [length] Message length if known beforehand - * @returns {RPC.Message} Message - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - Message.decode = function decode(reader, length) { - if (!(reader instanceof $Reader)) - reader = $Reader.create(reader); - let end = length === undefined ? reader.len : reader.pos + length, message = new $root.RPC.Message(); - while (reader.pos < end) { - let tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - message.from = reader.bytes(); - break; - } - case 2: { - message.data = reader.bytes(); - break; - } - case 3: { - message.seqno = reader.bytes(); - break; - } - case 4: { - message.topic = reader.string(); - break; - } - case 5: { - message.signature = reader.bytes(); - break; - } - case 6: { - message.key = reader.bytes(); - break; - } - default: - reader.skipType(tag & 7); - break; - } - } - if (!message.hasOwnProperty("topic")) - throw $util.ProtocolError("missing required 'topic'", { instance: message }); - return message; - }; - - /** - * Decodes a Message message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof RPC.Message - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {RPC.Message} Message - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - Message.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies a Message message. - * @function verify - * @memberof RPC.Message - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - Message.verify = function verify(message) { - if (typeof message !== "object" || message === null) - return "object expected"; - let properties = {}; - if (message.from != null && message.hasOwnProperty("from")) { - properties._from = 1; - if (!(message.from && typeof message.from.length === "number" || $util.isString(message.from))) - return "from: buffer expected"; - } - if (message.data != null && message.hasOwnProperty("data")) { - properties._data = 1; - if (!(message.data && typeof message.data.length === "number" || $util.isString(message.data))) - return "data: buffer expected"; - } - if (message.seqno != null && message.hasOwnProperty("seqno")) { - properties._seqno = 1; - if (!(message.seqno && typeof message.seqno.length === "number" || $util.isString(message.seqno))) - return "seqno: buffer expected"; - } - if (!$util.isString(message.topic)) - return "topic: string expected"; - if (message.signature != null && message.hasOwnProperty("signature")) { - properties._signature = 1; - if (!(message.signature && typeof message.signature.length === "number" || $util.isString(message.signature))) - return "signature: buffer expected"; - } - if (message.key != null && message.hasOwnProperty("key")) { - properties._key = 1; - if (!(message.key && typeof message.key.length === "number" || $util.isString(message.key))) - return "key: buffer expected"; - } - return null; - }; - - /** - * Creates a Message message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof RPC.Message - * @static - * @param {Object.} object Plain object - * @returns {RPC.Message} Message - */ - Message.fromObject = function fromObject(object) { - if (object instanceof $root.RPC.Message) - return object; - let message = new $root.RPC.Message(); - if (object.from != null) - if (typeof object.from === "string") - $util.base64.decode(object.from, message.from = $util.newBuffer($util.base64.length(object.from)), 0); - else if (object.from.length >= 0) - message.from = object.from; - if (object.data != null) - if (typeof object.data === "string") - $util.base64.decode(object.data, message.data = $util.newBuffer($util.base64.length(object.data)), 0); - else if (object.data.length >= 0) - message.data = object.data; - if (object.seqno != null) - if (typeof object.seqno === "string") - $util.base64.decode(object.seqno, message.seqno = $util.newBuffer($util.base64.length(object.seqno)), 0); - else if (object.seqno.length >= 0) - message.seqno = object.seqno; - if (object.topic != null) - message.topic = String(object.topic); - if (object.signature != null) - if (typeof object.signature === "string") - $util.base64.decode(object.signature, message.signature = $util.newBuffer($util.base64.length(object.signature)), 0); - else if (object.signature.length >= 0) - message.signature = object.signature; - if (object.key != null) - if (typeof object.key === "string") - $util.base64.decode(object.key, message.key = $util.newBuffer($util.base64.length(object.key)), 0); - else if (object.key.length >= 0) - message.key = object.key; - return message; - }; - - /** - * Creates a plain object from a Message message. Also converts values to other types if specified. - * @function toObject - * @memberof RPC.Message - * @static - * @param {RPC.Message} message Message - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - Message.toObject = function toObject(message, options) { - if (!options) - options = {}; - let object = {}; - if (options.defaults) - object.topic = ""; - if (message.from != null && message.hasOwnProperty("from")) { - object.from = options.bytes === String ? $util.base64.encode(message.from, 0, message.from.length) : options.bytes === Array ? Array.prototype.slice.call(message.from) : message.from; - if (options.oneofs) - object._from = "from"; - } - if (message.data != null && message.hasOwnProperty("data")) { - object.data = options.bytes === String ? $util.base64.encode(message.data, 0, message.data.length) : options.bytes === Array ? Array.prototype.slice.call(message.data) : message.data; - if (options.oneofs) - object._data = "data"; - } - if (message.seqno != null && message.hasOwnProperty("seqno")) { - object.seqno = options.bytes === String ? $util.base64.encode(message.seqno, 0, message.seqno.length) : options.bytes === Array ? Array.prototype.slice.call(message.seqno) : message.seqno; - if (options.oneofs) - object._seqno = "seqno"; - } - if (message.topic != null && message.hasOwnProperty("topic")) - object.topic = message.topic; - if (message.signature != null && message.hasOwnProperty("signature")) { - object.signature = options.bytes === String ? $util.base64.encode(message.signature, 0, message.signature.length) : options.bytes === Array ? Array.prototype.slice.call(message.signature) : message.signature; - if (options.oneofs) - object._signature = "signature"; - } - if (message.key != null && message.hasOwnProperty("key")) { - object.key = options.bytes === String ? $util.base64.encode(message.key, 0, message.key.length) : options.bytes === Array ? Array.prototype.slice.call(message.key) : message.key; - if (options.oneofs) - object._key = "key"; - } - return object; - }; - - /** - * Converts this Message to JSON. - * @function toJSON - * @memberof RPC.Message - * @instance - * @returns {Object.} JSON object - */ - Message.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - /** - * Gets the default type url for Message - * @function getTypeUrl - * @memberof RPC.Message - * @static - * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") - * @returns {string} The default type url - */ - Message.getTypeUrl = function getTypeUrl(typeUrlPrefix) { - if (typeUrlPrefix === undefined) { - typeUrlPrefix = "type.googleapis.com"; - } - return typeUrlPrefix + "/RPC.Message"; - }; - - return Message; - })(); - - RPC.ControlMessage = (function() { - - /** - * Properties of a ControlMessage. - * @memberof RPC - * @interface IControlMessage - * @property {Array.|null} [ihave] ControlMessage ihave - * @property {Array.|null} [iwant] ControlMessage iwant - * @property {Array.|null} [graft] ControlMessage graft - * @property {Array.|null} [prune] ControlMessage prune - */ - - /** - * Constructs a new ControlMessage. - * @memberof RPC - * @classdesc Represents a ControlMessage. - * @implements IControlMessage - * @constructor - * @param {RPC.IControlMessage=} [properties] Properties to set - */ - function ControlMessage(properties) { - this.ihave = []; - this.iwant = []; - this.graft = []; - this.prune = []; - if (properties) - for (let keys = Object.keys(properties), i = 0; i < keys.length; ++i) - if (properties[keys[i]] != null) - this[keys[i]] = properties[keys[i]]; - } - - /** - * ControlMessage ihave. - * @member {Array.} ihave - * @memberof RPC.ControlMessage - * @instance - */ - ControlMessage.prototype.ihave = $util.emptyArray; - - /** - * ControlMessage iwant. - * @member {Array.} iwant - * @memberof RPC.ControlMessage - * @instance - */ - ControlMessage.prototype.iwant = $util.emptyArray; - - /** - * ControlMessage graft. - * @member {Array.} graft - * @memberof RPC.ControlMessage - * @instance - */ - ControlMessage.prototype.graft = $util.emptyArray; - - /** - * ControlMessage prune. - * @member {Array.} prune - * @memberof RPC.ControlMessage - * @instance - */ - ControlMessage.prototype.prune = $util.emptyArray; - - /** - * Creates a new ControlMessage instance using the specified properties. - * @function create - * @memberof RPC.ControlMessage - * @static - * @param {RPC.IControlMessage=} [properties] Properties to set - * @returns {RPC.ControlMessage} ControlMessage instance - */ - ControlMessage.create = function create(properties) { - return new ControlMessage(properties); - }; - - /** - * Encodes the specified ControlMessage message. Does not implicitly {@link RPC.ControlMessage.verify|verify} messages. - * @function encode - * @memberof RPC.ControlMessage - * @static - * @param {RPC.IControlMessage} message ControlMessage message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - ControlMessage.encode = function encode(message, writer) { - if (!writer) - writer = $Writer.create(); - if (message.ihave != null && message.ihave.length) - for (let i = 0; i < message.ihave.length; ++i) - $root.RPC.ControlIHave.encode(message.ihave[i], writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim(); - if (message.iwant != null && message.iwant.length) - for (let i = 0; i < message.iwant.length; ++i) - $root.RPC.ControlIWant.encode(message.iwant[i], writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim(); - if (message.graft != null && message.graft.length) - for (let i = 0; i < message.graft.length; ++i) - $root.RPC.ControlGraft.encode(message.graft[i], writer.uint32(/* id 3, wireType 2 =*/26).fork()).ldelim(); - if (message.prune != null && message.prune.length) - for (let i = 0; i < message.prune.length; ++i) - $root.RPC.ControlPrune.encode(message.prune[i], writer.uint32(/* id 4, wireType 2 =*/34).fork()).ldelim(); - return writer; - }; - - /** - * Encodes the specified ControlMessage message, length delimited. Does not implicitly {@link RPC.ControlMessage.verify|verify} messages. - * @function encodeDelimited - * @memberof RPC.ControlMessage - * @static - * @param {RPC.IControlMessage} message ControlMessage message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - ControlMessage.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes a ControlMessage message from the specified reader or buffer. - * @function decode - * @memberof RPC.ControlMessage - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @param {number} [length] Message length if known beforehand - * @returns {RPC.ControlMessage} ControlMessage - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - ControlMessage.decode = function decode(reader, length) { - if (!(reader instanceof $Reader)) - reader = $Reader.create(reader); - let end = length === undefined ? reader.len : reader.pos + length, message = new $root.RPC.ControlMessage(); - while (reader.pos < end) { - let tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - if (!(message.ihave && message.ihave.length)) - message.ihave = []; - message.ihave.push($root.RPC.ControlIHave.decode(reader, reader.uint32())); - break; - } - case 2: { - if (!(message.iwant && message.iwant.length)) - message.iwant = []; - message.iwant.push($root.RPC.ControlIWant.decode(reader, reader.uint32())); - break; - } - case 3: { - if (!(message.graft && message.graft.length)) - message.graft = []; - message.graft.push($root.RPC.ControlGraft.decode(reader, reader.uint32())); - break; - } - case 4: { - if (!(message.prune && message.prune.length)) - message.prune = []; - message.prune.push($root.RPC.ControlPrune.decode(reader, reader.uint32())); - break; - } - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }; - - /** - * Decodes a ControlMessage message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof RPC.ControlMessage - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {RPC.ControlMessage} ControlMessage - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - ControlMessage.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies a ControlMessage message. - * @function verify - * @memberof RPC.ControlMessage - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - ControlMessage.verify = function verify(message) { - if (typeof message !== "object" || message === null) - return "object expected"; - if (message.ihave != null && message.hasOwnProperty("ihave")) { - if (!Array.isArray(message.ihave)) - return "ihave: array expected"; - for (let i = 0; i < message.ihave.length; ++i) { - let error = $root.RPC.ControlIHave.verify(message.ihave[i]); - if (error) - return "ihave." + error; - } - } - if (message.iwant != null && message.hasOwnProperty("iwant")) { - if (!Array.isArray(message.iwant)) - return "iwant: array expected"; - for (let i = 0; i < message.iwant.length; ++i) { - let error = $root.RPC.ControlIWant.verify(message.iwant[i]); - if (error) - return "iwant." + error; - } - } - if (message.graft != null && message.hasOwnProperty("graft")) { - if (!Array.isArray(message.graft)) - return "graft: array expected"; - for (let i = 0; i < message.graft.length; ++i) { - let error = $root.RPC.ControlGraft.verify(message.graft[i]); - if (error) - return "graft." + error; - } - } - if (message.prune != null && message.hasOwnProperty("prune")) { - if (!Array.isArray(message.prune)) - return "prune: array expected"; - for (let i = 0; i < message.prune.length; ++i) { - let error = $root.RPC.ControlPrune.verify(message.prune[i]); - if (error) - return "prune." + error; - } - } - return null; - }; - - /** - * Creates a ControlMessage message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof RPC.ControlMessage - * @static - * @param {Object.} object Plain object - * @returns {RPC.ControlMessage} ControlMessage - */ - ControlMessage.fromObject = function fromObject(object) { - if (object instanceof $root.RPC.ControlMessage) - return object; - let message = new $root.RPC.ControlMessage(); - if (object.ihave) { - if (!Array.isArray(object.ihave)) - throw TypeError(".RPC.ControlMessage.ihave: array expected"); - message.ihave = []; - for (let i = 0; i < object.ihave.length; ++i) { - if (typeof object.ihave[i] !== "object") - throw TypeError(".RPC.ControlMessage.ihave: object expected"); - message.ihave[i] = $root.RPC.ControlIHave.fromObject(object.ihave[i]); - } - } - if (object.iwant) { - if (!Array.isArray(object.iwant)) - throw TypeError(".RPC.ControlMessage.iwant: array expected"); - message.iwant = []; - for (let i = 0; i < object.iwant.length; ++i) { - if (typeof object.iwant[i] !== "object") - throw TypeError(".RPC.ControlMessage.iwant: object expected"); - message.iwant[i] = $root.RPC.ControlIWant.fromObject(object.iwant[i]); - } - } - if (object.graft) { - if (!Array.isArray(object.graft)) - throw TypeError(".RPC.ControlMessage.graft: array expected"); - message.graft = []; - for (let i = 0; i < object.graft.length; ++i) { - if (typeof object.graft[i] !== "object") - throw TypeError(".RPC.ControlMessage.graft: object expected"); - message.graft[i] = $root.RPC.ControlGraft.fromObject(object.graft[i]); - } - } - if (object.prune) { - if (!Array.isArray(object.prune)) - throw TypeError(".RPC.ControlMessage.prune: array expected"); - message.prune = []; - for (let i = 0; i < object.prune.length; ++i) { - if (typeof object.prune[i] !== "object") - throw TypeError(".RPC.ControlMessage.prune: object expected"); - message.prune[i] = $root.RPC.ControlPrune.fromObject(object.prune[i]); - } - } - return message; - }; - - /** - * Creates a plain object from a ControlMessage message. Also converts values to other types if specified. - * @function toObject - * @memberof RPC.ControlMessage - * @static - * @param {RPC.ControlMessage} message ControlMessage - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - ControlMessage.toObject = function toObject(message, options) { - if (!options) - options = {}; - let object = {}; - if (options.arrays || options.defaults) { - object.ihave = []; - object.iwant = []; - object.graft = []; - object.prune = []; - } - if (message.ihave && message.ihave.length) { - object.ihave = []; - for (let j = 0; j < message.ihave.length; ++j) - object.ihave[j] = $root.RPC.ControlIHave.toObject(message.ihave[j], options); - } - if (message.iwant && message.iwant.length) { - object.iwant = []; - for (let j = 0; j < message.iwant.length; ++j) - object.iwant[j] = $root.RPC.ControlIWant.toObject(message.iwant[j], options); - } - if (message.graft && message.graft.length) { - object.graft = []; - for (let j = 0; j < message.graft.length; ++j) - object.graft[j] = $root.RPC.ControlGraft.toObject(message.graft[j], options); - } - if (message.prune && message.prune.length) { - object.prune = []; - for (let j = 0; j < message.prune.length; ++j) - object.prune[j] = $root.RPC.ControlPrune.toObject(message.prune[j], options); - } - return object; - }; - - /** - * Converts this ControlMessage to JSON. - * @function toJSON - * @memberof RPC.ControlMessage - * @instance - * @returns {Object.} JSON object - */ - ControlMessage.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - /** - * Gets the default type url for ControlMessage - * @function getTypeUrl - * @memberof RPC.ControlMessage - * @static - * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") - * @returns {string} The default type url - */ - ControlMessage.getTypeUrl = function getTypeUrl(typeUrlPrefix) { - if (typeUrlPrefix === undefined) { - typeUrlPrefix = "type.googleapis.com"; - } - return typeUrlPrefix + "/RPC.ControlMessage"; - }; - - return ControlMessage; - })(); - - RPC.ControlIHave = (function() { - - /** - * Properties of a ControlIHave. - * @memberof RPC - * @interface IControlIHave - * @property {string|null} [topicID] ControlIHave topicID - * @property {Array.|null} [messageIDs] ControlIHave messageIDs - */ - - /** - * Constructs a new ControlIHave. - * @memberof RPC - * @classdesc Represents a ControlIHave. - * @implements IControlIHave - * @constructor - * @param {RPC.IControlIHave=} [properties] Properties to set - */ - function ControlIHave(properties) { - this.messageIDs = []; - if (properties) - for (let keys = Object.keys(properties), i = 0; i < keys.length; ++i) - if (properties[keys[i]] != null) - this[keys[i]] = properties[keys[i]]; - } - - /** - * ControlIHave topicID. - * @member {string|null|undefined} topicID - * @memberof RPC.ControlIHave - * @instance - */ - ControlIHave.prototype.topicID = null; - - /** - * ControlIHave messageIDs. - * @member {Array.} messageIDs - * @memberof RPC.ControlIHave - * @instance - */ - ControlIHave.prototype.messageIDs = $util.emptyArray; - - // OneOf field names bound to virtual getters and setters - let $oneOfFields; - - /** - * ControlIHave _topicID. - * @member {"topicID"|undefined} _topicID - * @memberof RPC.ControlIHave - * @instance - */ - Object.defineProperty(ControlIHave.prototype, "_topicID", { - get: $util.oneOfGetter($oneOfFields = ["topicID"]), - set: $util.oneOfSetter($oneOfFields) - }); - - /** - * Creates a new ControlIHave instance using the specified properties. - * @function create - * @memberof RPC.ControlIHave - * @static - * @param {RPC.IControlIHave=} [properties] Properties to set - * @returns {RPC.ControlIHave} ControlIHave instance - */ - ControlIHave.create = function create(properties) { - return new ControlIHave(properties); - }; - - /** - * Encodes the specified ControlIHave message. Does not implicitly {@link RPC.ControlIHave.verify|verify} messages. - * @function encode - * @memberof RPC.ControlIHave - * @static - * @param {RPC.IControlIHave} message ControlIHave message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - ControlIHave.encode = function encode(message, writer) { - if (!writer) - writer = $Writer.create(); - if (message.topicID != null && Object.hasOwnProperty.call(message, "topicID")) - writer.uint32(/* id 1, wireType 2 =*/10).string(message.topicID); - if (message.messageIDs != null && message.messageIDs.length) - for (let i = 0; i < message.messageIDs.length; ++i) - writer.uint32(/* id 2, wireType 2 =*/18).bytes(message.messageIDs[i]); - return writer; - }; - - /** - * Encodes the specified ControlIHave message, length delimited. Does not implicitly {@link RPC.ControlIHave.verify|verify} messages. - * @function encodeDelimited - * @memberof RPC.ControlIHave - * @static - * @param {RPC.IControlIHave} message ControlIHave message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - ControlIHave.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes a ControlIHave message from the specified reader or buffer. - * @function decode - * @memberof RPC.ControlIHave - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @param {number} [length] Message length if known beforehand - * @returns {RPC.ControlIHave} ControlIHave - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - ControlIHave.decode = function decode(reader, length) { - if (!(reader instanceof $Reader)) - reader = $Reader.create(reader); - let end = length === undefined ? reader.len : reader.pos + length, message = new $root.RPC.ControlIHave(); - while (reader.pos < end) { - let tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - message.topicID = reader.string(); - break; - } - case 2: { - if (!(message.messageIDs && message.messageIDs.length)) - message.messageIDs = []; - message.messageIDs.push(reader.bytes()); - break; - } - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }; - - /** - * Decodes a ControlIHave message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof RPC.ControlIHave - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {RPC.ControlIHave} ControlIHave - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - ControlIHave.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies a ControlIHave message. - * @function verify - * @memberof RPC.ControlIHave - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - ControlIHave.verify = function verify(message) { - if (typeof message !== "object" || message === null) - return "object expected"; - let properties = {}; - if (message.topicID != null && message.hasOwnProperty("topicID")) { - properties._topicID = 1; - if (!$util.isString(message.topicID)) - return "topicID: string expected"; - } - if (message.messageIDs != null && message.hasOwnProperty("messageIDs")) { - if (!Array.isArray(message.messageIDs)) - return "messageIDs: array expected"; - for (let i = 0; i < message.messageIDs.length; ++i) - if (!(message.messageIDs[i] && typeof message.messageIDs[i].length === "number" || $util.isString(message.messageIDs[i]))) - return "messageIDs: buffer[] expected"; - } - return null; - }; - - /** - * Creates a ControlIHave message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof RPC.ControlIHave - * @static - * @param {Object.} object Plain object - * @returns {RPC.ControlIHave} ControlIHave - */ - ControlIHave.fromObject = function fromObject(object) { - if (object instanceof $root.RPC.ControlIHave) - return object; - let message = new $root.RPC.ControlIHave(); - if (object.topicID != null) - message.topicID = String(object.topicID); - if (object.messageIDs) { - if (!Array.isArray(object.messageIDs)) - throw TypeError(".RPC.ControlIHave.messageIDs: array expected"); - message.messageIDs = []; - for (let i = 0; i < object.messageIDs.length; ++i) - if (typeof object.messageIDs[i] === "string") - $util.base64.decode(object.messageIDs[i], message.messageIDs[i] = $util.newBuffer($util.base64.length(object.messageIDs[i])), 0); - else if (object.messageIDs[i].length >= 0) - message.messageIDs[i] = object.messageIDs[i]; - } - return message; - }; - - /** - * Creates a plain object from a ControlIHave message. Also converts values to other types if specified. - * @function toObject - * @memberof RPC.ControlIHave - * @static - * @param {RPC.ControlIHave} message ControlIHave - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - ControlIHave.toObject = function toObject(message, options) { - if (!options) - options = {}; - let object = {}; - if (options.arrays || options.defaults) - object.messageIDs = []; - if (message.topicID != null && message.hasOwnProperty("topicID")) { - object.topicID = message.topicID; - if (options.oneofs) - object._topicID = "topicID"; - } - if (message.messageIDs && message.messageIDs.length) { - object.messageIDs = []; - for (let j = 0; j < message.messageIDs.length; ++j) - object.messageIDs[j] = options.bytes === String ? $util.base64.encode(message.messageIDs[j], 0, message.messageIDs[j].length) : options.bytes === Array ? Array.prototype.slice.call(message.messageIDs[j]) : message.messageIDs[j]; - } - return object; - }; - - /** - * Converts this ControlIHave to JSON. - * @function toJSON - * @memberof RPC.ControlIHave - * @instance - * @returns {Object.} JSON object - */ - ControlIHave.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - /** - * Gets the default type url for ControlIHave - * @function getTypeUrl - * @memberof RPC.ControlIHave - * @static - * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") - * @returns {string} The default type url - */ - ControlIHave.getTypeUrl = function getTypeUrl(typeUrlPrefix) { - if (typeUrlPrefix === undefined) { - typeUrlPrefix = "type.googleapis.com"; - } - return typeUrlPrefix + "/RPC.ControlIHave"; - }; - - return ControlIHave; - })(); - - RPC.ControlIWant = (function() { - - /** - * Properties of a ControlIWant. - * @memberof RPC - * @interface IControlIWant - * @property {Array.|null} [messageIDs] ControlIWant messageIDs - */ - - /** - * Constructs a new ControlIWant. - * @memberof RPC - * @classdesc Represents a ControlIWant. - * @implements IControlIWant - * @constructor - * @param {RPC.IControlIWant=} [properties] Properties to set - */ - function ControlIWant(properties) { - this.messageIDs = []; - if (properties) - for (let keys = Object.keys(properties), i = 0; i < keys.length; ++i) - if (properties[keys[i]] != null) - this[keys[i]] = properties[keys[i]]; - } - - /** - * ControlIWant messageIDs. - * @member {Array.} messageIDs - * @memberof RPC.ControlIWant - * @instance - */ - ControlIWant.prototype.messageIDs = $util.emptyArray; - - /** - * Creates a new ControlIWant instance using the specified properties. - * @function create - * @memberof RPC.ControlIWant - * @static - * @param {RPC.IControlIWant=} [properties] Properties to set - * @returns {RPC.ControlIWant} ControlIWant instance - */ - ControlIWant.create = function create(properties) { - return new ControlIWant(properties); - }; - - /** - * Encodes the specified ControlIWant message. Does not implicitly {@link RPC.ControlIWant.verify|verify} messages. - * @function encode - * @memberof RPC.ControlIWant - * @static - * @param {RPC.IControlIWant} message ControlIWant message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - ControlIWant.encode = function encode(message, writer) { - if (!writer) - writer = $Writer.create(); - if (message.messageIDs != null && message.messageIDs.length) - for (let i = 0; i < message.messageIDs.length; ++i) - writer.uint32(/* id 1, wireType 2 =*/10).bytes(message.messageIDs[i]); - return writer; - }; - - /** - * Encodes the specified ControlIWant message, length delimited. Does not implicitly {@link RPC.ControlIWant.verify|verify} messages. - * @function encodeDelimited - * @memberof RPC.ControlIWant - * @static - * @param {RPC.IControlIWant} message ControlIWant message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - ControlIWant.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes a ControlIWant message from the specified reader or buffer. - * @function decode - * @memberof RPC.ControlIWant - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @param {number} [length] Message length if known beforehand - * @returns {RPC.ControlIWant} ControlIWant - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - ControlIWant.decode = function decode(reader, length) { - if (!(reader instanceof $Reader)) - reader = $Reader.create(reader); - let end = length === undefined ? reader.len : reader.pos + length, message = new $root.RPC.ControlIWant(); - while (reader.pos < end) { - let tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - if (!(message.messageIDs && message.messageIDs.length)) - message.messageIDs = []; - message.messageIDs.push(reader.bytes()); - break; - } - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }; - - /** - * Decodes a ControlIWant message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof RPC.ControlIWant - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {RPC.ControlIWant} ControlIWant - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - ControlIWant.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies a ControlIWant message. - * @function verify - * @memberof RPC.ControlIWant - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - ControlIWant.verify = function verify(message) { - if (typeof message !== "object" || message === null) - return "object expected"; - if (message.messageIDs != null && message.hasOwnProperty("messageIDs")) { - if (!Array.isArray(message.messageIDs)) - return "messageIDs: array expected"; - for (let i = 0; i < message.messageIDs.length; ++i) - if (!(message.messageIDs[i] && typeof message.messageIDs[i].length === "number" || $util.isString(message.messageIDs[i]))) - return "messageIDs: buffer[] expected"; - } - return null; - }; - - /** - * Creates a ControlIWant message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof RPC.ControlIWant - * @static - * @param {Object.} object Plain object - * @returns {RPC.ControlIWant} ControlIWant - */ - ControlIWant.fromObject = function fromObject(object) { - if (object instanceof $root.RPC.ControlIWant) - return object; - let message = new $root.RPC.ControlIWant(); - if (object.messageIDs) { - if (!Array.isArray(object.messageIDs)) - throw TypeError(".RPC.ControlIWant.messageIDs: array expected"); - message.messageIDs = []; - for (let i = 0; i < object.messageIDs.length; ++i) - if (typeof object.messageIDs[i] === "string") - $util.base64.decode(object.messageIDs[i], message.messageIDs[i] = $util.newBuffer($util.base64.length(object.messageIDs[i])), 0); - else if (object.messageIDs[i].length >= 0) - message.messageIDs[i] = object.messageIDs[i]; - } - return message; - }; - - /** - * Creates a plain object from a ControlIWant message. Also converts values to other types if specified. - * @function toObject - * @memberof RPC.ControlIWant - * @static - * @param {RPC.ControlIWant} message ControlIWant - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - ControlIWant.toObject = function toObject(message, options) { - if (!options) - options = {}; - let object = {}; - if (options.arrays || options.defaults) - object.messageIDs = []; - if (message.messageIDs && message.messageIDs.length) { - object.messageIDs = []; - for (let j = 0; j < message.messageIDs.length; ++j) - object.messageIDs[j] = options.bytes === String ? $util.base64.encode(message.messageIDs[j], 0, message.messageIDs[j].length) : options.bytes === Array ? Array.prototype.slice.call(message.messageIDs[j]) : message.messageIDs[j]; - } - return object; - }; - - /** - * Converts this ControlIWant to JSON. - * @function toJSON - * @memberof RPC.ControlIWant - * @instance - * @returns {Object.} JSON object - */ - ControlIWant.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - /** - * Gets the default type url for ControlIWant - * @function getTypeUrl - * @memberof RPC.ControlIWant - * @static - * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") - * @returns {string} The default type url - */ - ControlIWant.getTypeUrl = function getTypeUrl(typeUrlPrefix) { - if (typeUrlPrefix === undefined) { - typeUrlPrefix = "type.googleapis.com"; - } - return typeUrlPrefix + "/RPC.ControlIWant"; - }; - - return ControlIWant; - })(); - - RPC.ControlGraft = (function() { - - /** - * Properties of a ControlGraft. - * @memberof RPC - * @interface IControlGraft - * @property {string|null} [topicID] ControlGraft topicID - */ - - /** - * Constructs a new ControlGraft. - * @memberof RPC - * @classdesc Represents a ControlGraft. - * @implements IControlGraft - * @constructor - * @param {RPC.IControlGraft=} [properties] Properties to set - */ - function ControlGraft(properties) { - if (properties) - for (let keys = Object.keys(properties), i = 0; i < keys.length; ++i) - if (properties[keys[i]] != null) - this[keys[i]] = properties[keys[i]]; - } - - /** - * ControlGraft topicID. - * @member {string|null|undefined} topicID - * @memberof RPC.ControlGraft - * @instance - */ - ControlGraft.prototype.topicID = null; - - // OneOf field names bound to virtual getters and setters - let $oneOfFields; - - /** - * ControlGraft _topicID. - * @member {"topicID"|undefined} _topicID - * @memberof RPC.ControlGraft - * @instance - */ - Object.defineProperty(ControlGraft.prototype, "_topicID", { - get: $util.oneOfGetter($oneOfFields = ["topicID"]), - set: $util.oneOfSetter($oneOfFields) - }); - - /** - * Creates a new ControlGraft instance using the specified properties. - * @function create - * @memberof RPC.ControlGraft - * @static - * @param {RPC.IControlGraft=} [properties] Properties to set - * @returns {RPC.ControlGraft} ControlGraft instance - */ - ControlGraft.create = function create(properties) { - return new ControlGraft(properties); - }; - - /** - * Encodes the specified ControlGraft message. Does not implicitly {@link RPC.ControlGraft.verify|verify} messages. - * @function encode - * @memberof RPC.ControlGraft - * @static - * @param {RPC.IControlGraft} message ControlGraft message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - ControlGraft.encode = function encode(message, writer) { - if (!writer) - writer = $Writer.create(); - if (message.topicID != null && Object.hasOwnProperty.call(message, "topicID")) - writer.uint32(/* id 1, wireType 2 =*/10).string(message.topicID); - return writer; - }; - - /** - * Encodes the specified ControlGraft message, length delimited. Does not implicitly {@link RPC.ControlGraft.verify|verify} messages. - * @function encodeDelimited - * @memberof RPC.ControlGraft - * @static - * @param {RPC.IControlGraft} message ControlGraft message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - ControlGraft.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes a ControlGraft message from the specified reader or buffer. - * @function decode - * @memberof RPC.ControlGraft - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @param {number} [length] Message length if known beforehand - * @returns {RPC.ControlGraft} ControlGraft - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - ControlGraft.decode = function decode(reader, length) { - if (!(reader instanceof $Reader)) - reader = $Reader.create(reader); - let end = length === undefined ? reader.len : reader.pos + length, message = new $root.RPC.ControlGraft(); - while (reader.pos < end) { - let tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - message.topicID = reader.string(); - break; - } - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }; - - /** - * Decodes a ControlGraft message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof RPC.ControlGraft - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {RPC.ControlGraft} ControlGraft - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - ControlGraft.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies a ControlGraft message. - * @function verify - * @memberof RPC.ControlGraft - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - ControlGraft.verify = function verify(message) { - if (typeof message !== "object" || message === null) - return "object expected"; - let properties = {}; - if (message.topicID != null && message.hasOwnProperty("topicID")) { - properties._topicID = 1; - if (!$util.isString(message.topicID)) - return "topicID: string expected"; - } - return null; - }; - - /** - * Creates a ControlGraft message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof RPC.ControlGraft - * @static - * @param {Object.} object Plain object - * @returns {RPC.ControlGraft} ControlGraft - */ - ControlGraft.fromObject = function fromObject(object) { - if (object instanceof $root.RPC.ControlGraft) - return object; - let message = new $root.RPC.ControlGraft(); - if (object.topicID != null) - message.topicID = String(object.topicID); - return message; - }; - - /** - * Creates a plain object from a ControlGraft message. Also converts values to other types if specified. - * @function toObject - * @memberof RPC.ControlGraft - * @static - * @param {RPC.ControlGraft} message ControlGraft - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - ControlGraft.toObject = function toObject(message, options) { - if (!options) - options = {}; - let object = {}; - if (message.topicID != null && message.hasOwnProperty("topicID")) { - object.topicID = message.topicID; - if (options.oneofs) - object._topicID = "topicID"; - } - return object; - }; - - /** - * Converts this ControlGraft to JSON. - * @function toJSON - * @memberof RPC.ControlGraft - * @instance - * @returns {Object.} JSON object - */ - ControlGraft.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - /** - * Gets the default type url for ControlGraft - * @function getTypeUrl - * @memberof RPC.ControlGraft - * @static - * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") - * @returns {string} The default type url - */ - ControlGraft.getTypeUrl = function getTypeUrl(typeUrlPrefix) { - if (typeUrlPrefix === undefined) { - typeUrlPrefix = "type.googleapis.com"; - } - return typeUrlPrefix + "/RPC.ControlGraft"; - }; - - return ControlGraft; - })(); - - RPC.ControlPrune = (function() { - - /** - * Properties of a ControlPrune. - * @memberof RPC - * @interface IControlPrune - * @property {string|null} [topicID] ControlPrune topicID - * @property {Array.|null} [peers] ControlPrune peers - * @property {number|Long|null} [backoff] ControlPrune backoff - */ - - /** - * Constructs a new ControlPrune. - * @memberof RPC - * @classdesc Represents a ControlPrune. - * @implements IControlPrune - * @constructor - * @param {RPC.IControlPrune=} [properties] Properties to set - */ - function ControlPrune(properties) { - this.peers = []; - if (properties) - for (let keys = Object.keys(properties), i = 0; i < keys.length; ++i) - if (properties[keys[i]] != null) - this[keys[i]] = properties[keys[i]]; - } - - /** - * ControlPrune topicID. - * @member {string|null|undefined} topicID - * @memberof RPC.ControlPrune - * @instance - */ - ControlPrune.prototype.topicID = null; - - /** - * ControlPrune peers. - * @member {Array.} peers - * @memberof RPC.ControlPrune - * @instance - */ - ControlPrune.prototype.peers = $util.emptyArray; - - /** - * ControlPrune backoff. - * @member {number|Long|null|undefined} backoff - * @memberof RPC.ControlPrune - * @instance - */ - ControlPrune.prototype.backoff = null; - - // OneOf field names bound to virtual getters and setters - let $oneOfFields; - - /** - * ControlPrune _topicID. - * @member {"topicID"|undefined} _topicID - * @memberof RPC.ControlPrune - * @instance - */ - Object.defineProperty(ControlPrune.prototype, "_topicID", { - get: $util.oneOfGetter($oneOfFields = ["topicID"]), - set: $util.oneOfSetter($oneOfFields) - }); - - /** - * ControlPrune _backoff. - * @member {"backoff"|undefined} _backoff - * @memberof RPC.ControlPrune - * @instance - */ - Object.defineProperty(ControlPrune.prototype, "_backoff", { - get: $util.oneOfGetter($oneOfFields = ["backoff"]), - set: $util.oneOfSetter($oneOfFields) - }); - - /** - * Creates a new ControlPrune instance using the specified properties. - * @function create - * @memberof RPC.ControlPrune - * @static - * @param {RPC.IControlPrune=} [properties] Properties to set - * @returns {RPC.ControlPrune} ControlPrune instance - */ - ControlPrune.create = function create(properties) { - return new ControlPrune(properties); - }; - - /** - * Encodes the specified ControlPrune message. Does not implicitly {@link RPC.ControlPrune.verify|verify} messages. - * @function encode - * @memberof RPC.ControlPrune - * @static - * @param {RPC.IControlPrune} message ControlPrune message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - ControlPrune.encode = function encode(message, writer) { - if (!writer) - writer = $Writer.create(); - if (message.topicID != null && Object.hasOwnProperty.call(message, "topicID")) - writer.uint32(/* id 1, wireType 2 =*/10).string(message.topicID); - if (message.peers != null && message.peers.length) - for (let i = 0; i < message.peers.length; ++i) - $root.RPC.PeerInfo.encode(message.peers[i], writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim(); - if (message.backoff != null && Object.hasOwnProperty.call(message, "backoff")) - writer.uint32(/* id 3, wireType 0 =*/24).uint64(message.backoff); - return writer; - }; - - /** - * Encodes the specified ControlPrune message, length delimited. Does not implicitly {@link RPC.ControlPrune.verify|verify} messages. - * @function encodeDelimited - * @memberof RPC.ControlPrune - * @static - * @param {RPC.IControlPrune} message ControlPrune message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - ControlPrune.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes a ControlPrune message from the specified reader or buffer. - * @function decode - * @memberof RPC.ControlPrune - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @param {number} [length] Message length if known beforehand - * @returns {RPC.ControlPrune} ControlPrune - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - ControlPrune.decode = function decode(reader, length) { - if (!(reader instanceof $Reader)) - reader = $Reader.create(reader); - let end = length === undefined ? reader.len : reader.pos + length, message = new $root.RPC.ControlPrune(); - while (reader.pos < end) { - let tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - message.topicID = reader.string(); - break; - } - case 2: { - if (!(message.peers && message.peers.length)) - message.peers = []; - message.peers.push($root.RPC.PeerInfo.decode(reader, reader.uint32())); - break; - } - case 3: { - message.backoff = reader.uint64(); - break; - } - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }; - - /** - * Decodes a ControlPrune message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof RPC.ControlPrune - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {RPC.ControlPrune} ControlPrune - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - ControlPrune.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies a ControlPrune message. - * @function verify - * @memberof RPC.ControlPrune - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - ControlPrune.verify = function verify(message) { - if (typeof message !== "object" || message === null) - return "object expected"; - let properties = {}; - if (message.topicID != null && message.hasOwnProperty("topicID")) { - properties._topicID = 1; - if (!$util.isString(message.topicID)) - return "topicID: string expected"; - } - if (message.peers != null && message.hasOwnProperty("peers")) { - if (!Array.isArray(message.peers)) - return "peers: array expected"; - for (let i = 0; i < message.peers.length; ++i) { - let error = $root.RPC.PeerInfo.verify(message.peers[i]); - if (error) - return "peers." + error; - } - } - if (message.backoff != null && message.hasOwnProperty("backoff")) { - properties._backoff = 1; - if (!$util.isInteger(message.backoff) && !(message.backoff && $util.isInteger(message.backoff.low) && $util.isInteger(message.backoff.high))) - return "backoff: integer|Long expected"; - } - return null; - }; - - /** - * Creates a ControlPrune message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof RPC.ControlPrune - * @static - * @param {Object.} object Plain object - * @returns {RPC.ControlPrune} ControlPrune - */ - ControlPrune.fromObject = function fromObject(object) { - if (object instanceof $root.RPC.ControlPrune) - return object; - let message = new $root.RPC.ControlPrune(); - if (object.topicID != null) - message.topicID = String(object.topicID); - if (object.peers) { - if (!Array.isArray(object.peers)) - throw TypeError(".RPC.ControlPrune.peers: array expected"); - message.peers = []; - for (let i = 0; i < object.peers.length; ++i) { - if (typeof object.peers[i] !== "object") - throw TypeError(".RPC.ControlPrune.peers: object expected"); - message.peers[i] = $root.RPC.PeerInfo.fromObject(object.peers[i]); - } - } - if (object.backoff != null) - if ($util.Long) - (message.backoff = $util.Long.fromValue(object.backoff)).unsigned = true; - else if (typeof object.backoff === "string") - message.backoff = parseInt(object.backoff, 10); - else if (typeof object.backoff === "number") - message.backoff = object.backoff; - else if (typeof object.backoff === "object") - message.backoff = new $util.LongBits(object.backoff.low >>> 0, object.backoff.high >>> 0).toNumber(true); - return message; - }; - - /** - * Creates a plain object from a ControlPrune message. Also converts values to other types if specified. - * @function toObject - * @memberof RPC.ControlPrune - * @static - * @param {RPC.ControlPrune} message ControlPrune - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - ControlPrune.toObject = function toObject(message, options) { - if (!options) - options = {}; - let object = {}; - if (options.arrays || options.defaults) - object.peers = []; - if (message.topicID != null && message.hasOwnProperty("topicID")) { - object.topicID = message.topicID; - if (options.oneofs) - object._topicID = "topicID"; - } - if (message.peers && message.peers.length) { - object.peers = []; - for (let j = 0; j < message.peers.length; ++j) - object.peers[j] = $root.RPC.PeerInfo.toObject(message.peers[j], options); - } - if (message.backoff != null && message.hasOwnProperty("backoff")) { - if (typeof message.backoff === "number") - object.backoff = options.longs === String ? String(message.backoff) : message.backoff; - else - object.backoff = options.longs === String ? $util.Long.prototype.toString.call(message.backoff) : options.longs === Number ? new $util.LongBits(message.backoff.low >>> 0, message.backoff.high >>> 0).toNumber(true) : message.backoff; - if (options.oneofs) - object._backoff = "backoff"; - } - return object; - }; - - /** - * Converts this ControlPrune to JSON. - * @function toJSON - * @memberof RPC.ControlPrune - * @instance - * @returns {Object.} JSON object - */ - ControlPrune.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - /** - * Gets the default type url for ControlPrune - * @function getTypeUrl - * @memberof RPC.ControlPrune - * @static - * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") - * @returns {string} The default type url - */ - ControlPrune.getTypeUrl = function getTypeUrl(typeUrlPrefix) { - if (typeUrlPrefix === undefined) { - typeUrlPrefix = "type.googleapis.com"; - } - return typeUrlPrefix + "/RPC.ControlPrune"; - }; - - return ControlPrune; - })(); - - RPC.PeerInfo = (function() { - - /** - * Properties of a PeerInfo. - * @memberof RPC - * @interface IPeerInfo - * @property {Uint8Array|null} [peerID] PeerInfo peerID - * @property {Uint8Array|null} [signedPeerRecord] PeerInfo signedPeerRecord - */ - - /** - * Constructs a new PeerInfo. - * @memberof RPC - * @classdesc Represents a PeerInfo. - * @implements IPeerInfo - * @constructor - * @param {RPC.IPeerInfo=} [properties] Properties to set - */ - function PeerInfo(properties) { - if (properties) - for (let keys = Object.keys(properties), i = 0; i < keys.length; ++i) - if (properties[keys[i]] != null) - this[keys[i]] = properties[keys[i]]; - } - - /** - * PeerInfo peerID. - * @member {Uint8Array|null|undefined} peerID - * @memberof RPC.PeerInfo - * @instance - */ - PeerInfo.prototype.peerID = null; - - /** - * PeerInfo signedPeerRecord. - * @member {Uint8Array|null|undefined} signedPeerRecord - * @memberof RPC.PeerInfo - * @instance - */ - PeerInfo.prototype.signedPeerRecord = null; - - // OneOf field names bound to virtual getters and setters - let $oneOfFields; - - /** - * PeerInfo _peerID. - * @member {"peerID"|undefined} _peerID - * @memberof RPC.PeerInfo - * @instance - */ - Object.defineProperty(PeerInfo.prototype, "_peerID", { - get: $util.oneOfGetter($oneOfFields = ["peerID"]), - set: $util.oneOfSetter($oneOfFields) - }); - - /** - * PeerInfo _signedPeerRecord. - * @member {"signedPeerRecord"|undefined} _signedPeerRecord - * @memberof RPC.PeerInfo - * @instance - */ - Object.defineProperty(PeerInfo.prototype, "_signedPeerRecord", { - get: $util.oneOfGetter($oneOfFields = ["signedPeerRecord"]), - set: $util.oneOfSetter($oneOfFields) - }); - - /** - * Creates a new PeerInfo instance using the specified properties. - * @function create - * @memberof RPC.PeerInfo - * @static - * @param {RPC.IPeerInfo=} [properties] Properties to set - * @returns {RPC.PeerInfo} PeerInfo instance - */ - PeerInfo.create = function create(properties) { - return new PeerInfo(properties); - }; - - /** - * Encodes the specified PeerInfo message. Does not implicitly {@link RPC.PeerInfo.verify|verify} messages. - * @function encode - * @memberof RPC.PeerInfo - * @static - * @param {RPC.IPeerInfo} message PeerInfo message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - PeerInfo.encode = function encode(message, writer) { - if (!writer) - writer = $Writer.create(); - if (message.peerID != null && Object.hasOwnProperty.call(message, "peerID")) - writer.uint32(/* id 1, wireType 2 =*/10).bytes(message.peerID); - if (message.signedPeerRecord != null && Object.hasOwnProperty.call(message, "signedPeerRecord")) - writer.uint32(/* id 2, wireType 2 =*/18).bytes(message.signedPeerRecord); - return writer; - }; - - /** - * Encodes the specified PeerInfo message, length delimited. Does not implicitly {@link RPC.PeerInfo.verify|verify} messages. - * @function encodeDelimited - * @memberof RPC.PeerInfo - * @static - * @param {RPC.IPeerInfo} message PeerInfo message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - PeerInfo.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes a PeerInfo message from the specified reader or buffer. - * @function decode - * @memberof RPC.PeerInfo - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @param {number} [length] Message length if known beforehand - * @returns {RPC.PeerInfo} PeerInfo - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - PeerInfo.decode = function decode(reader, length) { - if (!(reader instanceof $Reader)) - reader = $Reader.create(reader); - let end = length === undefined ? reader.len : reader.pos + length, message = new $root.RPC.PeerInfo(); - while (reader.pos < end) { - let tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - message.peerID = reader.bytes(); - break; - } - case 2: { - message.signedPeerRecord = reader.bytes(); - break; - } - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }; - - /** - * Decodes a PeerInfo message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof RPC.PeerInfo - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {RPC.PeerInfo} PeerInfo - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - PeerInfo.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies a PeerInfo message. - * @function verify - * @memberof RPC.PeerInfo - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - PeerInfo.verify = function verify(message) { - if (typeof message !== "object" || message === null) - return "object expected"; - let properties = {}; - if (message.peerID != null && message.hasOwnProperty("peerID")) { - properties._peerID = 1; - if (!(message.peerID && typeof message.peerID.length === "number" || $util.isString(message.peerID))) - return "peerID: buffer expected"; - } - if (message.signedPeerRecord != null && message.hasOwnProperty("signedPeerRecord")) { - properties._signedPeerRecord = 1; - if (!(message.signedPeerRecord && typeof message.signedPeerRecord.length === "number" || $util.isString(message.signedPeerRecord))) - return "signedPeerRecord: buffer expected"; - } - return null; - }; - - /** - * Creates a PeerInfo message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof RPC.PeerInfo - * @static - * @param {Object.} object Plain object - * @returns {RPC.PeerInfo} PeerInfo - */ - PeerInfo.fromObject = function fromObject(object) { - if (object instanceof $root.RPC.PeerInfo) - return object; - let message = new $root.RPC.PeerInfo(); - if (object.peerID != null) - if (typeof object.peerID === "string") - $util.base64.decode(object.peerID, message.peerID = $util.newBuffer($util.base64.length(object.peerID)), 0); - else if (object.peerID.length >= 0) - message.peerID = object.peerID; - if (object.signedPeerRecord != null) - if (typeof object.signedPeerRecord === "string") - $util.base64.decode(object.signedPeerRecord, message.signedPeerRecord = $util.newBuffer($util.base64.length(object.signedPeerRecord)), 0); - else if (object.signedPeerRecord.length >= 0) - message.signedPeerRecord = object.signedPeerRecord; - return message; - }; - - /** - * Creates a plain object from a PeerInfo message. Also converts values to other types if specified. - * @function toObject - * @memberof RPC.PeerInfo - * @static - * @param {RPC.PeerInfo} message PeerInfo - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - PeerInfo.toObject = function toObject(message, options) { - if (!options) - options = {}; - let object = {}; - if (message.peerID != null && message.hasOwnProperty("peerID")) { - object.peerID = options.bytes === String ? $util.base64.encode(message.peerID, 0, message.peerID.length) : options.bytes === Array ? Array.prototype.slice.call(message.peerID) : message.peerID; - if (options.oneofs) - object._peerID = "peerID"; - } - if (message.signedPeerRecord != null && message.hasOwnProperty("signedPeerRecord")) { - object.signedPeerRecord = options.bytes === String ? $util.base64.encode(message.signedPeerRecord, 0, message.signedPeerRecord.length) : options.bytes === Array ? Array.prototype.slice.call(message.signedPeerRecord) : message.signedPeerRecord; - if (options.oneofs) - object._signedPeerRecord = "signedPeerRecord"; - } - return object; - }; - - /** - * Converts this PeerInfo to JSON. - * @function toJSON - * @memberof RPC.PeerInfo - * @instance - * @returns {Object.} JSON object - */ - PeerInfo.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - /** - * Gets the default type url for PeerInfo - * @function getTypeUrl - * @memberof RPC.PeerInfo - * @static - * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") - * @returns {string} The default type url - */ - PeerInfo.getTypeUrl = function getTypeUrl(typeUrlPrefix) { - if (typeUrlPrefix === undefined) { - typeUrlPrefix = "type.googleapis.com"; - } - return typeUrlPrefix + "/RPC.PeerInfo"; - }; - - return PeerInfo; - })(); - - return RPC; -})(); - -export { $root as default }; diff --git a/packages/protons-benchmark/src/implementations/protons/bench.ts b/packages/protons-benchmark/src/implementations/protons/bench.ts index 0335913..9171f95 100644 --- a/packages/protons-benchmark/src/implementations/protons/bench.ts +++ b/packages/protons-benchmark/src/implementations/protons/bench.ts @@ -1,5 +1,5 @@ -import { encodeMessage, decodeMessage, message, enumeration } from 'protons-runtime' -import type { Codec } from 'protons-runtime' +import { decodeMessage, encodeMessage, enumeration, MaxLengthError, message, streamMessage } from 'protons-runtime' +import type { Codec, DecodeOptions, StreamingDecodeOptions, StreamingDecodeWithCollectionsOptions } from 'protons-runtime' import type { Uint8ArrayList } from 'uint8arraylist' export interface Foo { @@ -7,11 +7,11 @@ export interface Foo { } export namespace Foo { - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -24,7 +24,7 @@ export namespace Foo { if (opts.lengthDelimited !== false) { w.ldelim() } - }, (reader, length) => { + }, (reader, length, opts = {}) => { const obj: any = {} const end = length == null ? reader.len : reader.pos + length @@ -33,28 +33,83 @@ export namespace Foo { const tag = reader.uint32() switch (tag >>> 3) { - case 1: + case 1: { obj.baz = reader.uint32() break - default: + } + default: { reader.skipType(tag & 7) break + } } } return obj + }, function * (reader, length, opts = {}) { + let obj: any + + if (opts.emitCollections === true) { + obj = {} + } else { + obj = {} + } + + const end = length == null ? reader.len : reader.pos + length + + while (reader.pos < end) { + const tag = reader.uint32() + + switch (tag >>> 3) { + case 1: { + yield { + field: 'baz', + value: reader.uint32() + } + break + } + default: { + reader.skipType(tag & 7) + break + } + } + } + + if (opts.emitCollections === true) { + for (const [key, value] of Object.entries(obj)) { + if (Array.isArray(value) || value instanceof Map) { + yield { + field: key, + value + } + } + } + } }) } return _codec } - export const encode = (obj: Foo): Uint8Array => { + export interface FooBazFieldEvent { + field: 'baz' + value: number + } + + export type FooStreamEvent = FooBazFieldEvent + export type FooStreamCollectionsEvent = {} + + export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, Foo.codec()) } - export const decode = (buf: Uint8Array | Uint8ArrayList): Foo => { - return decodeMessage(buf, Foo.codec()) + export function decode (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Foo { + return decodeMessage(buf, Foo.codec(), opts) + } + + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + return streamMessage(buf, Foo.codec(), opts) } } @@ -63,26 +118,24 @@ export interface Bar { } export namespace Bar { - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } if (obj.tmp != null) { w.uint32(10) - Foo.codec().encode(obj.tmp, w, { - writeDefaults: false - }) + Foo.codec().encode(obj.tmp, w) } if (opts.lengthDelimited !== false) { w.ldelim() } - }, (reader, length) => { + }, (reader, length, opts = {}) => { const obj: any = {} const end = length == null ? reader.len : reader.pos + length @@ -91,28 +144,87 @@ export namespace Bar { const tag = reader.uint32() switch (tag >>> 3) { - case 1: - obj.tmp = Foo.codec().decode(reader, reader.uint32()) + case 1: { + obj.tmp = Foo.codec().decode(reader, reader.uint32(), { + limits: opts.limits?.tmp + }) break - default: + } + default: { reader.skipType(tag & 7) break + } } } return obj + }, function * (reader, length, opts = {}) { + let obj: any + + if (opts.emitCollections === true) { + obj = {} + } else { + obj = {} + } + + const end = length == null ? reader.len : reader.pos + length + + while (reader.pos < end) { + const tag = reader.uint32() + + switch (tag >>> 3) { + case 1: { + yield { + field: 'tmp', + value: Foo.codec().decode(reader, reader.uint32(), { + limits: opts.limits?.tmp + }) + } + break + } + default: { + reader.skipType(tag & 7) + break + } + } + } + + if (opts.emitCollections === true) { + for (const [key, value] of Object.entries(obj)) { + if (Array.isArray(value) || value instanceof Map) { + yield { + field: key, + value + } + } + } + } }) } return _codec } - export const encode = (obj: Bar): Uint8Array => { + export interface BarTmpFieldEvent { + field: 'tmp' + value: Foo + } + + export type BarStreamEvent = BarTmpFieldEvent + export type BarStreamCollectionsEvent = {} + + export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, Bar.codec()) } - export const decode = (buf: Uint8Array | Uint8ArrayList): Bar => { - return decodeMessage(buf, Bar.codec()) + export function decode (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Bar { + return decodeMessage(buf, Bar.codec(), opts) + } + + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + return streamMessage(buf, Bar.codec(), opts) } } @@ -129,20 +241,21 @@ enum __FOOValues { } export namespace FOO { - export const codec = (): Codec => { + export const codec = (): Codec => { return enumeration(__FOOValues) } } + export interface Yo { lol: FOO[] } export namespace Yo { - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -157,7 +270,7 @@ export namespace Yo { if (opts.lengthDelimited !== false) { w.ldelim() } - }, (reader, length) => { + }, (reader, length, opts = {}) => { const obj: any = { lol: [] } @@ -168,28 +281,111 @@ export namespace Yo { const tag = reader.uint32() switch (tag >>> 3) { - case 1: + case 1: { + if (opts.limits?.lol != null && obj.lol.length === opts.limits.lol) { + throw new MaxLengthError('Decode error - map field "lol" had too many elements') + } + obj.lol.push(FOO.codec().decode(reader)) break - default: + } + default: { reader.skipType(tag & 7) break + } } } return obj + }, function * (reader, length, opts = {}) { + let obj: any + + if (opts.emitCollections === true) { + obj = { + lol: [] + } + } else { + obj = { + lol: 0 + } + } + + const end = length == null ? reader.len : reader.pos + length + + while (reader.pos < end) { + const tag = reader.uint32() + + switch (tag >>> 3) { + case 1: { + if (opts.limits?.lol != null && (opts.emitCollections === true ? obj.lol.length === opts.limits.lol : obj.lol === opts.limits.lol)) { + throw new MaxLengthError('Decode error - map field "lol" had too many elements') + } + + const value = FOO.codec().decode(reader) + + yield { + field: 'lol$value', + index: opts.emitCollections === true ? obj.lol.length : obj.lol, + value + } + + if (opts.emitCollections === true) { + obj.lol.push(value) + } else { + obj.lol++ + } + + break + } + default: { + reader.skipType(tag & 7) + break + } + } + } + + if (opts.emitCollections === true) { + for (const [key, value] of Object.entries(obj)) { + if (Array.isArray(value) || value instanceof Map) { + yield { + field: key, + value + } + } + } + } }) } return _codec } - export const encode = (obj: Yo): Uint8Array => { + export interface YoLolFieldEvent { + field: 'lol' + value: FOO[] + } + + export interface YoLolValueEvent { + field: 'lol$value' + index: number + value: FOO + } + + export type YoStreamEvent = YoLolValueEvent + export type YoStreamCollectionsEvent = YoLolFieldEvent + + export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, Yo.codec()) } - export const decode = (buf: Uint8Array | Uint8ArrayList): Yo => { - return decodeMessage(buf, Yo.codec()) + export function decode (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Yo { + return decodeMessage(buf, Yo.codec(), opts) + } + + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + return streamMessage(buf, Yo.codec(), opts) } } @@ -199,11 +395,11 @@ export interface Lol { } export namespace Lol { - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -215,15 +411,13 @@ export namespace Lol { if (obj.b != null) { w.uint32(18) - Bar.codec().encode(obj.b, w, { - writeDefaults: false - }) + Bar.codec().encode(obj.b, w) } if (opts.lengthDelimited !== false) { w.ldelim() } - }, (reader, length) => { + }, (reader, length, opts = {}) => { const obj: any = {} const end = length == null ? reader.len : reader.pos + length @@ -232,31 +426,103 @@ export namespace Lol { const tag = reader.uint32() switch (tag >>> 3) { - case 1: + case 1: { obj.lol = reader.string() break - case 2: - obj.b = Bar.codec().decode(reader, reader.uint32()) + } + case 2: { + obj.b = Bar.codec().decode(reader, reader.uint32(), { + limits: opts.limits?.b + }) break - default: + } + default: { reader.skipType(tag & 7) break + } } } return obj + }, function * (reader, length, opts = {}) { + let obj: any + + if (opts.emitCollections === true) { + obj = {} + } else { + obj = {} + } + + const end = length == null ? reader.len : reader.pos + length + + while (reader.pos < end) { + const tag = reader.uint32() + + switch (tag >>> 3) { + case 1: { + yield { + field: 'lol', + value: reader.string() + } + break + } + case 2: { + yield { + field: 'b', + value: Bar.codec().decode(reader, reader.uint32(), { + limits: opts.limits?.b + }) + } + break + } + default: { + reader.skipType(tag & 7) + break + } + } + } + + if (opts.emitCollections === true) { + for (const [key, value] of Object.entries(obj)) { + if (Array.isArray(value) || value instanceof Map) { + yield { + field: key, + value + } + } + } + } }) } return _codec } - export const encode = (obj: Lol): Uint8Array => { + export interface LolLolFieldEvent { + field: 'lol' + value: string + } + + export interface LolBFieldEvent { + field: 'b' + value: Bar + } + + export type LolStreamEvent = LolLolFieldEvent | LolBFieldEvent + export type LolStreamCollectionsEvent = {} + + export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, Lol.codec()) } - export const decode = (buf: Uint8Array | Uint8ArrayList): Lol => { - return decodeMessage(buf, Lol.codec()) + export function decode (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Lol { + return decodeMessage(buf, Lol.codec(), opts) + } + + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + return streamMessage(buf, Lol.codec(), opts) } } @@ -268,20 +534,18 @@ export interface Test { } export namespace Test { - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } if (obj.meh != null) { w.uint32(50) - Lol.codec().encode(obj.meh, w, { - writeDefaults: false - }) + Lol.codec().encode(obj.meh, w) } if (obj.hello != null) { @@ -302,7 +566,7 @@ export namespace Test { if (opts.lengthDelimited !== false) { w.ldelim() } - }, (reader, length) => { + }, (reader, length, opts = {}) => { const obj: any = {} const end = length == null ? reader.len : reader.pos + length @@ -311,36 +575,134 @@ export namespace Test { const tag = reader.uint32() switch (tag >>> 3) { - case 6: - obj.meh = Lol.codec().decode(reader, reader.uint32()) + case 6: { + obj.meh = Lol.codec().decode(reader, reader.uint32(), { + limits: opts.limits?.meh + }) break - case 3: + } + case 3: { obj.hello = reader.uint32() break - case 1: + } + case 1: { obj.foo = reader.string() break - case 7: + } + case 7: { obj.payload = reader.bytes() break - default: + } + default: { reader.skipType(tag & 7) break + } } } return obj + }, function * (reader, length, opts = {}) { + let obj: any + + if (opts.emitCollections === true) { + obj = {} + } else { + obj = {} + } + + const end = length == null ? reader.len : reader.pos + length + + while (reader.pos < end) { + const tag = reader.uint32() + + switch (tag >>> 3) { + case 6: { + yield { + field: 'meh', + value: Lol.codec().decode(reader, reader.uint32(), { + limits: opts.limits?.meh + }) + } + break + } + case 3: { + yield { + field: 'hello', + value: reader.uint32() + } + break + } + case 1: { + yield { + field: 'foo', + value: reader.string() + } + break + } + case 7: { + yield { + field: 'payload', + value: reader.bytes() + } + break + } + default: { + reader.skipType(tag & 7) + break + } + } + } + + if (opts.emitCollections === true) { + for (const [key, value] of Object.entries(obj)) { + if (Array.isArray(value) || value instanceof Map) { + yield { + field: key, + value + } + } + } + } }) } return _codec } - export const encode = (obj: Test): Uint8Array => { + export interface TestMehFieldEvent { + field: 'meh' + value: Lol + } + + export interface TestHelloFieldEvent { + field: 'hello' + value: number + } + + export interface TestFooFieldEvent { + field: 'foo' + value: string + } + + export interface TestPayloadFieldEvent { + field: 'payload' + value: Uint8Array + } + + export type TestStreamEvent = TestMehFieldEvent | TestHelloFieldEvent | TestFooFieldEvent | TestPayloadFieldEvent + export type TestStreamCollectionsEvent = {} + + export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, Test.codec()) } - export const decode = (buf: Uint8Array | Uint8ArrayList): Test => { - return decodeMessage(buf, Test.codec()) + export function decode (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Test { + return decodeMessage(buf, Test.codec(), opts) + } + + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + return streamMessage(buf, Test.codec(), opts) } } diff --git a/packages/protons-benchmark/src/implementations/protons/rpc.ts b/packages/protons-benchmark/src/implementations/protons/rpc.ts deleted file mode 100644 index abaa988..0000000 --- a/packages/protons-benchmark/src/implementations/protons/rpc.ts +++ /dev/null @@ -1,734 +0,0 @@ -import { encodeMessage, decodeMessage, message, writer } from 'protons-runtime' -import type { Codec } from 'protons-runtime' -import type { Uint8ArrayList } from 'uint8arraylist' - -export interface RPC { - subscriptions: RPC.SubOpts[] - messages: RPC.Message[] - control?: RPC.ControlMessage -} - -export namespace RPC { - export interface SubOpts { - subscribe?: boolean - topic?: string - } - - export namespace SubOpts { - let _codec: Codec - - export const codec = (): Codec => { - if (_codec == null) { - _codec = message((obj, w, opts = {}) => { - if (opts.lengthDelimited !== false) { - w.fork() - } - - if (obj.subscribe != null) { - w.uint32(8) - w.bool(obj.subscribe) - } - - if (obj.topic != null) { - w.uint32(18) - w.string(obj.topic) - } - - if (opts.lengthDelimited !== false) { - w.ldelim() - } - }, (reader, length) => { - const obj: any = {} - - const end = length == null ? reader.len : reader.pos + length - - while (reader.pos < end) { - const tag = reader.uint32() - - switch (tag >>> 3) { - case 1: - obj.subscribe = reader.bool() - break - case 2: - obj.topic = reader.string() - break - default: - reader.skipType(tag & 7) - break - } - } - - return obj - }) - } - - return _codec - } - - export const encode = (obj: SubOpts): Uint8Array => { - return encodeMessage(obj, SubOpts.codec()) - } - - export const decode = (buf: Uint8Array | Uint8ArrayList): SubOpts => { - return decodeMessage(buf, SubOpts.codec()) - } - } - - export interface Message { - from?: Uint8Array - data?: Uint8Array - seqno?: Uint8Array - topic: string - signature?: Uint8Array - key?: Uint8Array - } - - export namespace Message { - let _codec: Codec - - export const codec = (): Codec => { - if (_codec == null) { - _codec = message((obj, w, opts = {}) => { - if (opts.lengthDelimited !== false) { - w.fork() - } - - if (obj.from != null) { - w.uint32(10) - w.bytes(obj.from) - } - - if (obj.data != null) { - w.uint32(18) - w.bytes(obj.data) - } - - if (obj.seqno != null) { - w.uint32(26) - w.bytes(obj.seqno) - } - - if (opts.writeDefaults === true || obj.topic !== '') { - w.uint32(34) - w.string(obj.topic ?? '') - } - - if (obj.signature != null) { - w.uint32(42) - w.bytes(obj.signature) - } - - if (obj.key != null) { - w.uint32(50) - w.bytes(obj.key) - } - - if (opts.lengthDelimited !== false) { - w.ldelim() - } - }, (reader, length) => { - const obj: any = { - topic: '' - } - - const end = length == null ? reader.len : reader.pos + length - - while (reader.pos < end) { - const tag = reader.uint32() - - switch (tag >>> 3) { - case 1: - obj.from = reader.bytes() - break - case 2: - obj.data = reader.bytes() - break - case 3: - obj.seqno = reader.bytes() - break - case 4: - obj.topic = reader.string() - break - case 5: - obj.signature = reader.bytes() - break - case 6: - obj.key = reader.bytes() - break - default: - reader.skipType(tag & 7) - break - } - } - - return obj - }) - } - - return _codec - } - - export const encode = (obj: Message): Uint8Array => { - return encodeMessage(obj, Message.codec()) - } - - export const decode = (buf: Uint8Array | Uint8ArrayList): Message => { - return decodeMessage(buf, Message.codec()) - } - } - - export interface ControlMessage { - ihave: RPC.ControlIHave[] - iwant: RPC.ControlIWant[] - graft: RPC.ControlGraft[] - prune: RPC.ControlPrune[] - } - - export namespace ControlMessage { - let _codec: Codec - - export const codec = (): Codec => { - if (_codec == null) { - _codec = message((obj, w, opts = {}) => { - if (opts.lengthDelimited !== false) { - w.fork() - } - - if (obj.ihave != null) { - for (const value of obj.ihave) { - const mw = writer() - RPC.ControlIHave.codec().encode(value, mw, { - lengthDelimited: false, - writeDefaults: true - }) - const buf = mw.finish() - - w.uint32(10) - w.bytes(buf) - } - } - - if (obj.iwant != null) { - for (const value of obj.iwant) { - const mw = writer() - RPC.ControlIWant.codec().encode(value, mw, { - lengthDelimited: false, - writeDefaults: true - }) - const buf = mw.finish() - - w.uint32(18) - w.bytes(buf) - } - } - - if (obj.graft != null) { - for (const value of obj.graft) { - const mw = writer() - RPC.ControlGraft.codec().encode(value, mw, { - lengthDelimited: false, - writeDefaults: true - }) - const buf = mw.finish() - - w.uint32(26) - w.bytes(buf) - } - } - - if (obj.prune != null) { - for (const value of obj.prune) { - const mw = writer() - RPC.ControlPrune.codec().encode(value, mw, { - lengthDelimited: false, - writeDefaults: true - }) - const buf = mw.finish() - - w.uint32(34) - w.bytes(buf) - } - } - - if (opts.lengthDelimited !== false) { - w.ldelim() - } - }, (reader, length) => { - const obj: any = { - ihave: [], - iwant: [], - graft: [], - prune: [] - } - - const end = length == null ? reader.len : reader.pos + length - - while (reader.pos < end) { - const tag = reader.uint32() - - switch (tag >>> 3) { - case 1: - obj.ihave.push(RPC.ControlIHave.codec().decode(reader, reader.uint32())) - break - case 2: - obj.iwant.push(RPC.ControlIWant.codec().decode(reader, reader.uint32())) - break - case 3: - obj.graft.push(RPC.ControlGraft.codec().decode(reader, reader.uint32())) - break - case 4: - obj.prune.push(RPC.ControlPrune.codec().decode(reader, reader.uint32())) - break - default: - reader.skipType(tag & 7) - break - } - } - - return obj - }) - } - - return _codec - } - - export const encode = (obj: ControlMessage): Uint8Array => { - return encodeMessage(obj, ControlMessage.codec()) - } - - export const decode = (buf: Uint8Array | Uint8ArrayList): ControlMessage => { - return decodeMessage(buf, ControlMessage.codec()) - } - } - - export interface ControlIHave { - topicID?: string - messageIDs: Uint8Array[] - } - - export namespace ControlIHave { - let _codec: Codec - - export const codec = (): Codec => { - if (_codec == null) { - _codec = message((obj, w, opts = {}) => { - if (opts.lengthDelimited !== false) { - w.fork() - } - - if (obj.topicID != null) { - w.uint32(10) - w.string(obj.topicID) - } - - if (obj.messageIDs != null) { - for (const value of obj.messageIDs) { - w.uint32(18) - w.bytes(value) - } - } - - if (opts.lengthDelimited !== false) { - w.ldelim() - } - }, (reader, length) => { - const obj: any = { - messageIDs: [] - } - - const end = length == null ? reader.len : reader.pos + length - - while (reader.pos < end) { - const tag = reader.uint32() - - switch (tag >>> 3) { - case 1: - obj.topicID = reader.string() - break - case 2: - obj.messageIDs.push(reader.bytes()) - break - default: - reader.skipType(tag & 7) - break - } - } - - return obj - }) - } - - return _codec - } - - export const encode = (obj: ControlIHave): Uint8Array => { - return encodeMessage(obj, ControlIHave.codec()) - } - - export const decode = (buf: Uint8Array | Uint8ArrayList): ControlIHave => { - return decodeMessage(buf, ControlIHave.codec()) - } - } - - export interface ControlIWant { - messageIDs: Uint8Array[] - } - - export namespace ControlIWant { - let _codec: Codec - - export const codec = (): Codec => { - if (_codec == null) { - _codec = message((obj, w, opts = {}) => { - if (opts.lengthDelimited !== false) { - w.fork() - } - - if (obj.messageIDs != null) { - for (const value of obj.messageIDs) { - w.uint32(10) - w.bytes(value) - } - } - - if (opts.lengthDelimited !== false) { - w.ldelim() - } - }, (reader, length) => { - const obj: any = { - messageIDs: [] - } - - const end = length == null ? reader.len : reader.pos + length - - while (reader.pos < end) { - const tag = reader.uint32() - - switch (tag >>> 3) { - case 1: - obj.messageIDs.push(reader.bytes()) - break - default: - reader.skipType(tag & 7) - break - } - } - - return obj - }) - } - - return _codec - } - - export const encode = (obj: ControlIWant): Uint8Array => { - return encodeMessage(obj, ControlIWant.codec()) - } - - export const decode = (buf: Uint8Array | Uint8ArrayList): ControlIWant => { - return decodeMessage(buf, ControlIWant.codec()) - } - } - - export interface ControlGraft { - topicID?: string - } - - export namespace ControlGraft { - let _codec: Codec - - export const codec = (): Codec => { - if (_codec == null) { - _codec = message((obj, w, opts = {}) => { - if (opts.lengthDelimited !== false) { - w.fork() - } - - if (obj.topicID != null) { - w.uint32(10) - w.string(obj.topicID) - } - - if (opts.lengthDelimited !== false) { - w.ldelim() - } - }, (reader, length) => { - const obj: any = {} - - const end = length == null ? reader.len : reader.pos + length - - while (reader.pos < end) { - const tag = reader.uint32() - - switch (tag >>> 3) { - case 1: - obj.topicID = reader.string() - break - default: - reader.skipType(tag & 7) - break - } - } - - return obj - }) - } - - return _codec - } - - export const encode = (obj: ControlGraft): Uint8Array => { - return encodeMessage(obj, ControlGraft.codec()) - } - - export const decode = (buf: Uint8Array | Uint8ArrayList): ControlGraft => { - return decodeMessage(buf, ControlGraft.codec()) - } - } - - export interface ControlPrune { - topicID?: string - peers: RPC.PeerInfo[] - backoff?: bigint - } - - export namespace ControlPrune { - let _codec: Codec - - export const codec = (): Codec => { - if (_codec == null) { - _codec = message((obj, w, opts = {}) => { - if (opts.lengthDelimited !== false) { - w.fork() - } - - if (obj.topicID != null) { - w.uint32(10) - w.string(obj.topicID) - } - - if (obj.peers != null) { - for (const value of obj.peers) { - const mw = writer() - RPC.PeerInfo.codec().encode(value, mw, { - lengthDelimited: false, - writeDefaults: true - }) - const buf = mw.finish() - - w.uint32(18) - w.bytes(buf) - } - } - - if (obj.backoff != null) { - w.uint32(24) - w.uint64(obj.backoff) - } - - if (opts.lengthDelimited !== false) { - w.ldelim() - } - }, (reader, length) => { - const obj: any = { - peers: [] - } - - const end = length == null ? reader.len : reader.pos + length - - while (reader.pos < end) { - const tag = reader.uint32() - - switch (tag >>> 3) { - case 1: - obj.topicID = reader.string() - break - case 2: - obj.peers.push(RPC.PeerInfo.codec().decode(reader, reader.uint32())) - break - case 3: - obj.backoff = reader.uint64() - break - default: - reader.skipType(tag & 7) - break - } - } - - return obj - }) - } - - return _codec - } - - export const encode = (obj: ControlPrune): Uint8Array => { - return encodeMessage(obj, ControlPrune.codec()) - } - - export const decode = (buf: Uint8Array | Uint8ArrayList): ControlPrune => { - return decodeMessage(buf, ControlPrune.codec()) - } - } - - export interface PeerInfo { - peerID?: Uint8Array - signedPeerRecord?: Uint8Array - } - - export namespace PeerInfo { - let _codec: Codec - - export const codec = (): Codec => { - if (_codec == null) { - _codec = message((obj, w, opts = {}) => { - if (opts.lengthDelimited !== false) { - w.fork() - } - - if (obj.peerID != null) { - w.uint32(10) - w.bytes(obj.peerID) - } - - if (obj.signedPeerRecord != null) { - w.uint32(18) - w.bytes(obj.signedPeerRecord) - } - - if (opts.lengthDelimited !== false) { - w.ldelim() - } - }, (reader, length) => { - const obj: any = {} - - const end = length == null ? reader.len : reader.pos + length - - while (reader.pos < end) { - const tag = reader.uint32() - - switch (tag >>> 3) { - case 1: - obj.peerID = reader.bytes() - break - case 2: - obj.signedPeerRecord = reader.bytes() - break - default: - reader.skipType(tag & 7) - break - } - } - - return obj - }) - } - - return _codec - } - - export const encode = (obj: PeerInfo): Uint8Array => { - return encodeMessage(obj, PeerInfo.codec()) - } - - export const decode = (buf: Uint8Array | Uint8ArrayList): PeerInfo => { - return decodeMessage(buf, PeerInfo.codec()) - } - } - - let _codec: Codec - - export const codec = (): Codec => { - if (_codec == null) { - _codec = message((obj, w, opts = {}) => { - if (opts.lengthDelimited !== false) { - w.fork() - } - - if (obj.subscriptions != null) { - for (const value of obj.subscriptions) { - const mw = writer() - RPC.SubOpts.codec().encode(value, mw, { - lengthDelimited: false, - writeDefaults: true - }) - const buf = mw.finish() - - w.uint32(10) - w.bytes(buf) - } - } - - if (obj.messages != null) { - for (const value of obj.messages) { - const mw = writer() - RPC.Message.codec().encode(value, mw, { - lengthDelimited: false, - writeDefaults: true - }) - const buf = mw.finish() - - w.uint32(18) - w.bytes(buf) - } - } - - if (obj.control != null) { - 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) { - w.ldelim() - } - }, (reader, length) => { - const obj: any = { - subscriptions: [], - messages: [] - } - - const end = length == null ? reader.len : reader.pos + length - - while (reader.pos < end) { - const tag = reader.uint32() - - switch (tag >>> 3) { - case 1: - obj.subscriptions.push(RPC.SubOpts.codec().decode(reader, reader.uint32())) - break - case 2: - obj.messages.push(RPC.Message.codec().decode(reader, reader.uint32())) - break - case 3: - obj.control = RPC.ControlMessage.codec().decode(reader, reader.uint32()) - break - default: - reader.skipType(tag & 7) - break - } - } - - return obj - }) - } - - return _codec - } - - export const encode = (obj: RPC): Uint8Array => { - return encodeMessage(obj, RPC.codec()) - } - - export const decode = (buf: Uint8Array | Uint8ArrayList): RPC => { - return decodeMessage(buf, RPC.codec()) - } -} diff --git a/packages/protons/src/index.ts b/packages/protons/src/index.ts index 7cb11da..ee7f0be 100644 --- a/packages/protons/src/index.ts +++ b/packages/protons/src/index.ts @@ -1557,7 +1557,8 @@ export async function generate (source: string, flags: Flags): Promise { '/* eslint-disable @typescript-eslint/no-unnecessary-boolean-literal-compare */', '/* eslint-disable @typescript-eslint/no-empty-interface */', '/* eslint-disable import/consistent-type-specifier-style */', - '/* eslint-disable @typescript-eslint/no-unused-vars */' + '/* eslint-disable @typescript-eslint/no-unused-vars */', + '/* eslint-disable require-yield */' ] const imports = [] diff --git a/packages/protons/test/fixtures/basic.ts b/packages/protons/test/fixtures/basic.ts index 7ac1f08..07526f0 100644 --- a/packages/protons/test/fixtures/basic.ts +++ b/packages/protons/test/fixtures/basic.ts @@ -1,11 +1,3 @@ -/* eslint-disable import/export */ -/* eslint-disable complexity */ -/* eslint-disable @typescript-eslint/no-namespace */ -/* eslint-disable @typescript-eslint/no-unnecessary-boolean-literal-compare */ -/* eslint-disable @typescript-eslint/no-empty-interface */ -/* eslint-disable import/consistent-type-specifier-style */ -/* eslint-disable @typescript-eslint/no-unused-vars */ - import { decodeMessage, encodeMessage, message, streamMessage } from 'protons-runtime' import type { Codec, DecodeOptions, StreamingDecodeOptions, StreamingDecodeWithCollectionsOptions } from 'protons-runtime' import type { Uint8ArrayList } from 'uint8arraylist' @@ -70,8 +62,8 @@ export namespace Basic { if (opts.emitCollections === true) { obj = { - num: 0 - } + num: 0 + } } else { obj = {} } @@ -103,6 +95,16 @@ export namespace Basic { } } + if (opts.emitCollections === true) { + for (const [key, value] of Object.entries(obj)) { + if (Array.isArray(value) || value instanceof Map) { + yield { + field: key, + value + } + } + } + } }) } @@ -191,14 +193,22 @@ export namespace Empty { } } + if (opts.emitCollections === true) { + for (const [key, value] of Object.entries(obj)) { + if (Array.isArray(value) || value instanceof Map) { + yield { + field: key, + value + } + } + } + } }) } return _codec } - - export type EmptyStreamEvent = {} export type EmptyStreamCollectionsEvent = {} diff --git a/packages/protons/test/fixtures/bitswap.ts b/packages/protons/test/fixtures/bitswap.ts index 1ea8f38..b6aa20b 100644 --- a/packages/protons/test/fixtures/bitswap.ts +++ b/packages/protons/test/fixtures/bitswap.ts @@ -1,10 +1,4 @@ -/* eslint-disable import/export */ /* eslint-disable complexity */ -/* eslint-disable @typescript-eslint/no-namespace */ -/* eslint-disable @typescript-eslint/no-unnecessary-boolean-literal-compare */ -/* eslint-disable @typescript-eslint/no-empty-interface */ -/* eslint-disable import/consistent-type-specifier-style */ -/* eslint-disable @typescript-eslint/no-unused-vars */ import { decodeMessage, encodeMessage, enumeration, MaxLengthError, message, streamMessage } from 'protons-runtime' import { alloc as uint8ArrayAlloc } from 'uint8arrays/alloc' @@ -135,11 +129,11 @@ export namespace Message { if (opts.emitCollections === true) { obj = { - block: uint8ArrayAlloc(0), - priority: 0, - wantType: WantType.Block, - sendDontHave: false - } + block: uint8ArrayAlloc(0), + priority: 0, + wantType: WantType.Block, + sendDontHave: false + } } else { obj = {} } @@ -192,6 +186,16 @@ export namespace Message { } } + if (opts.emitCollections === true) { + for (const [key, value] of Object.entries(obj)) { + if (Array.isArray(value) || value instanceof Map) { + yield { + field: key, + value + } + } + } + } }) } @@ -304,11 +308,13 @@ export namespace Message { if (opts.emitCollections === true) { obj = { - entries: [], - full: false - } + entries: [], + full: false + } } else { - obj = {} + obj = { + entries: 0 + } } const end = length == null ? reader.len : reader.pos + length @@ -318,17 +324,26 @@ export namespace Message { switch (tag >>> 3) { case 1: { - if (opts.limits?.entries != null && obj.entries.length === opts.limits.entries) { + if (opts.limits?.entries != null && (opts.emitCollections === true ? obj.entries.length === opts.limits.entries : obj.entries === opts.limits.entries)) { throw new MaxLengthError('Decode error - map field "entries" had too many elements') } + const value = Message.Wantlist.Entry.codec().decode(reader, reader.uint32(), { + limits: opts.limits?.entries$ + }) + yield { field: 'entries$value', - index: 0, - value: Message.Wantlist.Entry.codec().decode(reader, reader.uint32(), { - limits: opts.limits?.entries$ - }) + index: opts.emitCollections === true ? obj.entries.length : obj.entries, + value + } + + if (opts.emitCollections === true) { + obj.entries.push(value) + } else { + obj.entries++ } + break } case 2: { @@ -345,6 +360,16 @@ export namespace Message { } } + if (opts.emitCollections === true) { + for (const [key, value] of Object.entries(obj)) { + if (Array.isArray(value) || value instanceof Map) { + yield { + field: key, + value + } + } + } + } }) } @@ -446,9 +471,9 @@ export namespace Message { if (opts.emitCollections === true) { obj = { - prefix: uint8ArrayAlloc(0), - data: uint8ArrayAlloc(0) - } + prefix: uint8ArrayAlloc(0), + data: uint8ArrayAlloc(0) + } } else { obj = {} } @@ -480,6 +505,16 @@ export namespace Message { } } + if (opts.emitCollections === true) { + for (const [key, value] of Object.entries(obj)) { + if (Array.isArray(value) || value instanceof Map) { + yield { + field: key, + value + } + } + } + } }) } @@ -591,9 +626,9 @@ export namespace Message { if (opts.emitCollections === true) { obj = { - cid: uint8ArrayAlloc(0), - type: BlockPresenceType.Have - } + cid: uint8ArrayAlloc(0), + type: BlockPresenceType.Have + } } else { obj = {} } @@ -625,6 +660,16 @@ export namespace Message { } } + if (opts.emitCollections === true) { + for (const [key, value] of Object.entries(obj)) { + if (Array.isArray(value) || value instanceof Map) { + yield { + field: key, + value + } + } + } + } }) } @@ -767,13 +812,17 @@ export namespace Message { if (opts.emitCollections === true) { obj = { - blocks: [], - payload: [], - blockPresences: [], - pendingBytes: 0 - } + blocks: [], + payload: [], + blockPresences: [], + pendingBytes: 0 + } } else { - obj = {} + obj = { + blocks: 0, + payload: 0, + blockPresences: 0 + } } const end = length == null ? reader.len : reader.pos + length @@ -792,43 +841,70 @@ export namespace Message { break } case 2: { - if (opts.limits?.blocks != null && obj.blocks.length === opts.limits.blocks) { + if (opts.limits?.blocks != null && (opts.emitCollections === true ? obj.blocks.length === opts.limits.blocks : obj.blocks === opts.limits.blocks)) { throw new MaxLengthError('Decode error - map field "blocks" had too many elements') } + const value = reader.bytes() + yield { field: 'blocks$value', - index: 0, - value: reader.bytes() + index: opts.emitCollections === true ? obj.blocks.length : obj.blocks, + value + } + + if (opts.emitCollections === true) { + obj.blocks.push(value) + } else { + obj.blocks++ } + break } case 3: { - if (opts.limits?.payload != null && obj.payload.length === opts.limits.payload) { + if (opts.limits?.payload != null && (opts.emitCollections === true ? obj.payload.length === opts.limits.payload : obj.payload === opts.limits.payload)) { throw new MaxLengthError('Decode error - map field "payload" had too many elements') } + const value = Message.Block.codec().decode(reader, reader.uint32(), { + limits: opts.limits?.payload$ + }) + yield { field: 'payload$value', - index: 0, - value: Message.Block.codec().decode(reader, reader.uint32(), { - limits: opts.limits?.payload$ - }) + index: opts.emitCollections === true ? obj.payload.length : obj.payload, + value + } + + if (opts.emitCollections === true) { + obj.payload.push(value) + } else { + obj.payload++ } + break } case 4: { - if (opts.limits?.blockPresences != null && obj.blockPresences.length === opts.limits.blockPresences) { + if (opts.limits?.blockPresences != null && (opts.emitCollections === true ? obj.blockPresences.length === opts.limits.blockPresences : obj.blockPresences === opts.limits.blockPresences)) { throw new MaxLengthError('Decode error - map field "blockPresences" had too many elements') } + const value = Message.BlockPresence.codec().decode(reader, reader.uint32(), { + limits: opts.limits?.blockPresences$ + }) + yield { field: 'blockPresences$value', - index: 0, - value: Message.BlockPresence.codec().decode(reader, reader.uint32(), { - limits: opts.limits?.blockPresences$ - }) + index: opts.emitCollections === true ? obj.blockPresences.length : obj.blockPresences, + value + } + + if (opts.emitCollections === true) { + obj.blockPresences.push(value) + } else { + obj.blockPresences++ } + break } case 5: { @@ -845,6 +921,16 @@ export namespace Message { } } + if (opts.emitCollections === true) { + for (const [key, value] of Object.entries(obj)) { + if (Array.isArray(value) || value instanceof Map) { + yield { + field: key, + value + } + } + } + } }) } diff --git a/packages/protons/test/fixtures/circuit.ts b/packages/protons/test/fixtures/circuit.ts index ed9a801..e1eedd8 100644 --- a/packages/protons/test/fixtures/circuit.ts +++ b/packages/protons/test/fixtures/circuit.ts @@ -1,11 +1,3 @@ -/* eslint-disable import/export */ -/* eslint-disable complexity */ -/* eslint-disable @typescript-eslint/no-namespace */ -/* eslint-disable @typescript-eslint/no-unnecessary-boolean-literal-compare */ -/* eslint-disable @typescript-eslint/no-empty-interface */ -/* eslint-disable import/consistent-type-specifier-style */ -/* eslint-disable @typescript-eslint/no-unused-vars */ - import { decodeMessage, encodeMessage, enumeration, MaxLengthError, message, streamMessage } from 'protons-runtime' import { alloc as uint8ArrayAlloc } from 'uint8arrays/alloc' import type { Codec, DecodeOptions, StreamingDecodeOptions, StreamingDecodeWithCollectionsOptions } from 'protons-runtime' @@ -150,11 +142,13 @@ export namespace CircuitRelay { if (opts.emitCollections === true) { obj = { - id: uint8ArrayAlloc(0), - addrs: [] - } + id: uint8ArrayAlloc(0), + addrs: [] + } } else { - obj = {} + obj = { + addrs: 0 + } } const end = length == null ? reader.len : reader.pos + length @@ -171,15 +165,24 @@ export namespace CircuitRelay { break } case 2: { - if (opts.limits?.addrs != null && obj.addrs.length === opts.limits.addrs) { + if (opts.limits?.addrs != null && (opts.emitCollections === true ? obj.addrs.length === opts.limits.addrs : obj.addrs === opts.limits.addrs)) { throw new MaxLengthError('Decode error - map field "addrs" had too many elements') } + const value = reader.bytes() + yield { field: 'addrs$value', - index: 0, - value: reader.bytes() + index: opts.emitCollections === true ? obj.addrs.length : obj.addrs, + value } + + if (opts.emitCollections === true) { + obj.addrs.push(value) + } else { + obj.addrs++ + } + break } default: { @@ -189,6 +192,16 @@ export namespace CircuitRelay { } } + if (opts.emitCollections === true) { + for (const [key, value] of Object.entries(obj)) { + if (Array.isArray(value) || value instanceof Map) { + yield { + field: key, + value + } + } + } + } }) } @@ -352,6 +365,16 @@ export namespace CircuitRelay { } } + if (opts.emitCollections === true) { + for (const [key, value] of Object.entries(obj)) { + if (Array.isArray(value) || value instanceof Map) { + yield { + field: key, + value + } + } + } + } }) } diff --git a/packages/protons/test/fixtures/custom-option-jstype.ts b/packages/protons/test/fixtures/custom-option-jstype.ts index 58d3a4b..ae8ff9c 100644 --- a/packages/protons/test/fixtures/custom-option-jstype.ts +++ b/packages/protons/test/fixtures/custom-option-jstype.ts @@ -1,11 +1,3 @@ -/* eslint-disable import/export */ -/* eslint-disable complexity */ -/* eslint-disable @typescript-eslint/no-namespace */ -/* eslint-disable @typescript-eslint/no-unnecessary-boolean-literal-compare */ -/* eslint-disable @typescript-eslint/no-empty-interface */ -/* eslint-disable import/consistent-type-specifier-style */ -/* eslint-disable @typescript-eslint/no-unused-vars */ - import { decodeMessage, encodeMessage, message, streamMessage } from 'protons-runtime' import type { Codec, DecodeOptions, StreamingDecodeOptions, StreamingDecodeWithCollectionsOptions } from 'protons-runtime' import type { Uint8ArrayList } from 'uint8arraylist' @@ -115,13 +107,13 @@ export namespace CustomOptionNumber { if (opts.emitCollections === true) { obj = { - num: 0, - i64: 0, - ui64: 0, - si64: 0, - f64: 0, - sf64: 0 - } + num: 0, + i64: 0, + ui64: 0, + si64: 0, + f64: 0, + sf64: 0 + } } else { obj = {} } @@ -181,6 +173,16 @@ export namespace CustomOptionNumber { } } + if (opts.emitCollections === true) { + for (const [key, value] of Object.entries(obj)) { + if (Array.isArray(value) || value instanceof Map) { + yield { + field: key, + value + } + } + } + } }) } @@ -340,13 +342,13 @@ export namespace CustomOptionString { if (opts.emitCollections === true) { obj = { - num: 0, - i64: '', - ui64: '', - si64: '', - f64: '', - sf64: '' - } + num: 0, + i64: '', + ui64: '', + si64: '', + f64: '', + sf64: '' + } } else { obj = {} } @@ -406,6 +408,16 @@ export namespace CustomOptionString { } } + if (opts.emitCollections === true) { + for (const [key, value] of Object.entries(obj)) { + if (Array.isArray(value) || value instanceof Map) { + yield { + field: key, + value + } + } + } + } }) } diff --git a/packages/protons/test/fixtures/daemon.ts b/packages/protons/test/fixtures/daemon.ts index df02ed5..a67d442 100644 --- a/packages/protons/test/fixtures/daemon.ts +++ b/packages/protons/test/fixtures/daemon.ts @@ -1,10 +1,4 @@ -/* eslint-disable import/export */ /* eslint-disable complexity */ -/* eslint-disable @typescript-eslint/no-namespace */ -/* eslint-disable @typescript-eslint/no-unnecessary-boolean-literal-compare */ -/* eslint-disable @typescript-eslint/no-empty-interface */ -/* eslint-disable import/consistent-type-specifier-style */ -/* eslint-disable @typescript-eslint/no-unused-vars */ import { decodeMessage, encodeMessage, enumeration, MaxLengthError, message, streamMessage } from 'protons-runtime' import { alloc as uint8ArrayAlloc } from 'uint8arrays/alloc' @@ -189,8 +183,8 @@ export namespace Request { if (opts.emitCollections === true) { obj = { - type: Type.IDENTIFY - } + type: Type.IDENTIFY + } } else { obj = {} } @@ -287,6 +281,16 @@ export namespace Request { } } + if (opts.emitCollections === true) { + for (const [key, value] of Object.entries(obj)) { + if (Array.isArray(value) || value instanceof Map) { + yield { + field: key, + value + } + } + } + } }) } @@ -513,11 +517,13 @@ export namespace Response { if (opts.emitCollections === true) { obj = { - type: Type.OK, - peers: [] - } + type: Type.OK, + peers: [] + } } else { - obj = {} + obj = { + peers: 0 + } } const end = length == null ? reader.len : reader.pos + length @@ -570,17 +576,26 @@ export namespace Response { break } case 6: { - if (opts.limits?.peers != null && obj.peers.length === opts.limits.peers) { + if (opts.limits?.peers != null && (opts.emitCollections === true ? obj.peers.length === opts.limits.peers : obj.peers === opts.limits.peers)) { throw new MaxLengthError('Decode error - map field "peers" had too many elements') } + const value = PeerInfo.codec().decode(reader, reader.uint32(), { + limits: opts.limits?.peers$ + }) + yield { field: 'peers$value', - index: 0, - value: PeerInfo.codec().decode(reader, reader.uint32(), { - limits: opts.limits?.peers$ - }) + index: opts.emitCollections === true ? obj.peers.length : obj.peers, + value } + + if (opts.emitCollections === true) { + obj.peers.push(value) + } else { + obj.peers++ + } + break } case 7: { @@ -608,6 +623,16 @@ export namespace Response { } } + if (opts.emitCollections === true) { + for (const [key, value] of Object.entries(obj)) { + if (Array.isArray(value) || value instanceof Map) { + yield { + field: key, + value + } + } + } + } }) } @@ -745,11 +770,13 @@ export namespace IdentifyResponse { if (opts.emitCollections === true) { obj = { - id: uint8ArrayAlloc(0), - addrs: [] - } + id: uint8ArrayAlloc(0), + addrs: [] + } } else { - obj = {} + obj = { + addrs: 0 + } } const end = length == null ? reader.len : reader.pos + length @@ -766,15 +793,24 @@ export namespace IdentifyResponse { break } case 2: { - if (opts.limits?.addrs != null && obj.addrs.length === opts.limits.addrs) { + if (opts.limits?.addrs != null && (opts.emitCollections === true ? obj.addrs.length === opts.limits.addrs : obj.addrs === opts.limits.addrs)) { throw new MaxLengthError('Decode error - map field "addrs" had too many elements') } + const value = reader.bytes() + yield { field: 'addrs$value', - index: 0, - value: reader.bytes() + index: opts.emitCollections === true ? obj.addrs.length : obj.addrs, + value + } + + if (opts.emitCollections === true) { + obj.addrs.push(value) + } else { + obj.addrs++ } + break } default: { @@ -784,6 +820,16 @@ export namespace IdentifyResponse { } } + if (opts.emitCollections === true) { + for (const [key, value] of Object.entries(obj)) { + if (Array.isArray(value) || value instanceof Map) { + yield { + field: key, + value + } + } + } + } }) } @@ -901,11 +947,13 @@ export namespace ConnectRequest { if (opts.emitCollections === true) { obj = { - peer: uint8ArrayAlloc(0), - addrs: [] - } + peer: uint8ArrayAlloc(0), + addrs: [] + } } else { - obj = {} + obj = { + addrs: 0 + } } const end = length == null ? reader.len : reader.pos + length @@ -922,15 +970,24 @@ export namespace ConnectRequest { break } case 2: { - if (opts.limits?.addrs != null && obj.addrs.length === opts.limits.addrs) { + if (opts.limits?.addrs != null && (opts.emitCollections === true ? obj.addrs.length === opts.limits.addrs : obj.addrs === opts.limits.addrs)) { throw new MaxLengthError('Decode error - map field "addrs" had too many elements') } + const value = reader.bytes() + yield { field: 'addrs$value', - index: 0, - value: reader.bytes() + index: opts.emitCollections === true ? obj.addrs.length : obj.addrs, + value } + + if (opts.emitCollections === true) { + obj.addrs.push(value) + } else { + obj.addrs++ + } + break } case 3: { @@ -947,6 +1004,16 @@ export namespace ConnectRequest { } } + if (opts.emitCollections === true) { + for (const [key, value] of Object.entries(obj)) { + if (Array.isArray(value) || value instanceof Map) { + yield { + field: key, + value + } + } + } + } }) } @@ -1069,11 +1136,13 @@ export namespace StreamOpenRequest { if (opts.emitCollections === true) { obj = { - peer: uint8ArrayAlloc(0), - proto: [] - } + peer: uint8ArrayAlloc(0), + proto: [] + } } else { - obj = {} + obj = { + proto: 0 + } } const end = length == null ? reader.len : reader.pos + length @@ -1090,15 +1159,24 @@ export namespace StreamOpenRequest { break } case 2: { - if (opts.limits?.proto != null && obj.proto.length === opts.limits.proto) { + if (opts.limits?.proto != null && (opts.emitCollections === true ? obj.proto.length === opts.limits.proto : obj.proto === opts.limits.proto)) { throw new MaxLengthError('Decode error - map field "proto" had too many elements') } + const value = reader.string() + yield { field: 'proto$value', - index: 0, - value: reader.string() + index: opts.emitCollections === true ? obj.proto.length : obj.proto, + value + } + + if (opts.emitCollections === true) { + obj.proto.push(value) + } else { + obj.proto++ } + break } case 3: { @@ -1115,6 +1193,16 @@ export namespace StreamOpenRequest { } } + if (opts.emitCollections === true) { + for (const [key, value] of Object.entries(obj)) { + if (Array.isArray(value) || value instanceof Map) { + yield { + field: key, + value + } + } + } + } }) } @@ -1227,11 +1315,13 @@ export namespace StreamHandlerRequest { if (opts.emitCollections === true) { obj = { - addr: uint8ArrayAlloc(0), - proto: [] - } + addr: uint8ArrayAlloc(0), + proto: [] + } } else { - obj = {} + obj = { + proto: 0 + } } const end = length == null ? reader.len : reader.pos + length @@ -1248,15 +1338,24 @@ export namespace StreamHandlerRequest { break } case 2: { - if (opts.limits?.proto != null && obj.proto.length === opts.limits.proto) { + if (opts.limits?.proto != null && (opts.emitCollections === true ? obj.proto.length === opts.limits.proto : obj.proto === opts.limits.proto)) { throw new MaxLengthError('Decode error - map field "proto" had too many elements') } + const value = reader.string() + yield { field: 'proto$value', - index: 0, - value: reader.string() + index: opts.emitCollections === true ? obj.proto.length : obj.proto, + value } + + if (opts.emitCollections === true) { + obj.proto.push(value) + } else { + obj.proto++ + } + break } default: { @@ -1266,6 +1365,16 @@ export namespace StreamHandlerRequest { } } + if (opts.emitCollections === true) { + for (const [key, value] of Object.entries(obj)) { + if (Array.isArray(value) || value instanceof Map) { + yield { + field: key, + value + } + } + } + } }) } @@ -1356,8 +1465,8 @@ export namespace ErrorResponse { if (opts.emitCollections === true) { obj = { - msg: '' - } + msg: '' + } } else { obj = {} } @@ -1382,6 +1491,16 @@ export namespace ErrorResponse { } } + if (opts.emitCollections === true) { + for (const [key, value] of Object.entries(obj)) { + if (Array.isArray(value) || value instanceof Map) { + yield { + field: key, + value + } + } + } + } }) } @@ -1483,10 +1602,10 @@ export namespace StreamInfo { if (opts.emitCollections === true) { obj = { - peer: uint8ArrayAlloc(0), - addr: uint8ArrayAlloc(0), - proto: '' - } + peer: uint8ArrayAlloc(0), + addr: uint8ArrayAlloc(0), + proto: '' + } } else { obj = {} } @@ -1525,6 +1644,16 @@ export namespace StreamInfo { } } + if (opts.emitCollections === true) { + for (const [key, value] of Object.entries(obj)) { + if (Array.isArray(value) || value instanceof Map) { + yield { + field: key, + value + } + } + } + } }) } @@ -1704,8 +1833,8 @@ export namespace DHTRequest { if (opts.emitCollections === true) { obj = { - type: Type.FIND_PEER - } + type: Type.FIND_PEER + } } else { obj = {} } @@ -1772,6 +1901,16 @@ export namespace DHTRequest { } } + if (opts.emitCollections === true) { + for (const [key, value] of Object.entries(obj)) { + if (Array.isArray(value) || value instanceof Map) { + yield { + field: key, + value + } + } + } + } }) } @@ -1921,8 +2060,8 @@ export namespace DHTResponse { if (opts.emitCollections === true) { obj = { - type: Type.BEGIN - } + type: Type.BEGIN + } } else { obj = {} } @@ -1963,6 +2102,16 @@ export namespace DHTResponse { } } + if (opts.emitCollections === true) { + for (const [key, value] of Object.entries(obj)) { + if (Array.isArray(value) || value instanceof Map) { + yield { + field: key, + value + } + } + } + } }) } @@ -2069,11 +2218,13 @@ export namespace PeerInfo { if (opts.emitCollections === true) { obj = { - id: uint8ArrayAlloc(0), - addrs: [] - } + id: uint8ArrayAlloc(0), + addrs: [] + } } else { - obj = {} + obj = { + addrs: 0 + } } const end = length == null ? reader.len : reader.pos + length @@ -2090,15 +2241,24 @@ export namespace PeerInfo { break } case 2: { - if (opts.limits?.addrs != null && obj.addrs.length === opts.limits.addrs) { + if (opts.limits?.addrs != null && (opts.emitCollections === true ? obj.addrs.length === opts.limits.addrs : obj.addrs === opts.limits.addrs)) { throw new MaxLengthError('Decode error - map field "addrs" had too many elements') } + const value = reader.bytes() + yield { field: 'addrs$value', - index: 0, - value: reader.bytes() + index: opts.emitCollections === true ? obj.addrs.length : obj.addrs, + value } + + if (opts.emitCollections === true) { + obj.addrs.push(value) + } else { + obj.addrs++ + } + break } default: { @@ -2108,6 +2268,16 @@ export namespace PeerInfo { } } + if (opts.emitCollections === true) { + for (const [key, value] of Object.entries(obj)) { + if (Array.isArray(value) || value instanceof Map) { + yield { + field: key, + value + } + } + } + } }) } @@ -2246,8 +2416,8 @@ export namespace ConnManagerRequest { if (opts.emitCollections === true) { obj = { - type: Type.TAG_PEER - } + type: Type.TAG_PEER + } } else { obj = {} } @@ -2293,6 +2463,16 @@ export namespace ConnManagerRequest { } } + if (opts.emitCollections === true) { + for (const [key, value] of Object.entries(obj)) { + if (Array.isArray(value) || value instanceof Map) { + yield { + field: key, + value + } + } + } + } }) } @@ -2387,8 +2567,8 @@ export namespace DisconnectRequest { if (opts.emitCollections === true) { obj = { - peer: uint8ArrayAlloc(0) - } + peer: uint8ArrayAlloc(0) + } } else { obj = {} } @@ -2413,6 +2593,16 @@ export namespace DisconnectRequest { } } + if (opts.emitCollections === true) { + for (const [key, value] of Object.entries(obj)) { + if (Array.isArray(value) || value instanceof Map) { + yield { + field: key, + value + } + } + } + } }) } @@ -2532,8 +2722,8 @@ export namespace PSRequest { if (opts.emitCollections === true) { obj = { - type: Type.GET_TOPICS - } + type: Type.GET_TOPICS + } } else { obj = {} } @@ -2572,6 +2762,16 @@ export namespace PSRequest { } } + if (opts.emitCollections === true) { + for (const [key, value] of Object.entries(obj)) { + if (Array.isArray(value) || value instanceof Map) { + yield { + field: key, + value + } + } + } + } }) } @@ -2717,10 +2917,12 @@ export namespace PSMessage { if (opts.emitCollections === true) { obj = { - topicIDs: [] - } + topicIDs: [] + } } else { - obj = {} + obj = { + topicIDs: 0 + } } const end = length == null ? reader.len : reader.pos + length @@ -2751,15 +2953,24 @@ export namespace PSMessage { break } case 4: { - if (opts.limits?.topicIDs != null && obj.topicIDs.length === opts.limits.topicIDs) { + if (opts.limits?.topicIDs != null && (opts.emitCollections === true ? obj.topicIDs.length === opts.limits.topicIDs : obj.topicIDs === opts.limits.topicIDs)) { throw new MaxLengthError('Decode error - map field "topicIDs" had too many elements') } + const value = reader.string() + yield { field: 'topicIDs$value', - index: 0, - value: reader.string() + index: opts.emitCollections === true ? obj.topicIDs.length : obj.topicIDs, + value } + + if (opts.emitCollections === true) { + obj.topicIDs.push(value) + } else { + obj.topicIDs++ + } + break } case 5: { @@ -2783,6 +2994,16 @@ export namespace PSMessage { } } + if (opts.emitCollections === true) { + for (const [key, value] of Object.entries(obj)) { + if (Array.isArray(value) || value instanceof Map) { + yield { + field: key, + value + } + } + } + } }) } @@ -2916,11 +3137,14 @@ export namespace PSResponse { if (opts.emitCollections === true) { obj = { - topics: [], - peerIDs: [] - } + topics: [], + peerIDs: [] + } } else { - obj = {} + obj = { + topics: 0, + peerIDs: 0 + } } const end = length == null ? reader.len : reader.pos + length @@ -2930,27 +3154,45 @@ export namespace PSResponse { switch (tag >>> 3) { case 1: { - if (opts.limits?.topics != null && obj.topics.length === opts.limits.topics) { + if (opts.limits?.topics != null && (opts.emitCollections === true ? obj.topics.length === opts.limits.topics : obj.topics === opts.limits.topics)) { throw new MaxLengthError('Decode error - map field "topics" had too many elements') } + const value = reader.string() + yield { field: 'topics$value', - index: 0, - value: reader.string() + index: opts.emitCollections === true ? obj.topics.length : obj.topics, + value + } + + if (opts.emitCollections === true) { + obj.topics.push(value) + } else { + obj.topics++ } + break } case 2: { - if (opts.limits?.peerIDs != null && obj.peerIDs.length === opts.limits.peerIDs) { + if (opts.limits?.peerIDs != null && (opts.emitCollections === true ? obj.peerIDs.length === opts.limits.peerIDs : obj.peerIDs === opts.limits.peerIDs)) { throw new MaxLengthError('Decode error - map field "peerIDs" had too many elements') } + const value = reader.bytes() + yield { field: 'peerIDs$value', - index: 0, - value: reader.bytes() + index: opts.emitCollections === true ? obj.peerIDs.length : obj.peerIDs, + value } + + if (opts.emitCollections === true) { + obj.peerIDs.push(value) + } else { + obj.peerIDs++ + } + break } default: { @@ -2960,6 +3202,16 @@ export namespace PSResponse { } } + if (opts.emitCollections === true) { + for (const [key, value] of Object.entries(obj)) { + if (Array.isArray(value) || value instanceof Map) { + yield { + field: key, + value + } + } + } + } }) } @@ -3101,11 +3353,13 @@ export namespace PeerstoreRequest { if (opts.emitCollections === true) { obj = { - type: Type.INVALID, - protos: [] - } + type: Type.INVALID, + protos: [] + } } else { - obj = {} + obj = { + protos: 0 + } } const end = length == null ? reader.len : reader.pos + length @@ -3129,15 +3383,24 @@ export namespace PeerstoreRequest { break } case 3: { - if (opts.limits?.protos != null && obj.protos.length === opts.limits.protos) { + if (opts.limits?.protos != null && (opts.emitCollections === true ? obj.protos.length === opts.limits.protos : obj.protos === opts.limits.protos)) { throw new MaxLengthError('Decode error - map field "protos" had too many elements') } + const value = reader.string() + yield { field: 'protos$value', - index: 0, - value: reader.string() + index: opts.emitCollections === true ? obj.protos.length : obj.protos, + value + } + + if (opts.emitCollections === true) { + obj.protos.push(value) + } else { + obj.protos++ } + break } default: { @@ -3147,6 +3410,16 @@ export namespace PeerstoreRequest { } } + if (opts.emitCollections === true) { + for (const [key, value] of Object.entries(obj)) { + if (Array.isArray(value) || value instanceof Map) { + yield { + field: key, + value + } + } + } + } }) } @@ -3260,10 +3533,12 @@ export namespace PeerstoreResponse { if (opts.emitCollections === true) { obj = { - protos: [] - } + protos: [] + } } else { - obj = {} + obj = { + protos: 0 + } } const end = length == null ? reader.len : reader.pos + length @@ -3282,15 +3557,24 @@ export namespace PeerstoreResponse { break } case 2: { - if (opts.limits?.protos != null && obj.protos.length === opts.limits.protos) { + if (opts.limits?.protos != null && (opts.emitCollections === true ? obj.protos.length === opts.limits.protos : obj.protos === opts.limits.protos)) { throw new MaxLengthError('Decode error - map field "protos" had too many elements') } + const value = reader.string() + yield { field: 'protos$value', - index: 0, - value: reader.string() + index: opts.emitCollections === true ? obj.protos.length : obj.protos, + value + } + + if (opts.emitCollections === true) { + obj.protos.push(value) + } else { + obj.protos++ } + break } default: { @@ -3300,6 +3584,16 @@ export namespace PeerstoreResponse { } } + if (opts.emitCollections === true) { + for (const [key, value] of Object.entries(obj)) { + if (Array.isArray(value) || value instanceof Map) { + yield { + field: key, + value + } + } + } + } }) } diff --git a/packages/protons/test/fixtures/dht.ts b/packages/protons/test/fixtures/dht.ts index d9cb584..5d1eeb0 100644 --- a/packages/protons/test/fixtures/dht.ts +++ b/packages/protons/test/fixtures/dht.ts @@ -1,10 +1,4 @@ -/* eslint-disable import/export */ /* eslint-disable complexity */ -/* eslint-disable @typescript-eslint/no-namespace */ -/* eslint-disable @typescript-eslint/no-unnecessary-boolean-literal-compare */ -/* eslint-disable @typescript-eslint/no-empty-interface */ -/* eslint-disable import/consistent-type-specifier-style */ -/* eslint-disable @typescript-eslint/no-unused-vars */ import { decodeMessage, encodeMessage, enumeration, MaxLengthError, message, streamMessage } from 'protons-runtime' import type { Codec, DecodeOptions, StreamingDecodeOptions, StreamingDecodeWithCollectionsOptions } from 'protons-runtime' @@ -150,6 +144,16 @@ export namespace Record { } } + if (opts.emitCollections === true) { + for (const [key, value] of Object.entries(obj)) { + if (Array.isArray(value) || value instanceof Map) { + yield { + field: key, + value + } + } + } + } }) } @@ -329,10 +333,12 @@ export namespace Message { if (opts.emitCollections === true) { obj = { - addrs: [] - } + addrs: [] + } } else { - obj = {} + obj = { + addrs: 0 + } } const end = length == null ? reader.len : reader.pos + length @@ -349,15 +355,24 @@ export namespace Message { break } case 2: { - if (opts.limits?.addrs != null && obj.addrs.length === opts.limits.addrs) { + if (opts.limits?.addrs != null && (opts.emitCollections === true ? obj.addrs.length === opts.limits.addrs : obj.addrs === opts.limits.addrs)) { throw new MaxLengthError('Decode error - map field "addrs" had too many elements') } + const value = reader.bytes() + yield { field: 'addrs$value', - index: 0, - value: reader.bytes() + index: opts.emitCollections === true ? obj.addrs.length : obj.addrs, + value + } + + if (opts.emitCollections === true) { + obj.addrs.push(value) + } else { + obj.addrs++ } + break } case 3: { @@ -374,6 +389,16 @@ export namespace Message { } } + if (opts.emitCollections === true) { + for (const [key, value] of Object.entries(obj)) { + if (Array.isArray(value) || value instanceof Map) { + yield { + field: key, + value + } + } + } + } }) } @@ -526,11 +551,14 @@ export namespace Message { if (opts.emitCollections === true) { obj = { - closerPeers: [], - providerPeers: [] - } + closerPeers: [], + providerPeers: [] + } } else { - obj = {} + obj = { + closerPeers: 0, + providerPeers: 0 + } } const end = length == null ? reader.len : reader.pos + length @@ -568,31 +596,49 @@ export namespace Message { break } case 8: { - if (opts.limits?.closerPeers != null && obj.closerPeers.length === opts.limits.closerPeers) { + if (opts.limits?.closerPeers != null && (opts.emitCollections === true ? obj.closerPeers.length === opts.limits.closerPeers : obj.closerPeers === opts.limits.closerPeers)) { throw new MaxLengthError('Decode error - map field "closerPeers" had too many elements') } + const value = Message.Peer.codec().decode(reader, reader.uint32(), { + limits: opts.limits?.closerPeers$ + }) + yield { field: 'closerPeers$value', - index: 0, - value: Message.Peer.codec().decode(reader, reader.uint32(), { - limits: opts.limits?.closerPeers$ - }) + index: opts.emitCollections === true ? obj.closerPeers.length : obj.closerPeers, + value } + + if (opts.emitCollections === true) { + obj.closerPeers.push(value) + } else { + obj.closerPeers++ + } + break } case 9: { - if (opts.limits?.providerPeers != null && obj.providerPeers.length === opts.limits.providerPeers) { + if (opts.limits?.providerPeers != null && (opts.emitCollections === true ? obj.providerPeers.length === opts.limits.providerPeers : obj.providerPeers === opts.limits.providerPeers)) { throw new MaxLengthError('Decode error - map field "providerPeers" had too many elements') } + const value = Message.Peer.codec().decode(reader, reader.uint32(), { + limits: opts.limits?.providerPeers$ + }) + yield { field: 'providerPeers$value', - index: 0, - value: Message.Peer.codec().decode(reader, reader.uint32(), { - limits: opts.limits?.providerPeers$ - }) + index: opts.emitCollections === true ? obj.providerPeers.length : obj.providerPeers, + value } + + if (opts.emitCollections === true) { + obj.providerPeers.push(value) + } else { + obj.providerPeers++ + } + break } default: { @@ -602,6 +648,16 @@ export namespace Message { } } + if (opts.emitCollections === true) { + for (const [key, value] of Object.entries(obj)) { + if (Array.isArray(value) || value instanceof Map) { + yield { + field: key, + value + } + } + } + } }) } diff --git a/packages/protons/test/fixtures/maps.ts b/packages/protons/test/fixtures/maps.ts index f742b90..04c7f2a 100644 --- a/packages/protons/test/fixtures/maps.ts +++ b/packages/protons/test/fixtures/maps.ts @@ -1,10 +1,4 @@ -/* eslint-disable import/export */ /* eslint-disable complexity */ -/* eslint-disable @typescript-eslint/no-namespace */ -/* eslint-disable @typescript-eslint/no-unnecessary-boolean-literal-compare */ -/* eslint-disable @typescript-eslint/no-empty-interface */ -/* eslint-disable import/consistent-type-specifier-style */ -/* eslint-disable @typescript-eslint/no-unused-vars */ import { decodeMessage, encodeMessage, enumeration, MaxLengthError, MaxSizeError, message, streamMessage } from 'protons-runtime' import type { Codec, DecodeOptions, StreamingDecodeOptions, StreamingDecodeWithCollectionsOptions } from 'protons-runtime' @@ -95,11 +89,13 @@ export namespace SubMessage { if (opts.emitCollections === true) { obj = { - foo: '', - bar: [] - } + foo: '', + bar: [] + } } else { - obj = {} + obj = { + bar: 0 + } } const end = length == null ? reader.len : reader.pos + length @@ -116,15 +112,24 @@ export namespace SubMessage { break } case 2: { - if (opts.limits?.bar != null && obj.bar.length === opts.limits.bar) { + if (opts.limits?.bar != null && (opts.emitCollections === true ? obj.bar.length === opts.limits.bar : obj.bar === opts.limits.bar)) { throw new MaxLengthError('Decode error - map field "bar" had too many elements') } + const value = reader.uint32() + yield { field: 'bar$value', - index: 0, - value: reader.uint32() + index: opts.emitCollections === true ? obj.bar.length : obj.bar, + value + } + + if (opts.emitCollections === true) { + obj.bar.push(value) + } else { + obj.bar++ } + break } default: { @@ -134,6 +139,16 @@ export namespace SubMessage { } } + if (opts.emitCollections === true) { + for (const [key, value] of Object.entries(obj)) { + if (Array.isArray(value) || value instanceof Map) { + yield { + field: key, + value + } + } + } + } }) } @@ -244,9 +259,9 @@ export namespace MapTypes { if (opts.emitCollections === true) { obj = { - key: '', - value: '' - } + key: '', + value: '' + } } else { obj = {} } @@ -278,6 +293,16 @@ export namespace MapTypes { } } + if (opts.emitCollections === true) { + for (const [key, value] of Object.entries(obj)) { + if (Array.isArray(value) || value instanceof Map) { + yield { + field: key, + value + } + } + } + } }) } @@ -373,9 +398,9 @@ export namespace MapTypes { if (opts.emitCollections === true) { obj = { - key: 0, - value: 0 - } + key: 0, + value: 0 + } } else { obj = {} } @@ -407,6 +432,16 @@ export namespace MapTypes { } } + if (opts.emitCollections === true) { + for (const [key, value] of Object.entries(obj)) { + if (Array.isArray(value) || value instanceof Map) { + yield { + field: key, + value + } + } + } + } }) } @@ -502,9 +537,9 @@ export namespace MapTypes { if (opts.emitCollections === true) { obj = { - key: false, - value: false - } + key: false, + value: false + } } else { obj = {} } @@ -536,6 +571,16 @@ export namespace MapTypes { } } + if (opts.emitCollections === true) { + for (const [key, value] of Object.entries(obj)) { + if (Array.isArray(value) || value instanceof Map) { + yield { + field: key, + value + } + } + } + } }) } @@ -632,8 +677,8 @@ export namespace MapTypes { if (opts.emitCollections === true) { obj = { - key: '' - } + key: '' + } } else { obj = {} } @@ -667,6 +712,16 @@ export namespace MapTypes { } } + if (opts.emitCollections === true) { + for (const [key, value] of Object.entries(obj)) { + if (Array.isArray(value) || value instanceof Map) { + yield { + field: key, + value + } + } + } + } }) } @@ -762,9 +817,9 @@ export namespace MapTypes { if (opts.emitCollections === true) { obj = { - key: '', - value: EnumValue.NO_VALUE - } + key: '', + value: EnumValue.NO_VALUE + } } else { obj = {} } @@ -796,6 +851,16 @@ export namespace MapTypes { } } + if (opts.emitCollections === true) { + for (const [key, value] of Object.entries(obj)) { + if (Array.isArray(value) || value instanceof Map) { + yield { + field: key, + value + } + } + } + } }) } @@ -954,14 +1019,20 @@ export namespace MapTypes { if (opts.emitCollections === true) { obj = { - stringMap: new Map(), - intMap: new Map(), - boolMap: new Map(), - messageMap: new Map(), - enumMap: new Map() - } + stringMap: new Map(), + intMap: new Map(), + boolMap: new Map(), + messageMap: new Map(), + enumMap: new Map() + } } else { - obj = {} + obj = { + stringMap: 0, + intMap: 0, + boolMap: 0, + messageMap: 0, + enumMap: 0 + } } const end = length == null ? reader.len : reader.pos + length @@ -971,7 +1042,7 @@ export namespace MapTypes { switch (tag >>> 3) { case 1: { - if (opts.limits?.stringMap != null && obj.stringMap.size === opts.limits.stringMap) { + if (opts.limits?.stringMap != null && (opts.emitCollections === true ? obj.stringMap.size === opts.limits.stringMap : obj.stringMap === opts.limits.stringMap)) { throw new MaxSizeError('Decode error - map field "stringMap" had too many elements') } @@ -982,10 +1053,17 @@ export namespace MapTypes { key: entry.key, value: entry.value } + + if (opts.emitCollections === true) { + obj.stringMap.set(entry.key, entry.value) + } else { + obj.stringMap++ + } + break } case 2: { - if (opts.limits?.intMap != null && obj.intMap.size === opts.limits.intMap) { + if (opts.limits?.intMap != null && (opts.emitCollections === true ? obj.intMap.size === opts.limits.intMap : obj.intMap === opts.limits.intMap)) { throw new MaxSizeError('Decode error - map field "intMap" had too many elements') } @@ -996,10 +1074,17 @@ export namespace MapTypes { key: entry.key, value: entry.value } + + if (opts.emitCollections === true) { + obj.intMap.set(entry.key, entry.value) + } else { + obj.intMap++ + } + break } case 3: { - if (opts.limits?.boolMap != null && obj.boolMap.size === opts.limits.boolMap) { + if (opts.limits?.boolMap != null && (opts.emitCollections === true ? obj.boolMap.size === opts.limits.boolMap : obj.boolMap === opts.limits.boolMap)) { throw new MaxSizeError('Decode error - map field "boolMap" had too many elements') } @@ -1010,28 +1095,42 @@ export namespace MapTypes { key: entry.key, value: entry.value } + + if (opts.emitCollections === true) { + obj.boolMap.set(entry.key, entry.value) + } else { + obj.boolMap++ + } + break } case 4: { - if (opts.limits?.messageMap != null && obj.messageMap.size === opts.limits.messageMap) { + if (opts.limits?.messageMap != null && (opts.emitCollections === true ? obj.messageMap.size === opts.limits.messageMap : obj.messageMap === opts.limits.messageMap)) { throw new MaxSizeError('Decode error - map field "messageMap" had too many elements') } const entry = MapTypes.MapTypes$messageMapEntry.codec().decode(reader, reader.uint32(), { - limits: { - value: opts.limits?.messageMap$value - } - }) + limits: { + value: opts.limits?.messageMap$value + } + }) yield { field: 'messageMap', key: entry.key, value: entry.value } + + if (opts.emitCollections === true) { + obj.messageMap.set(entry.key, entry.value) + } else { + obj.messageMap++ + } + break } case 5: { - if (opts.limits?.enumMap != null && obj.enumMap.size === opts.limits.enumMap) { + if (opts.limits?.enumMap != null && (opts.emitCollections === true ? obj.enumMap.size === opts.limits.enumMap : obj.enumMap === opts.limits.enumMap)) { throw new MaxSizeError('Decode error - map field "enumMap" had too many elements') } @@ -1042,6 +1141,13 @@ export namespace MapTypes { key: entry.key, value: entry.value } + + if (opts.emitCollections === true) { + obj.enumMap.set(entry.key, entry.value) + } else { + obj.enumMap++ + } + break } default: { @@ -1051,6 +1157,16 @@ export namespace MapTypes { } } + if (opts.emitCollections === true) { + for (const [key, value] of Object.entries(obj)) { + if (Array.isArray(value) || value instanceof Map) { + yield { + field: key, + value + } + } + } + } }) } diff --git a/packages/protons/test/fixtures/noise.ts b/packages/protons/test/fixtures/noise.ts index 130dabb..e5cb241 100644 --- a/packages/protons/test/fixtures/noise.ts +++ b/packages/protons/test/fixtures/noise.ts @@ -1,11 +1,3 @@ -/* eslint-disable import/export */ -/* eslint-disable complexity */ -/* eslint-disable @typescript-eslint/no-namespace */ -/* eslint-disable @typescript-eslint/no-unnecessary-boolean-literal-compare */ -/* eslint-disable @typescript-eslint/no-empty-interface */ -/* eslint-disable import/consistent-type-specifier-style */ -/* eslint-disable @typescript-eslint/no-unused-vars */ - import { decodeMessage, encodeMessage, message, streamMessage } from 'protons-runtime' import { alloc as uint8ArrayAlloc } from 'uint8arrays/alloc' import type { Codec, DecodeOptions, StreamingDecodeOptions, StreamingDecodeWithCollectionsOptions } from 'protons-runtime' @@ -86,10 +78,10 @@ export namespace pb { if (opts.emitCollections === true) { obj = { - identityKey: uint8ArrayAlloc(0), - identitySig: uint8ArrayAlloc(0), - data: uint8ArrayAlloc(0) - } + identityKey: uint8ArrayAlloc(0), + identitySig: uint8ArrayAlloc(0), + data: uint8ArrayAlloc(0) + } } else { obj = {} } @@ -128,6 +120,16 @@ export namespace pb { } } + if (opts.emitCollections === true) { + for (const [key, value] of Object.entries(obj)) { + if (Array.isArray(value) || value instanceof Map) { + yield { + field: key, + value + } + } + } + } }) } @@ -218,14 +220,22 @@ export namespace pb { } } + if (opts.emitCollections === true) { + for (const [key, value] of Object.entries(obj)) { + if (Array.isArray(value) || value instanceof Map) { + yield { + field: key, + value + } + } + } + } }) } return _codec } - - export type pbStreamEvent = {} export type pbStreamCollectionsEvent = {} diff --git a/packages/protons/test/fixtures/oneof.ts b/packages/protons/test/fixtures/oneof.ts index 98b0415..286ef97 100644 --- a/packages/protons/test/fixtures/oneof.ts +++ b/packages/protons/test/fixtures/oneof.ts @@ -1,11 +1,3 @@ -/* eslint-disable import/export */ -/* eslint-disable complexity */ -/* eslint-disable @typescript-eslint/no-namespace */ -/* eslint-disable @typescript-eslint/no-unnecessary-boolean-literal-compare */ -/* eslint-disable @typescript-eslint/no-empty-interface */ -/* eslint-disable import/consistent-type-specifier-style */ -/* eslint-disable @typescript-eslint/no-unused-vars */ - import { decodeMessage, encodeMessage, enumeration, message, streamMessage } from 'protons-runtime' import type { Codec, DecodeOptions, StreamingDecodeOptions, StreamingDecodeWithCollectionsOptions } from 'protons-runtime' import type { Uint8ArrayList } from 'uint8arraylist' @@ -150,8 +142,8 @@ export namespace OneOfMessage { if (opts.emitCollections === true) { obj = { - fieldFive: '' - } + fieldFive: '' + } } else { obj = {} } @@ -220,6 +212,16 @@ export namespace OneOfMessage { delete obj.fieldFour } + if (opts.emitCollections === true) { + for (const [key, value] of Object.entries(obj)) { + if (Array.isArray(value) || value instanceof Map) { + yield { + field: key, + value + } + } + } + } }) } @@ -363,12 +365,12 @@ export namespace MessageWithoutOneOfs { if (opts.emitCollections === true) { obj = { - fieldOne: '', - fieldTwo: '', - fieldThree: EnumType.Val1, - fieldFour: EnumType.Val1, - fieldFive: '' - } + fieldOne: '', + fieldTwo: '', + fieldThree: EnumType.Val1, + fieldFour: EnumType.Val1, + fieldFive: '' + } } else { obj = {} } @@ -421,6 +423,16 @@ export namespace MessageWithoutOneOfs { } } + if (opts.emitCollections === true) { + for (const [key, value] of Object.entries(obj)) { + if (Array.isArray(value) || value instanceof Map) { + yield { + field: key, + value + } + } + } + } }) } diff --git a/packages/protons/test/fixtures/optional.ts b/packages/protons/test/fixtures/optional.ts index 4b6ccf7..38140ff 100644 --- a/packages/protons/test/fixtures/optional.ts +++ b/packages/protons/test/fixtures/optional.ts @@ -1,10 +1,4 @@ -/* eslint-disable import/export */ /* eslint-disable complexity */ -/* eslint-disable @typescript-eslint/no-namespace */ -/* eslint-disable @typescript-eslint/no-unnecessary-boolean-literal-compare */ -/* eslint-disable @typescript-eslint/no-empty-interface */ -/* eslint-disable import/consistent-type-specifier-style */ -/* eslint-disable @typescript-eslint/no-unused-vars */ import { decodeMessage, encodeMessage, enumeration, message, streamMessage } from 'protons-runtime' import type { Codec, DecodeOptions, StreamingDecodeOptions, StreamingDecodeWithCollectionsOptions } from 'protons-runtime' @@ -117,6 +111,16 @@ export namespace OptionalSubMessage { } } + if (opts.emitCollections === true) { + for (const [key, value] of Object.entries(obj)) { + if (Array.isArray(value) || value instanceof Map) { + yield { + field: key, + value + } + } + } + } }) } @@ -499,6 +503,16 @@ export namespace Optional { } } + if (opts.emitCollections === true) { + for (const [key, value] of Object.entries(obj)) { + if (Array.isArray(value) || value instanceof Map) { + yield { + field: key, + value + } + } + } + } }) } diff --git a/packages/protons/test/fixtures/peer.ts b/packages/protons/test/fixtures/peer.ts index 0df907b..958d45a 100644 --- a/packages/protons/test/fixtures/peer.ts +++ b/packages/protons/test/fixtures/peer.ts @@ -1,10 +1,4 @@ -/* eslint-disable import/export */ /* eslint-disable complexity */ -/* eslint-disable @typescript-eslint/no-namespace */ -/* eslint-disable @typescript-eslint/no-unnecessary-boolean-literal-compare */ -/* eslint-disable @typescript-eslint/no-empty-interface */ -/* eslint-disable import/consistent-type-specifier-style */ -/* eslint-disable @typescript-eslint/no-unused-vars */ import { decodeMessage, encodeMessage, MaxLengthError, message, streamMessage } from 'protons-runtime' import { alloc as uint8ArrayAlloc } from 'uint8arrays/alloc' @@ -125,12 +119,16 @@ export namespace Peer { if (opts.emitCollections === true) { obj = { - addresses: [], - protocols: [], - metadata: [] - } + addresses: [], + protocols: [], + metadata: [] + } } else { - obj = {} + obj = { + addresses: 0, + protocols: 0, + metadata: 0 + } } const end = length == null ? reader.len : reader.pos + length @@ -140,43 +138,70 @@ export namespace Peer { switch (tag >>> 3) { case 1: { - if (opts.limits?.addresses != null && obj.addresses.length === opts.limits.addresses) { + if (opts.limits?.addresses != null && (opts.emitCollections === true ? obj.addresses.length === opts.limits.addresses : obj.addresses === opts.limits.addresses)) { throw new MaxLengthError('Decode error - map field "addresses" had too many elements') } + const value = Address.codec().decode(reader, reader.uint32(), { + limits: opts.limits?.addresses$ + }) + yield { field: 'addresses$value', - index: 0, - value: Address.codec().decode(reader, reader.uint32(), { - limits: opts.limits?.addresses$ - }) + index: opts.emitCollections === true ? obj.addresses.length : obj.addresses, + value + } + + if (opts.emitCollections === true) { + obj.addresses.push(value) + } else { + obj.addresses++ } + break } case 2: { - if (opts.limits?.protocols != null && obj.protocols.length === opts.limits.protocols) { + if (opts.limits?.protocols != null && (opts.emitCollections === true ? obj.protocols.length === opts.limits.protocols : obj.protocols === opts.limits.protocols)) { throw new MaxLengthError('Decode error - map field "protocols" had too many elements') } + const value = reader.string() + yield { field: 'protocols$value', - index: 0, - value: reader.string() + index: opts.emitCollections === true ? obj.protocols.length : obj.protocols, + value } + + if (opts.emitCollections === true) { + obj.protocols.push(value) + } else { + obj.protocols++ + } + break } case 3: { - if (opts.limits?.metadata != null && obj.metadata.length === opts.limits.metadata) { + if (opts.limits?.metadata != null && (opts.emitCollections === true ? obj.metadata.length === opts.limits.metadata : obj.metadata === opts.limits.metadata)) { throw new MaxLengthError('Decode error - map field "metadata" had too many elements') } + const value = Metadata.codec().decode(reader, reader.uint32(), { + limits: opts.limits?.metadata$ + }) + yield { field: 'metadata$value', - index: 0, - value: Metadata.codec().decode(reader, reader.uint32(), { - limits: opts.limits?.metadata$ - }) + index: opts.emitCollections === true ? obj.metadata.length : obj.metadata, + value } + + if (opts.emitCollections === true) { + obj.metadata.push(value) + } else { + obj.metadata++ + } + break } case 4: { @@ -200,6 +225,16 @@ export namespace Peer { } } + if (opts.emitCollections === true) { + for (const [key, value] of Object.entries(obj)) { + if (Array.isArray(value) || value instanceof Map) { + yield { + field: key, + value + } + } + } + } }) } @@ -327,8 +362,8 @@ export namespace Address { if (opts.emitCollections === true) { obj = { - multiaddr: uint8ArrayAlloc(0) - } + multiaddr: uint8ArrayAlloc(0) + } } else { obj = {} } @@ -360,6 +395,16 @@ export namespace Address { } } + if (opts.emitCollections === true) { + for (const [key, value] of Object.entries(obj)) { + if (Array.isArray(value) || value instanceof Map) { + yield { + field: key, + value + } + } + } + } }) } @@ -455,9 +500,9 @@ export namespace Metadata { if (opts.emitCollections === true) { obj = { - key: '', - value: uint8ArrayAlloc(0) - } + key: '', + value: uint8ArrayAlloc(0) + } } else { obj = {} } @@ -489,6 +534,16 @@ export namespace Metadata { } } + if (opts.emitCollections === true) { + for (const [key, value] of Object.entries(obj)) { + if (Array.isArray(value) || value instanceof Map) { + yield { + field: key, + value + } + } + } + } }) } diff --git a/packages/protons/test/fixtures/proto2.ts b/packages/protons/test/fixtures/proto2.ts index 21431d8..a81cf68 100644 --- a/packages/protons/test/fixtures/proto2.ts +++ b/packages/protons/test/fixtures/proto2.ts @@ -1,11 +1,3 @@ -/* eslint-disable import/export */ -/* eslint-disable complexity */ -/* eslint-disable @typescript-eslint/no-namespace */ -/* eslint-disable @typescript-eslint/no-unnecessary-boolean-literal-compare */ -/* eslint-disable @typescript-eslint/no-empty-interface */ -/* eslint-disable import/consistent-type-specifier-style */ -/* eslint-disable @typescript-eslint/no-unused-vars */ - import { decodeMessage, encodeMessage, message, streamMessage } from 'protons-runtime' import type { Codec, DecodeOptions, StreamingDecodeOptions, StreamingDecodeWithCollectionsOptions } from 'protons-runtime' import type { Uint8ArrayList } from 'uint8arraylist' @@ -60,8 +52,8 @@ export namespace MessageWithRequired { if (opts.emitCollections === true) { obj = { - scalarField: 0 - } + scalarField: 0 + } } else { obj = {} } @@ -86,6 +78,16 @@ export namespace MessageWithRequired { } } + if (opts.emitCollections === true) { + for (const [key, value] of Object.entries(obj)) { + if (Array.isArray(value) || value instanceof Map) { + yield { + field: key, + value + } + } + } + } }) } diff --git a/packages/protons/test/fixtures/protons-options.ts b/packages/protons/test/fixtures/protons-options.ts index dab94f1..96076f3 100644 --- a/packages/protons/test/fixtures/protons-options.ts +++ b/packages/protons/test/fixtures/protons-options.ts @@ -1,11 +1,3 @@ -/* eslint-disable import/export */ -/* eslint-disable complexity */ -/* eslint-disable @typescript-eslint/no-namespace */ -/* eslint-disable @typescript-eslint/no-unnecessary-boolean-literal-compare */ -/* eslint-disable @typescript-eslint/no-empty-interface */ -/* eslint-disable import/consistent-type-specifier-style */ -/* eslint-disable @typescript-eslint/no-unused-vars */ - import { decodeMessage, encodeMessage, MaxLengthError, MaxSizeError, message, streamMessage } from 'protons-runtime' import type { Codec, DecodeOptions, StreamingDecodeOptions, StreamingDecodeWithCollectionsOptions } from 'protons-runtime' import type { Uint8ArrayList } from 'uint8arraylist' @@ -70,10 +62,12 @@ export namespace MessageWithSizeLimitedRepeatedField { if (opts.emitCollections === true) { obj = { - repeatedField: [] - } + repeatedField: [] + } } else { - obj = {} + obj = { + repeatedField: 0 + } } const end = length == null ? reader.len : reader.pos + length @@ -83,19 +77,28 @@ export namespace MessageWithSizeLimitedRepeatedField { switch (tag >>> 3) { case 1: { - if (opts.limits?.repeatedField != null && obj.repeatedField.length === opts.limits.repeatedField) { + if (opts.limits?.repeatedField != null && (opts.emitCollections === true ? obj.repeatedField.length === opts.limits.repeatedField : obj.repeatedField === opts.limits.repeatedField)) { throw new MaxLengthError('Decode error - map field "repeatedField" had too many elements') } - if (obj.repeatedField.length === 1) { + if (opts.emitCollections === true ? obj.repeatedField.length === 1 : obj.repeatedField === 1) { throw new MaxLengthError('Decode error - repeated field "repeatedField" had too many elements') } + const value = reader.string() + yield { field: 'repeatedField$value', - index: 0, - value: reader.string() + index: opts.emitCollections === true ? obj.repeatedField.length : obj.repeatedField, + value + } + + if (opts.emitCollections === true) { + obj.repeatedField.push(value) + } else { + obj.repeatedField++ } + break } default: { @@ -105,6 +108,16 @@ export namespace MessageWithSizeLimitedRepeatedField { } } + if (opts.emitCollections === true) { + for (const [key, value] of Object.entries(obj)) { + if (Array.isArray(value) || value instanceof Map) { + yield { + field: key, + value + } + } + } + } }) } @@ -206,9 +219,9 @@ export namespace MessageWithSizeLimitedMap { if (opts.emitCollections === true) { obj = { - key: '', - value: '' - } + key: '', + value: '' + } } else { obj = {} } @@ -240,6 +253,16 @@ export namespace MessageWithSizeLimitedMap { } } + if (opts.emitCollections === true) { + for (const [key, value] of Object.entries(obj)) { + if (Array.isArray(value) || value instanceof Map) { + yield { + field: key, + value + } + } + } + } }) } @@ -330,10 +353,12 @@ export namespace MessageWithSizeLimitedMap { if (opts.emitCollections === true) { obj = { - mapField: new Map() - } + mapField: new Map() + } } else { - obj = {} + obj = { + mapField: 0 + } } const end = length == null ? reader.len : reader.pos + length @@ -343,11 +368,11 @@ export namespace MessageWithSizeLimitedMap { switch (tag >>> 3) { case 1: { - if (opts.limits?.mapField != null && obj.mapField.size === opts.limits.mapField) { + if (opts.limits?.mapField != null && (opts.emitCollections === true ? obj.mapField.size === opts.limits.mapField : obj.mapField === opts.limits.mapField)) { throw new MaxSizeError('Decode error - map field "mapField" had too many elements') } - if (obj.mapField.size === 1) { + if (opts.emitCollections === true ? obj.mapField.size === 1 : obj.mapField === 1) { throw new MaxSizeError('Decode error - map field "mapField" had too many elements') } @@ -358,6 +383,13 @@ export namespace MessageWithSizeLimitedMap { key: entry.key, value: entry.value } + + if (opts.emitCollections === true) { + obj.mapField.set(entry.key, entry.value) + } else { + obj.mapField++ + } + break } default: { @@ -367,6 +399,16 @@ export namespace MessageWithSizeLimitedMap { } } + if (opts.emitCollections === true) { + for (const [key, value] of Object.entries(obj)) { + if (Array.isArray(value) || value instanceof Map) { + yield { + field: key, + value + } + } + } + } }) } diff --git a/packages/protons/test/fixtures/repeated.ts b/packages/protons/test/fixtures/repeated.ts index 05c2ea9..3e91f9f 100644 --- a/packages/protons/test/fixtures/repeated.ts +++ b/packages/protons/test/fixtures/repeated.ts @@ -1,10 +1,4 @@ -/* eslint-disable import/export */ /* eslint-disable complexity */ -/* eslint-disable @typescript-eslint/no-namespace */ -/* eslint-disable @typescript-eslint/no-unnecessary-boolean-literal-compare */ -/* eslint-disable @typescript-eslint/no-empty-interface */ -/* eslint-disable import/consistent-type-specifier-style */ -/* eslint-disable @typescript-eslint/no-unused-vars */ import { decodeMessage, encodeMessage, MaxLengthError, message, streamMessage } from 'protons-runtime' import type { Codec, DecodeOptions, StreamingDecodeOptions, StreamingDecodeWithCollectionsOptions } from 'protons-runtime' @@ -76,8 +70,8 @@ export namespace SubSubMessage { if (opts.emitCollections === true) { obj = { - foo: [] - } + foo: [] + } } else { obj = { foo: 0 @@ -272,9 +266,9 @@ export namespace SubMessage { if (opts.emitCollections === true) { obj = { - foo: [], - messages: [] - } + foo: [], + messages: [] + } } else { obj = { foo: 0, @@ -331,8 +325,8 @@ export namespace SubMessage { } const value = SubSubMessage.codec().decode(reader, reader.uint32(), { - limits: opts.limits?.messages$ - }) + limits: opts.limits?.messages$ + }) yield { field: 'messages$value', @@ -539,10 +533,10 @@ export namespace RepeatedTypes { if (opts.emitCollections === true) { obj = { - number: [], - limitedNumber: [], - messages: [] - } + number: [], + limitedNumber: [], + messages: [] + } } else { obj = { number: 0, @@ -609,8 +603,8 @@ export namespace RepeatedTypes { } const value = SubMessage.codec().decode(reader, reader.uint32(), { - limits: opts.limits?.messages$ - }) + limits: opts.limits?.messages$ + }) yield { field: 'messages$value', diff --git a/packages/protons/test/fixtures/singular.ts b/packages/protons/test/fixtures/singular.ts index 4e67d46..728b05d 100644 --- a/packages/protons/test/fixtures/singular.ts +++ b/packages/protons/test/fixtures/singular.ts @@ -1,10 +1,4 @@ -/* eslint-disable import/export */ /* eslint-disable complexity */ -/* eslint-disable @typescript-eslint/no-namespace */ -/* eslint-disable @typescript-eslint/no-unnecessary-boolean-literal-compare */ -/* eslint-disable @typescript-eslint/no-empty-interface */ -/* eslint-disable import/consistent-type-specifier-style */ -/* eslint-disable @typescript-eslint/no-unused-vars */ import { decodeMessage, encodeMessage, enumeration, message, streamMessage } from 'protons-runtime' import { alloc as uint8ArrayAlloc } from 'uint8arrays/alloc' @@ -90,9 +84,9 @@ export namespace SingularSubMessage { if (opts.emitCollections === true) { obj = { - foo: '', - bar: 0 - } + foo: '', + bar: 0 + } } else { obj = {} } @@ -124,6 +118,16 @@ export namespace SingularSubMessage { } } + if (opts.emitCollections === true) { + for (const [key, value] of Object.entries(obj)) { + if (Array.isArray(value) || value instanceof Map) { + yield { + field: key, + value + } + } + } + } }) } @@ -385,23 +389,23 @@ export namespace Singular { if (opts.emitCollections === true) { obj = { - double: 0, - float: 0, - int32: 0, - int64: 0n, - uint32: 0, - uint64: 0n, - sint32: 0, - sint64: 0n, - fixed32: 0, - fixed64: 0n, - sfixed32: 0, - sfixed64: 0n, - bool: false, - string: '', - bytes: uint8ArrayAlloc(0), - enum: SingularEnum.NO_VALUE - } + double: 0, + float: 0, + int32: 0, + int64: 0n, + uint32: 0, + uint64: 0n, + sint32: 0, + sint64: 0n, + fixed32: 0, + fixed64: 0n, + sfixed32: 0, + sfixed64: 0n, + bool: false, + string: '', + bytes: uint8ArrayAlloc(0), + enum: SingularEnum.NO_VALUE + } } else { obj = {} } @@ -540,6 +544,16 @@ export namespace Singular { } } + if (opts.emitCollections === true) { + for (const [key, value] of Object.entries(obj)) { + if (Array.isArray(value) || value instanceof Map) { + yield { + field: key, + value + } + } + } + } }) } diff --git a/packages/protons/test/fixtures/test.ts b/packages/protons/test/fixtures/test.ts index 1598084..2fbbcd1 100644 --- a/packages/protons/test/fixtures/test.ts +++ b/packages/protons/test/fixtures/test.ts @@ -1,10 +1,4 @@ -/* eslint-disable import/export */ /* eslint-disable complexity */ -/* eslint-disable @typescript-eslint/no-namespace */ -/* eslint-disable @typescript-eslint/no-unnecessary-boolean-literal-compare */ -/* eslint-disable @typescript-eslint/no-empty-interface */ -/* eslint-disable import/consistent-type-specifier-style */ -/* eslint-disable @typescript-eslint/no-unused-vars */ import { decodeMessage, encodeMessage, enumeration, MaxLengthError, message, streamMessage } from 'protons-runtime' import type { Codec, DecodeOptions, StreamingDecodeOptions, StreamingDecodeWithCollectionsOptions } from 'protons-runtime' @@ -76,8 +70,8 @@ export namespace SubMessage { if (opts.emitCollections === true) { obj = { - foo: '' - } + foo: '' + } } else { obj = {} } @@ -369,8 +363,8 @@ export namespace AllTheTypes { if (opts.emitCollections === true) { obj = { - field14: [] - } + field14: [] + } } else { obj = { field14: 0 diff --git a/packages/protons/test/streaming-decode.spec.ts b/packages/protons/test/streaming-decode.spec.ts index a9220c3..bbc390a 100644 --- a/packages/protons/test/streaming-decode.spec.ts +++ b/packages/protons/test/streaming-decode.spec.ts @@ -1,6 +1,6 @@ import { expect } from 'aegir/chai' -import { AllTheTypes, AnEnum } from './fixtures/test.ts' import all from 'it-all' +import { AllTheTypes, AnEnum } from './fixtures/test.ts' describe('streaming-decode', () => { it('should yield collections when asked to', async () => { From 1449090d68783e1f37b617302ea6998b2fb4cd53 Mon Sep 17 00:00:00 2001 From: achingbrain Date: Fri, 20 Mar 2026 16:30:13 +0100 Subject: [PATCH 3/4] chore: refactor code gen to be more maintainable --- .../src/implementations/protons/bench.ts | 247 +-- packages/protons-runtime/src/codec.ts | 31 +- packages/protons-runtime/src/codecs/enum.ts | 2 +- .../protons-runtime/src/codecs/message.ts | 2 +- packages/protons-runtime/src/decode.ts | 2 +- packages/protons-runtime/src/encode.ts | 2 +- packages/protons-runtime/src/index.ts | 4 +- packages/protons-runtime/src/stream.ts | 4 +- packages/protons/src/fields/array-field.ts | 114 ++ packages/protons/src/fields/enum-field.ts | 53 + packages/protons/src/fields/field.ts | 201 +++ packages/protons/src/fields/map-field.ts | 112 ++ packages/protons/src/fields/message-field.ts | 19 + packages/protons/src/index.ts | 1481 +---------------- packages/protons/src/types/enum.ts | 108 ++ packages/protons/src/types/index.ts | 20 + packages/protons/src/types/message.ts | 495 ++++++ packages/protons/src/types/module.ts | 234 +++ packages/protons/src/types/primitive.ts | 204 +++ packages/protons/test/fixtures/basic.ts | 78 +- packages/protons/test/fixtures/bitswap.ts | 343 +--- packages/protons/test/fixtures/circuit.ts | 137 +- .../test/fixtures/custom-option-jstype.ts | 128 +- packages/protons/test/fixtures/daemon.ts | 1309 +++++---------- packages/protons/test/fixtures/dht.ts | 223 +-- packages/protons/test/fixtures/maps.ts | 499 ++---- packages/protons/test/fixtures/noise.ts | 82 +- packages/protons/test/fixtures/oneof.ts | 116 +- packages/protons/test/fixtures/optional.ts | 121 +- packages/protons/test/fixtures/peer.ts | 213 +-- packages/protons/test/fixtures/proto2.ts | 40 +- .../protons/test/fixtures/protons-options.ts | 181 +- packages/protons/test/fixtures/repeated.ts | 310 +--- packages/protons/test/fixtures/singular.ts | 141 +- packages/protons/test/fixtures/test.ts | 146 +- .../protons/test/streaming-decode.spec.ts | 44 +- 36 files changed, 2788 insertions(+), 4658 deletions(-) create mode 100644 packages/protons/src/fields/array-field.ts create mode 100644 packages/protons/src/fields/enum-field.ts create mode 100644 packages/protons/src/fields/field.ts create mode 100644 packages/protons/src/fields/map-field.ts create mode 100644 packages/protons/src/fields/message-field.ts create mode 100644 packages/protons/src/types/enum.ts create mode 100644 packages/protons/src/types/index.ts create mode 100644 packages/protons/src/types/message.ts create mode 100644 packages/protons/src/types/module.ts create mode 100644 packages/protons/src/types/primitive.ts diff --git a/packages/protons-benchmark/src/implementations/protons/bench.ts b/packages/protons-benchmark/src/implementations/protons/bench.ts index 9171f95..ab6a14f 100644 --- a/packages/protons-benchmark/src/implementations/protons/bench.ts +++ b/packages/protons-benchmark/src/implementations/protons/bench.ts @@ -1,5 +1,7 @@ +/* eslint-disable require-yield */ + import { decodeMessage, encodeMessage, enumeration, MaxLengthError, message, streamMessage } from 'protons-runtime' -import type { Codec, DecodeOptions, StreamingDecodeOptions, StreamingDecodeWithCollectionsOptions } from 'protons-runtime' +import type { Codec, DecodeOptions } from 'protons-runtime' import type { Uint8ArrayList } from 'uint8arraylist' export interface Foo { @@ -7,11 +9,11 @@ export interface Foo { } export namespace Foo { - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -45,15 +47,7 @@ export namespace Foo { } return obj - }, function * (reader, length, opts = {}) { - let obj: any - - if (opts.emitCollections === true) { - obj = {} - } else { - obj = {} - } - + }, function * (reader, length, prefix, opts = {}) { const end = length == null ? reader.len : reader.pos + length while (reader.pos < end) { @@ -62,7 +56,7 @@ export namespace Foo { switch (tag >>> 3) { case 1: { yield { - field: 'baz', + field: `${prefix != null ? `${prefix}.` : ''}baz`, value: reader.uint32() } break @@ -73,17 +67,6 @@ export namespace Foo { } } } - - if (opts.emitCollections === true) { - for (const [key, value] of Object.entries(obj)) { - if (Array.isArray(value) || value instanceof Map) { - yield { - field: key, - value - } - } - } - } }) } @@ -95,9 +78,6 @@ export namespace Foo { value: number } - export type FooStreamEvent = FooBazFieldEvent - export type FooStreamCollectionsEvent = {} - export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, Foo.codec()) } @@ -106,9 +86,7 @@ export namespace Foo { return decodeMessage(buf, Foo.codec(), opts) } - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Generator { return streamMessage(buf, Foo.codec(), opts) } } @@ -118,11 +96,11 @@ export interface Bar { } export namespace Bar { - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -158,15 +136,7 @@ export namespace Bar { } return obj - }, function * (reader, length, opts = {}) { - let obj: any - - if (opts.emitCollections === true) { - obj = {} - } else { - obj = {} - } - + }, function * (reader, length, prefix, opts = {}) { const end = length == null ? reader.len : reader.pos + length while (reader.pos < end) { @@ -175,7 +145,7 @@ export namespace Bar { switch (tag >>> 3) { case 1: { yield { - field: 'tmp', + field: `${prefix != null ? `${prefix}.` : ''}tmp`, value: Foo.codec().decode(reader, reader.uint32(), { limits: opts.limits?.tmp }) @@ -188,31 +158,17 @@ export namespace Bar { } } } - - if (opts.emitCollections === true) { - for (const [key, value] of Object.entries(obj)) { - if (Array.isArray(value) || value instanceof Map) { - yield { - field: key, - value - } - } - } - } }) } return _codec } - export interface BarTmpFieldEvent { - field: 'tmp' - value: Foo + export interface BarTmpFooBazFieldEvent { + field: 'baz' + value: number } - export type BarStreamEvent = BarTmpFieldEvent - export type BarStreamCollectionsEvent = {} - export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, Bar.codec()) } @@ -221,9 +177,7 @@ export namespace Bar { return decodeMessage(buf, Bar.codec(), opts) } - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Generator { return streamMessage(buf, Bar.codec(), opts) } } @@ -241,7 +195,7 @@ enum __FOOValues { } export namespace FOO { - export const codec = (): Codec => { + export const codec = (): Codec => { return enumeration(__FOOValues) } } @@ -251,11 +205,11 @@ export interface Yo { } export namespace Yo { - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -283,7 +237,7 @@ export namespace Yo { switch (tag >>> 3) { case 1: { if (opts.limits?.lol != null && obj.lol.length === opts.limits.lol) { - throw new MaxLengthError('Decode error - map field "lol" had too many elements') + throw new MaxLengthError('Decode error - repeated field "lol" had too many elements') } obj.lol.push(FOO.codec().decode(reader)) @@ -297,17 +251,9 @@ export namespace Yo { } return obj - }, function * (reader, length, opts = {}) { - let obj: any - - if (opts.emitCollections === true) { - obj = { - lol: [] - } - } else { - obj = { - lol: 0 - } + }, function * (reader, length, prefix, opts = {}) { + const obj = { + lol: 0 } const end = length == null ? reader.len : reader.pos + length @@ -317,24 +263,19 @@ export namespace Yo { switch (tag >>> 3) { case 1: { - if (opts.limits?.lol != null && (opts.emitCollections === true ? obj.lol.length === opts.limits.lol : obj.lol === opts.limits.lol)) { - throw new MaxLengthError('Decode error - map field "lol" had too many elements') + if (opts.limits?.lol != null && obj.lol === opts.limits.lol) { + throw new MaxLengthError('Decode error - repeated field "lol" had too many elements') } const value = FOO.codec().decode(reader) + obj.lol++ yield { - field: 'lol$value', - index: opts.emitCollections === true ? obj.lol.length : obj.lol, + field: `${prefix != null ? `${prefix}.` : ''}lol`, + index: obj.lol, value } - if (opts.emitCollections === true) { - obj.lol.push(value) - } else { - obj.lol++ - } - break } default: { @@ -343,37 +284,12 @@ export namespace Yo { } } } - - if (opts.emitCollections === true) { - for (const [key, value] of Object.entries(obj)) { - if (Array.isArray(value) || value instanceof Map) { - yield { - field: key, - value - } - } - } - } }) } return _codec } - export interface YoLolFieldEvent { - field: 'lol' - value: FOO[] - } - - export interface YoLolValueEvent { - field: 'lol$value' - index: number - value: FOO - } - - export type YoStreamEvent = YoLolValueEvent - export type YoStreamCollectionsEvent = YoLolFieldEvent - export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, Yo.codec()) } @@ -382,9 +298,7 @@ export namespace Yo { return decodeMessage(buf, Yo.codec(), opts) } - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Generator<{}> { return streamMessage(buf, Yo.codec(), opts) } } @@ -395,11 +309,11 @@ export interface Lol { } export namespace Lol { - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -444,15 +358,7 @@ export namespace Lol { } return obj - }, function * (reader, length, opts = {}) { - let obj: any - - if (opts.emitCollections === true) { - obj = {} - } else { - obj = {} - } - + }, function * (reader, length, prefix, opts = {}) { const end = length == null ? reader.len : reader.pos + length while (reader.pos < end) { @@ -461,14 +367,14 @@ export namespace Lol { switch (tag >>> 3) { case 1: { yield { - field: 'lol', + field: `${prefix != null ? `${prefix}.` : ''}lol`, value: reader.string() } break } case 2: { yield { - field: 'b', + field: `${prefix != null ? `${prefix}.` : ''}b`, value: Bar.codec().decode(reader, reader.uint32(), { limits: opts.limits?.b }) @@ -481,17 +387,6 @@ export namespace Lol { } } } - - if (opts.emitCollections === true) { - for (const [key, value] of Object.entries(obj)) { - if (Array.isArray(value) || value instanceof Map) { - yield { - field: key, - value - } - } - } - } }) } @@ -503,14 +398,11 @@ export namespace Lol { value: string } - export interface LolBFieldEvent { - field: 'b' - value: Bar + export interface LolBBarTmpFooBazFieldEvent { + field: 'baz' + value: number } - export type LolStreamEvent = LolLolFieldEvent | LolBFieldEvent - export type LolStreamCollectionsEvent = {} - export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, Lol.codec()) } @@ -519,9 +411,7 @@ export namespace Lol { return decodeMessage(buf, Lol.codec(), opts) } - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Generator { return streamMessage(buf, Lol.codec(), opts) } } @@ -534,11 +424,11 @@ export interface Test { } export namespace Test { - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -601,15 +491,7 @@ export namespace Test { } return obj - }, function * (reader, length, opts = {}) { - let obj: any - - if (opts.emitCollections === true) { - obj = {} - } else { - obj = {} - } - + }, function * (reader, length, prefix, opts = {}) { const end = length == null ? reader.len : reader.pos + length while (reader.pos < end) { @@ -618,7 +500,7 @@ export namespace Test { switch (tag >>> 3) { case 6: { yield { - field: 'meh', + field: `${prefix != null ? `${prefix}.` : ''}meh`, value: Lol.codec().decode(reader, reader.uint32(), { limits: opts.limits?.meh }) @@ -627,21 +509,21 @@ export namespace Test { } case 3: { yield { - field: 'hello', + field: `${prefix != null ? `${prefix}.` : ''}hello`, value: reader.uint32() } break } case 1: { yield { - field: 'foo', + field: `${prefix != null ? `${prefix}.` : ''}foo`, value: reader.string() } break } case 7: { yield { - field: 'payload', + field: `${prefix != null ? `${prefix}.` : ''}payload`, value: reader.bytes() } break @@ -652,26 +534,20 @@ export namespace Test { } } } - - if (opts.emitCollections === true) { - for (const [key, value] of Object.entries(obj)) { - if (Array.isArray(value) || value instanceof Map) { - yield { - field: key, - value - } - } - } - } }) } return _codec } - export interface TestMehFieldEvent { - field: 'meh' - value: Lol + export interface TestMehLolLolFieldEvent { + field: 'lol' + value: string + } + + export interface TestMehLolBBarTmpFooBazFieldEvent { + field: 'baz' + value: number } export interface TestHelloFieldEvent { @@ -689,9 +565,6 @@ export namespace Test { value: Uint8Array } - export type TestStreamEvent = TestMehFieldEvent | TestHelloFieldEvent | TestFooFieldEvent | TestPayloadFieldEvent - export type TestStreamCollectionsEvent = {} - export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, Test.codec()) } @@ -700,9 +573,7 @@ export namespace Test { return decodeMessage(buf, Test.codec(), opts) } - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Generator { return streamMessage(buf, Test.codec(), opts) } } diff --git a/packages/protons-runtime/src/codec.ts b/packages/protons-runtime/src/codec.ts index 0f06795..5fbfdd5 100644 --- a/packages/protons-runtime/src/codec.ts +++ b/packages/protons-runtime/src/codec.ts @@ -59,40 +59,19 @@ export interface DecodeFunction { (reader: Reader, length?: number, opts?: DecodeOptions): T } -export interface StreamingDecodeOptions extends DecodeOptions { - /** - * If true, yield a value event for repeated elements/maps, otherwise only - * yield events for collection members - * - * @default false - */ - emitCollections?: false -} - -export interface StreamingDecodeWithCollectionsOptions extends DecodeOptions { - /** - * If true, yield a value event for repeated elements/maps, otherwise only - * yield events for collection members - * - * @default false - */ - emitCollections: true -} - -export interface StreamFunction { - (reader: Reader, length?: number, opts?: StreamingDecodeOptions): Generator - (reader: Reader, length?: number, opts?: StreamingDecodeWithCollectionsOptions): Generator +export interface StreamFunction { + (reader: Reader, length?: number, prefix?: string, opts?: DecodeOptions): Generator } -export interface Codec { +export interface Codec { name: string type: number encode: EncodeFunction decode: DecodeFunction - stream: StreamFunction + stream: StreamFunction } -export function createCodec (name: string, type: number, encode: EncodeFunction, decode: DecodeFunction, stream: StreamFunction): Codec { +export function createCodec (name: string, type: number, encode: EncodeFunction, decode: DecodeFunction, stream: StreamFunction): Codec { return { name, type, diff --git a/packages/protons-runtime/src/codecs/enum.ts b/packages/protons-runtime/src/codecs/enum.ts index 68a6777..fb83643 100644 --- a/packages/protons-runtime/src/codecs/enum.ts +++ b/packages/protons-runtime/src/codecs/enum.ts @@ -1,7 +1,7 @@ import { createCodec, CODEC_TYPES } from '../codec.ts' import type { DecodeFunction, EncodeFunction, Codec } from '../codec.ts' -export function enumeration (v: any): Codec { +export function enumeration (v: any): Codec { function findValue (val: string | number): number { // Use the reverse mapping to look up the enum key for the stored value // https://www.typescriptlang.org/docs/handbook/enums.html#reverse-mappings diff --git a/packages/protons-runtime/src/codecs/message.ts b/packages/protons-runtime/src/codecs/message.ts index 3f7bed3..41018c7 100644 --- a/packages/protons-runtime/src/codecs/message.ts +++ b/packages/protons-runtime/src/codecs/message.ts @@ -5,6 +5,6 @@ export interface Factory { new (obj: A): T } -export function message (encode: EncodeFunction, decode: DecodeFunction, stream: StreamFunction): Codec { +export function message (encode: EncodeFunction, decode: DecodeFunction, stream: StreamFunction): Codec { return createCodec('message', CODEC_TYPES.LENGTH_DELIMITED, encode, decode, stream) } diff --git a/packages/protons-runtime/src/decode.ts b/packages/protons-runtime/src/decode.ts index 73ca27a..18ef696 100644 --- a/packages/protons-runtime/src/decode.ts +++ b/packages/protons-runtime/src/decode.ts @@ -2,7 +2,7 @@ import { createReader } from './utils/reader.ts' import type { Codec, DecodeOptions } from './codec.ts' import type { Uint8ArrayList } from 'uint8arraylist' -export function decodeMessage (buf: Uint8Array | Uint8ArrayList, codec: Pick, 'decode'>, opts?: DecodeOptions): T { +export function decodeMessage (buf: Uint8Array | Uint8ArrayList, codec: Pick, 'decode'>, opts?: DecodeOptions): T { const reader = createReader(buf) return codec.decode(reader, undefined, opts) diff --git a/packages/protons-runtime/src/encode.ts b/packages/protons-runtime/src/encode.ts index 0ae7963..5ac8c39 100644 --- a/packages/protons-runtime/src/encode.ts +++ b/packages/protons-runtime/src/encode.ts @@ -1,7 +1,7 @@ import { createWriter } from './utils/writer.ts' import type { Codec } from './codec.ts' -export function encodeMessage (message: Partial, codec: Pick, 'encode'>): Uint8Array { +export function encodeMessage (message: Partial, codec: Pick, 'encode'>): Uint8Array { const w = createWriter() codec.encode(message, w, { diff --git a/packages/protons-runtime/src/index.ts b/packages/protons-runtime/src/index.ts index 9bf9efe..58a06e2 100644 --- a/packages/protons-runtime/src/index.ts +++ b/packages/protons-runtime/src/index.ts @@ -14,7 +14,7 @@ import type { Codec } from './codec.ts' export interface FieldDef { name: string - codec: Codec + codec: Codec optional?: true repeats?: true packed?: true @@ -36,7 +36,7 @@ export { enumeration } from './codecs/enum.ts' export { message } from './codecs/message.ts' export { createReader as reader } from './utils/reader.ts' export { createWriter as writer } from './utils/writer.ts' -export type { Codec, EncodeOptions, DecodeOptions, StreamingDecodeOptions, StreamingDecodeWithCollectionsOptions } from './codec.ts' +export type { Codec, EncodeOptions, DecodeOptions } from './codec.ts' export interface Writer { /** diff --git a/packages/protons-runtime/src/stream.ts b/packages/protons-runtime/src/stream.ts index 8c07b52..ed31acc 100644 --- a/packages/protons-runtime/src/stream.ts +++ b/packages/protons-runtime/src/stream.ts @@ -1,8 +1,8 @@ import { createReader } from './utils/reader.ts' -import type { Codec, StreamingDecodeOptions } from './codec.ts' +import type { Codec } from './codec.ts' import type { Uint8ArrayList } from 'uint8arraylist' -export function * streamMessage (buf: Uint8Array | Uint8ArrayList, codec: Pick, 'stream'>, opts?: StreamingDecodeOptions): Generator { +export function * streamMessage (buf: Uint8Array | Uint8ArrayList, codec: Pick, 'stream'>, opts?: any): Generator { const reader = createReader(buf) yield * codec.stream(reader, undefined, opts) diff --git a/packages/protons/src/fields/array-field.ts b/packages/protons/src/fields/array-field.ts new file mode 100644 index 0000000..9d62a34 --- /dev/null +++ b/packages/protons/src/fields/array-field.ts @@ -0,0 +1,114 @@ +import { Enum } from '../types/enum.ts' +import { Message } from '../types/message.ts' +import { codecTypes, Field } from './field.ts' +import type { FieldDef } from './field.ts' +import type { Parent, Type } from '../types/index.ts' + +export interface ArrayFieldDef extends FieldDef { + rule: 'repeated' +} + +export function isArrayFieldDef (obj?: any): obj is ArrayFieldDef { + return obj?.rule === 'repeated' +} + +export class ArrayField extends Field { + private lengthLimit?: number + + constructor (name: string, def: ArrayFieldDef, parent: Parent) { + super(name, def, parent) + + this.lengthLimit = def.options?.['(protons.options).limit'] + } + + getInterfaceField (parent: Parent, indent = ''): string { + return `${super.getInterfaceField(parent, indent)}[]` + } + + getDefaultField (parent: Parent): string { + return `${this.name}: []` + } + + getEncoder (parent: Parent): string { + const type = parent.findType(this.type) + let id = (this.id << 3) | codecTypes[this.type] + + if (type instanceof Message) { + id = (this.id << 3) | codecTypes.message + } + + if (type instanceof Enum) { + id = (this.id << 3) | codecTypes.enum + } + + return ` + if (obj.${this.name} != null) { + for (const value of obj.${this.name}) { + w.uint32(${id}) + ${type.getEncoder(this, 'value')} + } + }` + } + + getDecoder (parent: Parent): string { + parent.addImport('protons-runtime', 'MaxLengthError') + + let limit = ` + if (opts.limits?.${this.name} != null && obj.${this.name}.length === opts.limits.${this.name}) { + throw new MaxLengthError('Decode error - repeated field "${this.name}" had too many elements') + } +` + + if (this.lengthLimit != null) { + limit += ` + if (obj.${this.name}.length === ${this.lengthLimit}) { + throw new MaxLengthError('Decode error - repeated field "${this.name}" had too many elements') + } +` + } + + const type: Type = parent.findType(this.type) + + return `case ${this.id}: {${limit} + obj.${this.name}.push(${type.getDecoder(this)}) + break + }` + } + + getStreamingDecoder (parent: Parent): string { + parent.addImport('protons-runtime', 'MaxLengthError') + + let limit = ` + if (opts.limits?.${this.name} != null && obj.${this.name} === opts.limits.${this.name}) { + throw new MaxLengthError('Decode error - repeated field "${this.name}" had too many elements') + } +` + + if (this.lengthLimit != null) { + limit += ` + if (obj.${this.name} === ${this.lengthLimit}) { + throw new MaxLengthError('Decode error - repeated field "${this.name}" had too many elements') + } +` + } + + const type: Type = parent.findType(this.type) + + return `case ${this.id}: {${limit} + const value = ${type.getDecoder(this)} + obj.${this.name}++ + + yield { + field: \`\${prefix != null ? \`\${prefix}.\` : ''}${this.name}\`, + index: obj.${this.name}, + value + } + + break + }` + } + + getLimitField (): string { + return `${this.name}: ${this.lengthLimit ?? 0}` + } +} diff --git a/packages/protons/src/fields/enum-field.ts b/packages/protons/src/fields/enum-field.ts new file mode 100644 index 0000000..65a1701 --- /dev/null +++ b/packages/protons/src/fields/enum-field.ts @@ -0,0 +1,53 @@ +import { Enum } from '../types/enum.ts' +import { Field } from './field.ts' +import type { FieldDef } from './field.ts' +import type { Parent } from '../types/index.ts' + +export class EnumField extends Field { + private enum: Enum + + constructor (name: string, def: FieldDef, parent: Parent) { + super(name, def, parent) + + const type = parent.findType(def.type) + + if (!(type instanceof Enum)) { + throw new Error(`Type "${def.type}" was not an Enum`) + } + + this.enum = type + } + + getDefaultField (parent: Parent): string { + if (this.optional) { + return '' + } + + const type = parent.findType(this.type) + + return `${this.name}: ${type.pbType}.${this.enum.lowestValueName}` + } +/* + getValueTest (): string { + console.info(this.name, 'optional', this.optional, 'proto2required', this.proto2Required) + + if (this.proto2Required) { + return 'true' + } + + const valueTest = `obj.${this.name} != null` + + // singular enums default to 0, but enums can be defined without a 0 + // value which is against the proto3 spec but is tolerated + if (this.optional || this.proto2Required) { + return valueTest + } + + if (this.enum.lowestValue === 0) { + return `${valueTest} && __${this.type}Values[obj.${this.name}] !== 0` + } + + return valueTest + } + */ +} diff --git a/packages/protons/src/fields/field.ts b/packages/protons/src/fields/field.ts new file mode 100644 index 0000000..5e370ac --- /dev/null +++ b/packages/protons/src/fields/field.ts @@ -0,0 +1,201 @@ +import { ParseError } from 'protons-runtime' +import { Enum } from '../types/enum.ts' +import { Message } from '../types/message.ts' +import type { Parent, Type } from '../types/index.ts' + +export const CODEC_TYPES = { + VARINT: 0, + BIT64: 1, + LENGTH_DELIMITED: 2, + START_GROUP: 3, + END_GROUP: 4, + BIT32: 5 +} + +export const codecTypes: Record = { + bool: CODEC_TYPES.VARINT, + bytes: CODEC_TYPES.LENGTH_DELIMITED, + double: CODEC_TYPES.BIT64, + enum: CODEC_TYPES.VARINT, + fixed32: CODEC_TYPES.BIT32, + fixed64: CODEC_TYPES.BIT64, + float: CODEC_TYPES.BIT32, + int32: CODEC_TYPES.VARINT, + int64: CODEC_TYPES.VARINT, + message: CODEC_TYPES.LENGTH_DELIMITED, + sfixed32: CODEC_TYPES.BIT32, + sfixed64: CODEC_TYPES.BIT64, + sint32: CODEC_TYPES.VARINT, + sint64: CODEC_TYPES.VARINT, + string: CODEC_TYPES.LENGTH_DELIMITED, + uint32: CODEC_TYPES.VARINT, + uint64: CODEC_TYPES.VARINT +} + +const jsTypeOverrides: Record = { + JS_NUMBER: 'number', + JS_STRING: 'string' +} + +interface DefaultValueGenerator { + (): string +} + +const defaultValueGenerators: Record = { + bool: () => 'false', + bytes: () => 'uint8ArrayAlloc(0)', + double: () => '0', + fixed32: () => '0', + fixed64: () => '0n', + float: () => '0', + int32: () => '0', + int64: () => '0n', + sfixed32: () => '0', + sfixed64: () => '0n', + sint32: () => '0', + sint64: () => '0n', + string: () => "''", + uint32: () => '0', + uint64: () => '0n' +} + +const defaultValueGeneratorsJsTypeOverrides: Record = { + number: () => '0', + string: () => "''" +} + +export interface FieldOptions extends Record { + proto3_optional?: boolean + jstype?: 'string' | 'number' +} + +export interface FieldDef { + id: number + type: string + repeated?: boolean + options?: FieldOptions + rule?: string + oneof?: string[] +} + +export interface MessageField { + /** + * Return a string that can be used in a typescript interface for this field + */ + getInterfaceField (parent: Parent, indent?: string): string +} + +export class Field implements MessageField { + public id: number + public name: string + public optional: boolean + public type: string + public proto2Required: boolean + public jsTypeOverride?: 'string' | 'number' + public oneof?: string[] + + constructor (name: string, def: FieldDef, parent: Parent) { + this.id = def.id + this.name = name + + // the default type for a message is unset so they are always optional + // https://developers.google.com/protocol-buffers/docs/proto3#default + this.optional = def.repeated !== true && def.options?.proto3_optional === true + this.type = def.type ?? 'string' + this.oneof = def.oneof + this.proto2Required = false + + if (def.options?.jstype != null) { + this.jsTypeOverride = jsTypeOverrides[def.options.jstype] + } + + if (this.jsTypeOverride != null && !['int64', 'uint64', 'sint64', 'fixed64', 'sfixed64'].includes(this.type)) { + throw new Error(`jstype override option is only allowed on int64, uint64, sint64, fixed64 or sfixed64 fields - got "${this.type}"`) + } + + if (def.rule === 'required') { + const message = `field "${name}" is required, this is not allowed in proto3. Please convert your proto2 definitions to proto3 - see https://github.com/ipfs/protons/wiki/Required-fields-and-protobuf-3` + + if (parent.flags?.strict === true) { + throw new ParseError(message) + } else { + this.proto2Required = true + + // eslint-disable-next-line no-console + console.info(`[WARN] ${message}`) + } + } + } + + getInterfaceField (parent: Parent, indent = ''): string { + return `${indent}${this.name}${this.optional ? '?' : ''}: ${this.jsTypeOverride ?? parent.findType(this.type).jsType}` + } + + getDefaultField (parent: Parent): string { + if (this.optional) { + return '' + } + + const type = parent.findType(this.type) + + if (type.pbType === 'bytes') { + parent.addImport('uint8arrays/alloc', 'alloc', 'uint8ArrayAlloc') + } + + let defaultValueGenerator = defaultValueGenerators[type.pbType] + + if (this.jsTypeOverride) { + defaultValueGenerator = defaultValueGeneratorsJsTypeOverrides[this.jsTypeOverride] + } + + if (defaultValueGenerator == null) { + return '' + } + + return `${this.name}: ${defaultValueGenerator()}` + } + + getDecoder (parent: Parent): string { + const type: Type = parent.findType(this.type) + + return `case ${this.id}: { + obj.${this.name} = ${type.getDecoder(this)} + break + }` + } + + getStreamingDecoder (parent: Parent): string { + const type: Type = parent.findType(this.type) + + return `case ${this.id}: { + yield { + field: \`\${prefix != null ? \`\${prefix}.\` : ''}${this.name}\`, + value: ${type.getDecoder(this, ' ')} + } + break + }` + } + + getEncoder (parent: Parent): string { + const type = parent.findType(this.type) + let id = (this.id << 3) | codecTypes[this.type] + + if (type instanceof Message) { + id = (this.id << 3) | codecTypes.message + } + + if (type instanceof Enum) { + id = (this.id << 3) | codecTypes.enum + } + + return ` + if (${type.getValueTest(this, `obj.${this.name}`)}) { + w.uint32(${id}) + ${type.getEncoder(this, `obj.${this.name}`)} + }` + } + + getLimitField (): string { + return '' + } +} diff --git a/packages/protons/src/fields/map-field.ts b/packages/protons/src/fields/map-field.ts new file mode 100644 index 0000000..7a88c9b --- /dev/null +++ b/packages/protons/src/fields/map-field.ts @@ -0,0 +1,112 @@ +import { codecTypes, Field } from './field.ts' +import type { FieldDef } from './field.ts' +import type { Parent } from '../types/index.ts' + +export interface MapFieldDef extends FieldDef { + keyType?: string + valueType: string +} + +export function isMapFieldDef (obj?: any): obj is MapFieldDef { + return obj?.keyType != null +} + +export class MapField extends Field { + public keyType: string + public valueType: string + public entryType: string + private lengthLimit?: number + + constructor (name: string, def: MapFieldDef, parent: Parent) { + super(name, def, parent) + + this.type = 'message' + this.keyType = def.keyType ?? 'string' + this.valueType = def.valueType + this.entryType = def.type + this.lengthLimit = def.options?.['(protons.options).limit'] + } + + getInterfaceField (parent: Parent): string { + return `${this.name}: Map<${parent.findType(this.keyType).jsType}, ${parent.findType(this.valueType).jsType}>` + } + + getDefaultField (parent: Parent): string { + return `${this.name}: new Map<${parent.findType(this.keyType).jsType}, ${parent.findType(this.valueType).jsType}>()` + } + + getEncoder (parent: Parent): string { + const id = (this.id << 3) | codecTypes.message + const entryType = parent.findType(this.entryType) + + return ` + if (${entryType.getValueTest(this, 'value')}) { + for (const [key, value] of obj.${this.name}.entries()) { + w.uint32(${id}) + ${entryType.getEncoder(this, '{ key, value }')} + } + }` + } + + getDecoder (parent: Parent): string { + parent.addImport('protons-runtime', 'MaxSizeError') + const entryType = parent.findType(this.entryType) + + let limit = ` + if (opts.limits?.${this.name} != null && obj.${this.name}.size === opts.limits.${this.name}) { + throw new MaxSizeError('Decode error - map field "${this.name}" had too many elements') + } +` + + if (this.lengthLimit != null) { + limit += ` + if (obj.${this.name}.size === ${this.lengthLimit}) { + throw new MaxSizeError('Decode error - map field "${this.name}" had too many elements') + } +` + } + + return `case ${this.id}: {${limit} + const entry = ${entryType.getDecoder(this)} + obj.${this.name}.set(entry.key, entry.value) + break + }` + } + + getStreamingDecoder (parent: Parent): string { + parent.addImport('protons-runtime', 'MaxLengthError') + + let limit = ` + if (opts.limits?.${this.name} != null && obj.${this.name} === opts.limits.${this.name}) { + throw new MaxLengthError('Decode error - map field "${this.name}" had too many elements') + } +` + + if (this.lengthLimit != null) { + limit += ` + if (obj.${this.name} === ${this.lengthLimit}) { + throw new MaxLengthError('Decode error - repeated field "${this.name}" had too many elements') + } +` + } + + const entryType = parent.findType(this.entryType) + + return `case ${this.id}: {${limit} + const entry = ${entryType.getDecoder(this)} + obj.${this.name}++ + + yield { + field: \`\${prefix != null ? \`\${prefix}.\` : ''}${this.name}\`, + key: entry.key, + value: entry.value + } + + break + }` + } + + getLimitField (): string { + return `${this.name}: ${this.lengthLimit ?? 0}` + } +} diff --git a/packages/protons/src/fields/message-field.ts b/packages/protons/src/fields/message-field.ts new file mode 100644 index 0000000..f9767db --- /dev/null +++ b/packages/protons/src/fields/message-field.ts @@ -0,0 +1,19 @@ +import { Message } from '../types/message.ts' +import { Field } from './field.ts' +import type { Parent } from '../types/index.ts' + +export class MessageField extends Field { + getInterfaceField (parent: Parent, indent = ''): string { + return `${indent}${this.name}?: ${parent.findType(this.type).jsType}` + } + + getMessage (parent: Parent): Message { + const type = parent.findType(this.type) + + if (!(type instanceof Message)) { + throw new Error(`Field ${this.name} was not a message field`) + } + + return type + } +} diff --git a/packages/protons/src/index.ts b/packages/protons/src/index.ts index ee7f0be..4e12751 100644 --- a/packages/protons/src/index.ts +++ b/packages/protons/src/index.ts @@ -1,5 +1,3 @@ -/* eslint-disable max-depth */ - /** * @packageDocumentation * @@ -197,1296 +195,14 @@ import fs from 'fs/promises' import path from 'path' import { promisify } from 'util' import { main as pbjs } from 'protobufjs-cli/pbjs.js' -import { NoMessagesFoundError, ParseError } from 'protons-runtime' - -export const CODEC_TYPES = { - VARINT: 0, - BIT64: 1, - LENGTH_DELIMITED: 2, - START_GROUP: 3, - END_GROUP: 4, - BIT32: 5 -} - -interface StreamEvent { - name: string - fields: string[] - collection: boolean -} +import { Module } from './types/module.ts' function pathWithExtension (input: string, extension: string, outputDir?: string): string { const output = outputDir ?? path.dirname(input) return path.join(output, path.basename(input).split('.').slice(0, -1).join('.') + extension) } -function camelize (input: string): string { - return `${input.substring(0, 1).toUpperCase()}${input.substring(1)}` -} - -function interfacesOrEmpty (evts: StreamEvent[]): string { - if (evts.length === 0) { - return '{}' - } - - return evts.map(evt => evt.name).join(' | ') -} - -/** - * This will be removed in a future release - * - * @deprecated - */ -export class CodeError extends Error { - public code: string - - constructor (message: string, code: string, options?: ErrorOptions) { - super(message, options) - - this.code = code - } -} - -const types: Record = { - bool: 'boolean', - bytes: 'Uint8Array', - double: 'number', - fixed32: 'number', - fixed64: 'bigint', - float: 'number', - int32: 'number', - int64: 'bigint', - sfixed32: 'number', - sfixed64: 'bigint', - sint32: 'number', - sint64: 'bigint', - string: 'string', - uint32: 'number', - uint64: 'bigint' -} - -const jsTypeOverrides: Record = { - JS_NUMBER: 'number', - JS_STRING: 'string' -} - -const encoderGenerators: Record string> = { - bool: (val) => `w.bool(${val})`, - bytes: (val) => `w.bytes(${val})`, - double: (val) => `w.double(${val})`, - fixed32: (val) => `w.fixed32(${val})`, - fixed64: (val, jsTypeOverride) => { - if (jsTypeOverride === 'number') { - return `w.fixed64Number(${val})` - } - - if (jsTypeOverride === 'string') { - return `w.fixed64String(${val})` - } - - return `w.fixed64(${val})` - }, - float: (val) => `w.float(${val})`, - int32: (val) => `w.int32(${val})`, - int64: (val, jsTypeOverride) => { - if (jsTypeOverride === 'number') { - return `w.int64Number(${val})` - } - - if (jsTypeOverride === 'string') { - return `w.int64String(${val})` - } - - return `w.int64(${val})` - }, - sfixed32: (val) => `w.sfixed32(${val})`, - sfixed64: (val, jsTypeOverride) => { - if (jsTypeOverride === 'number') { - return `w.sfixed64Number(${val})` - } - - if (jsTypeOverride === 'string') { - return `w.sfixed64String(${val})` - } - - return `w.sfixed64(${val})` - }, - sint32: (val) => `w.sint32(${val})`, - sint64: (val, jsTypeOverride) => { - if (jsTypeOverride === 'number') { - return `w.sint64Number(${val})` - } - - if (jsTypeOverride === 'string') { - return `w.sint64String(${val})` - } - - return `w.sint64(${val})` - }, - string: (val) => `w.string(${val})`, - uint32: (val) => `w.uint32(${val})`, - uint64: (val, jsTypeOverride) => { - if (jsTypeOverride === 'number') { - return `w.uint64Number(${val})` - } - - if (jsTypeOverride === 'string') { - return `w.uint64String(${val})` - } - - return `w.uint64(${val})` - } -} - -const decoderGenerators: Record string> = { - bool: () => 'reader.bool()', - bytes: () => 'reader.bytes()', - double: () => 'reader.double()', - fixed32: () => 'reader.fixed32()', - fixed64: (jsTypeOverride) => { - if (jsTypeOverride === 'number') { - return 'reader.fixed64Number()' - } - - if (jsTypeOverride === 'string') { - return 'reader.fixed64String()' - } - - return 'reader.fixed64()' - }, - float: () => 'reader.float()', - int32: () => 'reader.int32()', - int64: (jsTypeOverride) => { - if (jsTypeOverride === 'number') { - return 'reader.int64Number()' - } - - if (jsTypeOverride === 'string') { - return 'reader.int64String()' - } - - return 'reader.int64()' - }, - sfixed32: () => 'reader.sfixed32()', - sfixed64: (jsTypeOverride) => { - if (jsTypeOverride === 'number') { - return 'reader.sfixed64Number()' - } - - if (jsTypeOverride === 'string') { - return 'reader.sfixed64String()' - } - - return 'reader.sfixed64()' - }, - sint32: () => 'reader.sint32()', - sint64: (jsTypeOverride) => { - if (jsTypeOverride === 'number') { - return 'reader.sint64Number()' - } - - if (jsTypeOverride === 'string') { - return 'reader.sint64String()' - } - - return 'reader.sint64()' - }, - string: () => 'reader.string()', - uint32: () => 'reader.uint32()', - uint64: (jsTypeOverride) => { - if (jsTypeOverride === 'number') { - return 'reader.uint64Number()' - } - - if (jsTypeOverride === 'string') { - return 'reader.uint64String()' - } - - return 'reader.uint64()' - } -} - -const defaultValueGenerators: Record string> = { - bool: () => 'false', - bytes: () => 'uint8ArrayAlloc(0)', - double: () => '0', - fixed32: () => '0', - fixed64: () => '0n', - float: () => '0', - int32: () => '0', - int64: () => '0n', - sfixed32: () => '0', - sfixed64: () => '0n', - sint32: () => '0', - sint64: () => '0n', - string: () => "''", - uint32: () => '0', - uint64: () => '0n' -} - -const defaultValueGeneratorsJsTypeOverrides: Record string> = { - number: () => '0', - string: () => "''" -} - -const defaultValueTestGenerators: Record string> = { - bool: (field) => `(${field} != null && ${field} !== false)`, - bytes: (field) => `(${field} != null && ${field}.byteLength > 0)`, - double: (field) => `(${field} != null && ${field} !== 0)`, - fixed32: (field) => `(${field} != null && ${field} !== 0)`, - fixed64: (field) => `(${field} != null && ${field} !== 0n)`, - float: (field) => `(${field} != null && ${field} !== 0)`, - int32: (field) => `(${field} != null && ${field} !== 0)`, - int64: (field) => `(${field} != null && ${field} !== 0n)`, - sfixed32: (field) => `(${field} != null && ${field} !== 0)`, - sfixed64: (field) => `(${field} != null && ${field} !== 0n)`, - sint32: (field) => `(${field} != null && ${field} !== 0)`, - sint64: (field) => `(${field} != null && ${field} !== 0n)`, - string: (field) => `(${field} != null && ${field} !== '')`, - uint32: (field) => `(${field} != null && ${field} !== 0)`, - uint64: (field) => `(${field} != null && ${field} !== 0n)` -} - -const defaultValueTestGeneratorsJsTypeOverrides: Record string> = { - number: (field) => `(${field} != null && ${field} !== 0)`, - string: (field) => `(${field} != null && ${field} !== '')` -} - -function findJsTypeOverride (defaultType: string, fieldDef: FieldDef): 'number' | 'string' | undefined { - if (fieldDef.options?.jstype != null && jsTypeOverrides[fieldDef.options?.jstype] != null) { - if (!['int64', 'uint64', 'sint64', 'fixed64', 'sfixed64'].includes(defaultType)) { - throw new Error(`jstype is only allowed on int64, uint64, sint64, fixed64 or sfixed64 fields - got "${defaultType}"`) - } - - return jsTypeOverrides[fieldDef.options?.jstype] - } -} - -function findJsTypeName (typeName: string, classDef: MessageDef, moduleDef: ModuleDef, fieldDef: FieldDef): string { - const override = findJsTypeOverride(typeName, fieldDef) - - if (override != null) { - return override - } - - if (types[typeName] != null) { - return types[typeName] - } - - if (isEnumDef(classDef)) { - throw new Error('Could not find type in enum') - } - - if (classDef.nested?.[typeName] != null) { - return `${classDef.fullName}.${typeName}` - } - - if (classDef.parent != null) { - return findJsTypeName(typeName, classDef.parent, moduleDef, fieldDef) - } - - if (moduleDef.globals[typeName] != null) { - return typeName - } - - throw new Error(`Could not resolve type name "${typeName}"`) -} - -function findDef (typeName: string, classDef: MessageDef, moduleDef: ModuleDef): MessageDef { - if (isEnumDef(classDef)) { - throw new Error('Could not find type in enum') - } - - if (classDef.nested?.[typeName] != null) { - return classDef.nested?.[typeName] - } - - if (classDef.parent != null) { - return findDef(typeName, classDef.parent, moduleDef) - } - - if (moduleDef.globals[typeName] != null) { - return moduleDef.globals[typeName] - } - - throw new Error(`Could not resolve type name "${typeName}"`) -} - -function createDefaultObject (fields: Record, messageDef: MessageDef, moduleDef: ModuleDef, indent = ''): string { - const output = Object.entries(fields) - .map(([name, fieldDef]) => { - if (fieldDef.map) { - return `${name}: new Map<${types[fieldDef.keyType ?? 'string']}, ${types[fieldDef.valueType]}>()` - } - - if (fieldDef.repeated) { - return `${name}: []` - } - - if (fieldDef.optional) { - return '' - } - - const type: string = fieldDef.type - let defaultValue - let defaultValueGenerator = defaultValueGenerators[type] - - if (defaultValueGenerator != null) { - const jsTypeOverride = findJsTypeOverride(type, fieldDef) - - if (jsTypeOverride != null && defaultValueGeneratorsJsTypeOverrides[jsTypeOverride] != null) { - defaultValueGenerator = defaultValueGeneratorsJsTypeOverrides[jsTypeOverride] - } - - if (type === 'bytes') { - moduleDef.addImport('uint8arrays/alloc', 'alloc', 'uint8ArrayAlloc') - } - - defaultValue = defaultValueGenerator() - } else { - const def = findDef(fieldDef.type, messageDef, moduleDef) - - if (isEnumDef(def)) { - // select lowest-value enum - should be 0 but it's not guaranteed - const val = Object.entries(def.values) - .sort((a, b) => { - if (a[1] < b[1]) { - return 1 - } - - if (a[1] > b[1]) { - return -1 - } - - return 0 - }) - .pop() - - if (val == null) { - throw new Error(`Could not find default enum value for ${def.fullName}`) - } - - defaultValue = `${def.name}.${val[0]}` - } else { - defaultValue = 'undefined' - } - } - - return `${name}: ${defaultValue}` - }) - .filter(Boolean) - .join(`,\n ${indent}`) - - if (output !== '') { - return ` - ${indent}${output} - ${indent}` - } - - return '' -} - -function createLimitObject (fields: Record): string { - const output = Object.entries(fields) - .map(([name, fieldDef]) => { - if (fieldDef.map) { - return `${name}: 0` - } - - if (fieldDef.repeated) { - return `${name}: 0` - } - - return '' - }) - .filter(Boolean) - .join(',\n ') - - if (output !== '') { - return ` - ${output} - ` - } - - return '' -} - -const encoders: Record = { - bool: 'bool', - bytes: 'bytes', - double: 'double', - fixed32: 'fixed32', - fixed64: 'fixed64', - float: 'float', - int32: 'int32', - int64: 'int64', - sfixed32: 'sfixed32', - sfixed64: 'sfixed64', - sint32: 'sint32', - sint64: 'sint64', - string: 'string', - uint32: 'uint32', - uint64: 'uint64' -} - -const codecTypes: Record = { - bool: CODEC_TYPES.VARINT, - bytes: CODEC_TYPES.LENGTH_DELIMITED, - double: CODEC_TYPES.BIT64, - enum: CODEC_TYPES.VARINT, - fixed32: CODEC_TYPES.BIT32, - fixed64: CODEC_TYPES.BIT64, - float: CODEC_TYPES.BIT32, - int32: CODEC_TYPES.VARINT, - int64: CODEC_TYPES.VARINT, - message: CODEC_TYPES.LENGTH_DELIMITED, - sfixed32: CODEC_TYPES.BIT32, - sfixed64: CODEC_TYPES.BIT64, - sint32: CODEC_TYPES.VARINT, - sint64: CODEC_TYPES.VARINT, - string: CODEC_TYPES.LENGTH_DELIMITED, - uint32: CODEC_TYPES.VARINT, - uint64: CODEC_TYPES.VARINT -} - -interface ClassDef { - name: string - fullName: string - parent?: ClassDef - fields?: Record - nested?: Record - oneofs?: Array -} - -interface EnumDef { - name: string - fullName: string - parent?: ClassDef - values: Record -} - -type MessageDef = ClassDef | EnumDef - -function isEnumDef (obj: any): obj is EnumDef { - return obj.values != null -} - -interface FieldDef { - type: string - id: number - options?: Record - rule: string - optional: boolean - repeated: boolean - lengthLimit?: number - message: boolean - enum: boolean - map: boolean - valueType: string - keyType: string - - /** - * Support proto2 required field. This field means a value should always be - * in the serialized buffer, any message without it should be considered - * invalid. It was removed for proto3. - */ - proto2Required: boolean -} - -function defineFields (fields: Record, messageDef: MessageDef, moduleDef: ModuleDef): string[] { - return Object.entries(fields).map(([fieldName, fieldDef]) => { - if (fieldDef.map) { - return `${fieldName}: Map<${findJsTypeName(fieldDef.keyType ?? 'string', messageDef, moduleDef, fieldDef)}, ${findJsTypeName(fieldDef.valueType, messageDef, moduleDef, fieldDef)}>` - } - - return `${fieldName}${fieldDef.optional ? '?' : ''}: ${findJsTypeName(fieldDef.type, messageDef, moduleDef, fieldDef)}${fieldDef.repeated ? '[]' : ''}` - }) -} - -function compileMessage (messageDef: MessageDef, moduleDef: ModuleDef, flags?: Flags): string { - if (isEnumDef(messageDef)) { - moduleDef.addImport('protons-runtime', 'enumeration') - - // check that the enum def values start from 0 - if (Object.values(messageDef.values)[0] !== 0) { - const message = `enum ${messageDef.name} does not contain a value that maps to zero as it's first element, this is required in proto3 - see https://protobuf.dev/programming-guides/proto3/#enum` - - if (flags?.strict === true) { - throw new ParseError(message) - } else { - // eslint-disable-next-line no-console - console.info(`[WARN] ${message}`) - } - } - - return ` -export enum ${messageDef.name} { - ${ - Object.keys(messageDef.values).map(name => { - return `${name} = '${name}'` - }).join(',\n ').trim() - } -} - -enum __${messageDef.name}Values { - ${ - Object.entries(messageDef.values).map(([name, value]) => { - return `${name} = ${value}` - }).join(',\n ').trim() - } -} - -export namespace ${messageDef.name} { - export const codec = (): Codec<${messageDef.name}, any, any> => { - return enumeration<${messageDef.name}>(__${messageDef.name}Values) - } -} -`.trimStart() - } - - let nested = '' - - if (messageDef.nested != null) { - nested = '\n' - nested += Object.values(messageDef.nested) - .map(def => compileMessage(def, moduleDef, flags).trim()) - .join('\n\n') - .split('\n') - .map(line => line.trim() === '' ? '' : ` ${line}`) - .join('\n') - } - - const fields = messageDef.fields ?? {} - - // import relevant modules - moduleDef.addImport('protons-runtime', 'encodeMessage') - moduleDef.addImport('protons-runtime', 'decodeMessage') - moduleDef.addImport('protons-runtime', 'streamMessage') - moduleDef.addImport('protons-runtime', 'message') - moduleDef.addTypeImport('protons-runtime', 'Codec') - moduleDef.addTypeImport('protons-runtime', 'DecodeOptions') - moduleDef.addTypeImport('protons-runtime', 'StreamingDecodeOptions') - moduleDef.addTypeImport('protons-runtime', 'StreamingDecodeWithCollectionsOptions') - moduleDef.addTypeImport('uint8arraylist', 'Uint8ArrayList') - - const interfaceFields = defineFields(fields, messageDef, moduleDef) - .join('\n ') - .trim() - - let interfaceDef = '' - let interfaceCodecDef = '' - - if (interfaceFields === '') { - interfaceDef = ` -export interface ${messageDef.name} {}` - } else { - interfaceDef = ` -export interface ${messageDef.name} { - ${ - defineFields(fields, messageDef, moduleDef) - .join('\n ') - .trim() - } -}` - } - - const encodeFields = Object.entries(fields) - .map(([name, fieldDef]) => { - let codec: string = encoders[fieldDef.type] - let type: string = fieldDef.map ? 'message' : fieldDef.type - let typeName: string = '' - - if (codec == null) { - if (fieldDef.enum) { - moduleDef.addImport('protons-runtime', 'enumeration') - type = 'enum' - } else { - moduleDef.addImport('protons-runtime', 'message') - type = 'message' - } - - typeName = findJsTypeName(fieldDef.type, messageDef, moduleDef, fieldDef) - codec = `${typeName}.codec()` - } - - let valueTest = `obj.${name} != null` - - if (fieldDef.map) { - valueTest = `obj.${name} != null && obj.${name}.size !== 0` - } else if (!fieldDef.optional && !fieldDef.repeated && !fieldDef.proto2Required) { - let defaultValueTestGenerator = defaultValueTestGenerators[type] - - // proto3 singular fields should only be written out if they are not the default value - if (defaultValueTestGenerator != null) { - const jsTypeOverride = findJsTypeOverride(type, fieldDef) - - if (jsTypeOverride != null && defaultValueTestGeneratorsJsTypeOverrides[jsTypeOverride] != null) { - defaultValueTestGenerator = defaultValueTestGeneratorsJsTypeOverrides[jsTypeOverride] - } - - valueTest = `${defaultValueTestGenerator(`obj.${name}`)}` - } else if (type === 'enum') { - // handle enums - const def = findDef(fieldDef.type, messageDef, moduleDef) - - if (!isEnumDef(def)) { - throw new Error(`${fieldDef.type} was not enum def`) - } - - valueTest = `obj.${name} != null` - - // singular enums default to 0, but enums can be defined without a 0 - // value which is against the proto3 spec but is tolerated - if (Object.values(def.values)[0] === 0) { - valueTest += ` && __${fieldDef.type}Values[obj.${name}] !== 0` - } - } - } - - function createWriteField (valueVar: string): () => string { - const id = (fieldDef.id << 3) | codecTypes[type] - - if (fieldDef.enum) { - const def = findDef(fieldDef.type, messageDef, moduleDef) - - if (!isEnumDef(def)) { - throw new Error(`${fieldDef.type} was not enum def`) - } - } - - let writeField = (): string => { - const encoderGenerator = encoderGenerators[type] - const jsTypeOverride = findJsTypeOverride(type, fieldDef) - - return `w.uint32(${id}) - ${encoderGenerator == null ? `${codec}.encode(${valueVar}, w)` : encoderGenerator(valueVar, jsTypeOverride)}` - } - - if (type === 'message') { - // message fields are only written if they have values. But if a message - // is part of a repeated field, and consists of only default values it - // won't be written, so write a zero-length buffer if that's the case - writeField = (): string => `w.uint32(${id}) - ${typeName}.codec().encode(${valueVar}, w)` - } - - return writeField - } - - let writeField = createWriteField(`obj.${name}`) - - if (fieldDef.repeated) { - if (fieldDef.map) { - writeField = () => ` - for (const [key, value] of obj.${name}.entries()) { - ${ - createWriteField('{ key, value }')() - .split('\n') - .map(s => { - const trimmed = s.trim() - - return trimmed === '' ? trimmed : ` ${s}` - }) - .join('\n') - } - } - `.trim() - } else { - writeField = () => ` - for (const value of obj.${name}) { - ${ - createWriteField('value')() - .split('\n') - .map(s => { - const trimmed = s.trim() - - return trimmed === '' ? trimmed : ` ${s}` - }) - .join('\n') - } - } - `.trim() - } - } - - return ` - if (${valueTest}) { - ${writeField()} - }` - }).join('\n') - - const enforceOneOfEncoding = createOneOfEncoding(messageDef) - const enforceOneOfDecoding = createOneOfDecoding(messageDef) - const streamEvents: StreamEvent[] = [] - - const decodeFields = Object.entries(fields) - .map(([fieldName, fieldDef]) => { - function createReadField (fieldName: string, fieldDef: FieldDef): string { - let codec: string = encoders[fieldDef.type] - let type: string = fieldDef.type - - if (codec == null) { - if (fieldDef.enum) { - moduleDef.addImport('protons-runtime', 'enumeration') - type = 'enum' - } else { - moduleDef.addImport('protons-runtime', 'message') - type = 'message' - } - - const typeName = findJsTypeName(fieldDef.type, messageDef, moduleDef, fieldDef) - codec = `${typeName}.codec()` - } - - // override setting type on js object - const jsTypeOverride = findJsTypeOverride(fieldDef.type, fieldDef) - - let fieldOpts = '' - - if (fieldDef.message) { - let suffix = '' - - if (fieldDef.repeated) { - suffix = '$' - } - - fieldOpts = `, { - limits: opts.limits?.${fieldName}${suffix} - }` - } - - if (fieldDef.map) { - fieldOpts = `, { - limits: { - value: opts.limits?.${fieldName}$value - } - }` - - // do not pass limit opts to map value types that are enums or - // primitives - only support messages - if (types[fieldDef.valueType] != null) { - // primmitive type - fieldOpts = '' - } else { - const valueType = findDef(fieldDef.valueType, messageDef, moduleDef) - - if (isEnumDef(valueType)) { - // enum type - fieldOpts = '' - } - } - } - - const parseValue = `${decoderGenerators[type] == null - ? `${codec}.decode(reader${type === 'message' - ? `, reader.uint32()${fieldOpts}` - : ''})` - : decoderGenerators[type](jsTypeOverride)}` - - if (fieldDef.map) { - moduleDef.addImport('protons-runtime', 'MaxSizeError') - - let limit = ` - if (opts.limits?.${fieldName} != null && obj.${fieldName}.size === opts.limits.${fieldName}) { - throw new MaxSizeError('Decode error - map field "${fieldName}" had too many elements') - } -` - - if (fieldDef.lengthLimit != null) { - limit += ` - if (obj.${fieldName}.size === ${fieldDef.lengthLimit}) { - throw new MaxSizeError('Decode error - map field "${fieldName}" had too many elements') - } -` - } - - return `case ${fieldDef.id}: {${limit} - const entry = ${parseValue} - obj.${fieldName}.set(entry.key, entry.value) - break - }` - } else if (fieldDef.repeated) { - moduleDef.addImport('protons-runtime', 'MaxLengthError') - - let limit = ` - if (opts.limits?.${fieldName} != null && obj.${fieldName}.length === opts.limits.${fieldName}) { - throw new MaxLengthError('Decode error - map field "${fieldName}" had too many elements') - } -` - - if (fieldDef.lengthLimit != null) { - limit += ` - if (obj.${fieldName}.length === ${fieldDef.lengthLimit}) { - throw new MaxLengthError('Decode error - repeated field "${fieldName}" had too many elements') - } -` - } - - return `case ${fieldDef.id}: {${limit} - obj.${fieldName}.push(${parseValue}) - break - }` - } - - return `case ${fieldDef.id}: { - obj.${fieldName} = ${parseValue} - break - }` - } - - return createReadField(fieldName, fieldDef) - }) - .join('\n ') - - const streamFields = Object.entries(fields) - .map(([fieldName, fieldDef]) => { - let valueDef = `${findJsTypeName(fieldDef.type, messageDef, moduleDef, fieldDef)}${fieldDef.repeated ? '[]' : ''}` - - if (fieldDef.map) { - valueDef = `Map<${findJsTypeName(fieldDef.keyType, messageDef, moduleDef, fieldDef)}, ${findJsTypeName(fieldDef.valueType, messageDef, moduleDef, fieldDef)}>` - } - - streamEvents.push({ - name: `${messageDef.name}${camelize(fieldName)}FieldEvent`, - fields: [ - `field: '${fieldName}'`, - `value: ${valueDef}` - ], - collection: fieldDef.map || fieldDef.repeated - }) - - if (fieldDef.map) { - streamEvents.push({ - name: `${messageDef.name}${camelize(fieldName)}EntryEvent`, - fields: [ - `field: '${fieldName}$entry'`, - `key: ${findJsTypeName(fieldDef.keyType, messageDef, moduleDef, fieldDef)}`, - `value: ${findJsTypeName(fieldDef.valueType, messageDef, moduleDef, fieldDef)}` - ], - collection: false - }) - } else if (fieldDef.repeated) { - streamEvents.push({ - name: `${messageDef.name}${camelize(fieldName)}ValueEvent`, - fields: [ - `field: '${fieldName}$value'`, - 'index: number', - `value: ${findJsTypeName(fieldDef.type, messageDef, moduleDef, fieldDef)}` - ], - collection: false - }) - } - - function createStreamField (fieldName: string, fieldDef: FieldDef): string { - let codec: string = encoders[fieldDef.type] - let type: string = fieldDef.type - - if (codec == null) { - if (fieldDef.enum) { - moduleDef.addImport('protons-runtime', 'enumeration') - type = 'enum' - } else { - moduleDef.addImport('protons-runtime', 'message') - type = 'message' - } - - const typeName = findJsTypeName(fieldDef.type, messageDef, moduleDef, fieldDef) - codec = `${typeName}.codec()` - } - - // override setting type on js object - const jsTypeOverride = findJsTypeOverride(fieldDef.type, fieldDef) - - let fieldOpts = '' - - if (fieldDef.message) { - let suffix = '' - - if (fieldDef.repeated) { - suffix = '$' - } - - fieldOpts = `, { - limits: opts.limits?.${fieldName}${suffix} - }` - } - - if (fieldDef.map) { - fieldOpts = `, { - limits: { - value: opts.limits?.${fieldName}$value - } - }` - - // do not pass limit opts to map value types that are enums or - // primitives - only support messages - if (types[fieldDef.valueType] != null) { - // primmitive type - fieldOpts = '' - } else { - const valueType = findDef(fieldDef.valueType, messageDef, moduleDef) - - if (isEnumDef(valueType)) { - // enum type - fieldOpts = '' - } - } - } - - const parseValue = `${decoderGenerators[type] == null - ? `${codec}.decode(reader${type === 'message' - ? `, reader.uint32()${fieldOpts}` - : ''})` - : decoderGenerators[type](jsTypeOverride)}` - - if (fieldDef.map) { - moduleDef.addImport('protons-runtime', 'MaxSizeError') - - let limit = ` - if (opts.limits?.${fieldName} != null && (opts.emitCollections === true ? obj.${fieldName}.size === opts.limits.${fieldName} : obj.${fieldName} === opts.limits.${fieldName})) { - throw new MaxSizeError('Decode error - map field "${fieldName}" had too many elements') - } -` - - if (fieldDef.lengthLimit != null) { - limit += ` - if (opts.emitCollections === true ? obj.${fieldName}.size === ${fieldDef.lengthLimit} : obj.${fieldName} === ${fieldDef.lengthLimit}) { - throw new MaxSizeError('Decode error - map field "${fieldName}" had too many elements') - } -` - } - - return `case ${fieldDef.id}: {${limit} - const entry = ${parseValue} - - yield { - field: '${fieldName}', - key: entry.key, - value: entry.value - } - - if (opts.emitCollections === true) { - obj.${fieldName}.set(entry.key, entry.value) - } else { - obj.${fieldName}++ - } - - break - }` - } else if (fieldDef.repeated) { - moduleDef.addImport('protons-runtime', 'MaxLengthError') - - let limit = ` - if (opts.limits?.${fieldName} != null && (opts.emitCollections === true ? obj.${fieldName}.length === opts.limits.${fieldName} : obj.${fieldName} === opts.limits.${fieldName})) { - throw new MaxLengthError('Decode error - map field "${fieldName}" had too many elements') - } -` - - if (fieldDef.lengthLimit != null) { - limit += ` - if (opts.emitCollections === true ? obj.${fieldName}.length === ${fieldDef.lengthLimit} : obj.${fieldName} === ${fieldDef.lengthLimit}) { - throw new MaxLengthError('Decode error - repeated field "${fieldName}" had too many elements') - } -` - } - - return `case ${fieldDef.id}: {${limit} - const value = ${parseValue} - - yield { - field: '${fieldName}$value', - index: opts.emitCollections === true ? obj.${fieldName}.length : obj.${fieldName}, - value - } - - if (opts.emitCollections === true) { - obj.${fieldName}.push(value) - } else { - obj.${fieldName}++ - } - - break - }` - } - - return `case ${fieldDef.id}: { - yield { - field: '${fieldName}', - value: ${parseValue} - } - break - }` - } - - return createStreamField(fieldName, fieldDef) - }) - .join('\n ') - - interfaceCodecDef = ` - let _codec: Codec<${messageDef.name}, ${messageDef.name}StreamEvent, ${messageDef.name}StreamCollectionsEvent> - - export const codec = (): Codec<${messageDef.name}, ${messageDef.name}StreamEvent, ${messageDef.name}StreamCollectionsEvent> => { - if (_codec == null) { - _codec = message<${messageDef.name}, ${messageDef.name}StreamEvent, ${messageDef.name}StreamCollectionsEvent>((obj, w, opts = {}) => { - if (opts.lengthDelimited !== false) { - w.fork() - } -${enforceOneOfEncoding}${encodeFields === '' ? '' : `${encodeFields}\n`} - if (opts.lengthDelimited !== false) { - w.ldelim() - } - }, (reader, length, opts = {}) => { - const obj: any = {${createDefaultObject(fields, messageDef, moduleDef)}} - - const end = length == null ? reader.len : reader.pos + length - - while (reader.pos < end) { - const tag = reader.uint32() - - switch (tag >>> 3) {${decodeFields === '' ? '' : `\n ${decodeFields}`} - default: { - reader.skipType(tag & 7) - break - } - } - } -${enforceOneOfDecoding === '' ? '' : `${enforceOneOfDecoding}\n`} - return obj - }, function * (reader, length, opts = {}) { - let obj: any - - if (opts.emitCollections === true) { - obj = {${createDefaultObject(fields, messageDef, moduleDef, ' ')}} - } else { - obj = {${createLimitObject(fields)}} - } - - const end = length == null ? reader.len : reader.pos + length - - while (reader.pos < end) { - const tag = reader.uint32() - - switch (tag >>> 3) {${streamFields === '' ? '' : `\n ${streamFields}`} - default: { - reader.skipType(tag & 7) - break - } - } - } -${enforceOneOfDecoding === '' ? '' : `${enforceOneOfDecoding}\n`} - if (opts.emitCollections === true) { - for (const [key, value] of Object.entries(obj)) { - if (Array.isArray(value) || value instanceof Map) { - yield { - field: key, - value - } - } - } - } - }) - } - - return _codec - } - - ${streamEvents.map(evt => `export interface ${evt.name} { - ${evt.fields.join('\n ')} - }`).join('\n\n ')} - - export type ${messageDef.name}StreamEvent = ${interfacesOrEmpty(streamEvents.filter(evt => !evt.collection))} - export type ${messageDef.name}StreamCollectionsEvent = ${interfacesOrEmpty(streamEvents.filter(evt => evt.collection))} - - export function encode (obj: Partial<${messageDef.name}>): Uint8Array { - return encodeMessage(obj, ${messageDef.name}.codec()) - } - - export function decode (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions<${messageDef.name}>): ${messageDef.name} { - return decodeMessage(buf, ${messageDef.name}.codec(), opts) - } - - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions<${messageDef.name}>): Generator<${messageDef.name}StreamEvent> - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions<${messageDef.name}>): Generator<${messageDef.name}StreamCollectionsEvent> - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { - return streamMessage(buf, ${messageDef.name}.codec(), opts) - }` - - return ` -${interfaceDef} - -export namespace ${messageDef.name} { - ${`${nested}${nested !== '' && interfaceCodecDef !== '' ? '\n' : ''}${interfaceCodecDef}`.trim()} -} -`.trimStart() -} - -interface Import { - symbol: string - alias?: string - type: boolean -} - -class ModuleDef { - imports: Map - types: Set - compiled: string[] - globals: Record - - constructor () { - this.imports = new Map() - this.types = new Set() - this.compiled = [] - this.globals = {} - } - - addImport (module: string, symbol: string, alias?: string): void { - const defs = this._findDefs(module) - - for (const def of defs) { - // check if we already have a definition for this symbol - if (def.symbol === symbol) { - if (alias !== def.alias) { - throw new Error(`Type symbol ${symbol} imported from ${module} with alias ${def.alias} does not match alias ${alias}`) - } - - // if it was a type before it's not now - def.type = false - return - } - } - - defs.push({ - symbol, - alias, - type: false - }) - } - - addTypeImport (module: string, symbol: string, alias?: string): void { - const defs = this._findDefs(module) - - for (const def of defs) { - // check if we already have a definition for this symbol - if (def.symbol === symbol) { - if (alias !== def.alias) { - throw new Error(`Type symbol ${symbol} imported from ${module} with alias ${def.alias} does not match alias ${alias}`) - } - - return - } - } - - defs.push({ - symbol, - alias, - type: true - }) - } - - _findDefs (module: string): Import[] { - let defs = this.imports.get(module) - - if (defs == null) { - defs = [] - this.imports.set(module, defs) - } - - return defs - } -} - -function defineModule (def: ClassDef, flags: Flags): ModuleDef { - const moduleDef = new ModuleDef() - const defs = def.nested - - if (defs == null) { - throw new NoMessagesFoundError('No top-level messages found in protobuf') - } - - function defineMessage (defs: Record, parent?: ClassDef, flags?: Flags): void { - for (const className of Object.keys(defs)) { - const classDef = defs[className] - - classDef.name = className - classDef.parent = parent - classDef.fullName = parent == null ? className : `${parent.fullName}.${className}` - - if (classDef.nested != null) { - defineMessage(classDef.nested, classDef) - } - - if (classDef.fields != null) { - for (const name of Object.keys(classDef.fields)) { - const fieldDef = classDef.fields[name] - fieldDef.repeated = fieldDef.rule === 'repeated' - fieldDef.optional = !fieldDef.repeated && fieldDef.options?.proto3_optional === true - fieldDef.map = fieldDef.keyType != null - fieldDef.lengthLimit = fieldDef.options?.['(protons.options).limit'] - fieldDef.proto2Required = false - - if (fieldDef.rule === 'required') { - const message = `field "${name}" is required, this is not allowed in proto3. Please convert your proto2 definitions to proto3 - see https://github.com/ipfs/protons/wiki/Required-fields-and-protobuf-3` - - if (flags?.strict === true) { - throw new ParseError(message) - } else { - fieldDef.proto2Required = true - - // eslint-disable-next-line no-console - console.info(`[WARN] ${message}`) - } - } - } - } - - if (parent == null) { - moduleDef.globals[className] = classDef - } - } - } - - function updateTypes (defs: Record, parent?: ClassDef): void { - for (const className of Object.keys(defs)) { - const classDef = defs[className] - - if (classDef.nested != null) { - updateTypes(classDef.nested, classDef) - } - - if (classDef.fields != null) { - for (const name of Object.keys(classDef.fields)) { - const fieldDef = classDef.fields[name] - if (types[fieldDef.type] == null) { - const def = findDef(fieldDef.type, classDef, moduleDef) - - fieldDef.enum = isEnumDef(def) - fieldDef.message = !fieldDef.enum - - if (fieldDef.message && !fieldDef.repeated) { - // the default type for a message is unset so they are always optional - // https://developers.google.com/protocol-buffers/docs/proto3#default - fieldDef.optional = true - } - } - } - } - } - } - - defineMessage(defs, undefined, flags) - - // set enum/message fields now all messages have been defined - updateTypes(defs) - - for (const className of Object.keys(defs)) { - const classDef = defs[className] - - moduleDef.compiled.push(compileMessage(classDef, moduleDef, flags)) - } - - return moduleDef -} - -interface Flags { +export interface Flags { /** * Specifies an output directory */ @@ -1516,198 +232,9 @@ export async function generate (source: string, flags: Flags): Promise { } const def = JSON.parse(json) - - for (const [className, classDef] of Object.entries(def.nested ?? {})) { - for (const [fieldName, fieldDef] of Object.entries(classDef.fields ?? {})) { - if (fieldDef.keyType == null) { - continue - } - - // https://developers.google.com/protocol-buffers/docs/proto3#backwards_compatibility - const mapEntryType = `${className}$${fieldName}Entry` - - classDef.nested = classDef.nested ?? {} - classDef.nested[mapEntryType] = { - fields: { - key: { - type: fieldDef.keyType, - id: 1 - }, - value: { - type: fieldDef.type, - id: 2 - } - } - } - - fieldDef.valueType = fieldDef.type - fieldDef.type = mapEntryType - fieldDef.rule = 'repeated' - } - - configureOnOfs(classDef) - } - - const moduleDef = defineModule(def, flags) - - const ignores = [ - '/* eslint-disable import/export */', - '/* eslint-disable complexity */', - '/* eslint-disable @typescript-eslint/no-namespace */', - '/* eslint-disable @typescript-eslint/no-unnecessary-boolean-literal-compare */', - '/* eslint-disable @typescript-eslint/no-empty-interface */', - '/* eslint-disable import/consistent-type-specifier-style */', - '/* eslint-disable @typescript-eslint/no-unused-vars */', - '/* eslint-disable require-yield */' - ] - - const imports = [] - const importedModules = Array.from([...moduleDef.imports.entries()]) - .sort((a, b) => { - return a[0].localeCompare(b[0]) - }) - .sort((a, b) => { - const aAllTypes = a[1].reduce((acc, curr) => { - return acc && curr.type - }, true) - - const bAllTypes = b[1].reduce((acc, curr) => { - return acc && curr.type - }, true) - - if (aAllTypes && !bAllTypes) { - return 1 - } - - if (!aAllTypes && bAllTypes) { - return -1 - } - - return 0 - }) - - // add imports - for (const imp of importedModules) { - const symbols = imp[1] - .filter(imp => !imp.type) - .sort((a, b) => { - return a.symbol.localeCompare(b.symbol) - }).map(imp => { - return `${imp.symbol}${imp.alias != null ? ` as ${imp.alias}` : ''}` - }).join(', ') - - if (symbols.length > 0) { - imports.push(`import { ${symbols} } from '${imp[0]}'`) - } - } - - // add type imports - for (const imp of importedModules) { - const symbols = imp[1] - .filter(imp => imp.type) - .sort((a, b) => { - return a.symbol.localeCompare(b.symbol) - }).map(imp => { - return `${imp.symbol}${imp.alias != null ? ` as ${imp.alias}` : ''}` - }).join(', ') - - if (symbols.length > 0) { - imports.push(`import type { ${symbols} } from '${imp[0]}'`) - } - } - - const lines = [ - ...ignores, - '', - ...imports, - '', - ...moduleDef.compiled - ] - - const content = lines.join('\n').trim() + const module = new Module(def, flags) + const content = module.compile() const outputPath = pathWithExtension(source, '.ts', flags.output) await fs.writeFile(outputPath, content + '\n') } - -function configureOnOfs (classDef: any): void { - const oneOfs: Record = classDef.oneofs ?? {} - - for (const [, { oneof: fields }] of Object.entries(oneOfs)) { - fields.forEach(field => { - classDef.fields[field].options ??= {} - classDef.fields[field].options.proto3_optional = true - classDef.fields[field].oneof = fields - }) - } - - const oneofs: Record = classDef.oneofs ?? {} - - // reverse order of oneofs as spec says last field overwrites all others - classDef.oneofs = Object.values(oneofs).map(({ oneof }) => oneof.reverse()) - - for (const nestedDef of Object.values(classDef.nested ?? {})) { - configureOnOfs(nestedDef) - } -} - -function createOneOfEncoding (messageDef: ClassDef): string { - if (messageDef.oneofs == null) { - return '' - } - - let oneofs = messageDef.oneofs.map(fields => { - if (fields.length < 2) { - return '' - } - - let oneof = '' - - for (const name of fields) { - oneof += ` - if (obj.${name} != null) { -${fields - .filter(field => field !== name) - .map(name => ` obj.${name} = undefined`).join('\n')} - } -` - } - - return oneof.trimEnd() - }).join('\n').trimEnd() - - if (oneofs !== '') { - oneofs = ` - obj = { ...obj } -${oneofs} -` - } - - return oneofs -} - -function createOneOfDecoding (messageDef: ClassDef): string { - if (messageDef.oneofs == null) { - return '' - } - - return messageDef.oneofs.map(fields => { - if (fields.length < 2) { - return '' - } - - let oneof = '' - - for (const name of fields) { - oneof += ` - if (obj.${name} != null) { -${fields - .filter(field => field !== name) - .map(name => ` delete obj.${name}`).join('\n')} - } -` - } - - return oneof.trimEnd() - }).join('\n').trimEnd() -} diff --git a/packages/protons/src/types/enum.ts b/packages/protons/src/types/enum.ts new file mode 100644 index 0000000..856c06d --- /dev/null +++ b/packages/protons/src/types/enum.ts @@ -0,0 +1,108 @@ +import { ParseError } from 'protons-runtime' +import type { Parent, Type } from './index.ts' +import type { Field } from '../fields/field.ts' + +export interface EnumDef { + values: Record +} + +export function isEnumDef (obj?: any): obj is EnumDef { + return obj?.values != null +} + +export class Enum implements Type { + public pbType: string + public jsType: string + public values: Map + public lowestValue: number + public lowestValueName: string + + constructor (pbType: string, jsType: string, def: EnumDef) { + this.pbType = pbType + this.jsType = jsType + this.values = new Map(Object.entries(def.values)) + + // select lowest-value enum - should be 0 but it's not guaranteed + const lowestValue = [...this.values.entries()] + .sort((a, b) => { + if (a[1] < b[1]) { + return 1 + } + + if (a[1] > b[1]) { + return -1 + } + + return 0 + }) + .pop() + + if (lowestValue == null) { + throw new Error(`Could not find lowest enum value for ${pbType}`) + } + + this.lowestValue = lowestValue[1] + this.lowestValueName = lowestValue[0] + } + + init (): void { + + } + + getDecoder (field: Field): string { + return `${this.jsType}.codec().decode(reader)` + } + + getEncoder (field: Field, accessor: string): string { + return `${this.jsType}.codec().encode(${accessor}, w)` + } + + getValueTest (field: Field, accessor: string): string { + if (field.proto2Required) { + return 'true' + } + + const valueTest = `${accessor} != null` + + // singular enums default to 0, but enums can be defined without a 0 + // value which is against the proto3 spec but is tolerated + if (field.optional || field.proto2Required) { + return valueTest + } + + return `${valueTest} && __${field.type}Values[${accessor}] !== 0` + } + + public compile (parent: Parent): string { + // import required modules + parent.addImport('protons-runtime', 'enumeration') + + // check that the enum def values start from 0 + if ([...this.values.values()][0] !== 0) { + const message = `enum ${this.pbType} does not contain a value that maps to zero as it's first element, this is required in proto3 - see https://protobuf.dev/programming-guides/proto3/#enum` + + if (parent.flags.strict === true) { + throw new ParseError(message) + } else { + // eslint-disable-next-line no-console + console.info(`[WARN] ${message}`) + } + } + + return ` +export enum ${this.pbType} { + ${[...this.values.keys()].map(key => `${key} = '${key}'`).join(',\n ')} +} + +enum __${this.pbType}Values { + ${[...this.values.entries()].map(([key, value]) => `${key} = ${value}`).join(',\n ')} +} + +export namespace ${this.pbType} { + export const codec = (): Codec<${this.pbType}> => { + return enumeration<${this.pbType}>(__${this.pbType}Values) + } +} +`.trimStart() + } +} diff --git a/packages/protons/src/types/index.ts b/packages/protons/src/types/index.ts new file mode 100644 index 0000000..439e11c --- /dev/null +++ b/packages/protons/src/types/index.ts @@ -0,0 +1,20 @@ +import type { Field } from '../fields/field.ts' +import type { Flags } from '../index.ts' +import type { Module } from './module.ts' + +export interface Type { + jsType: string + pbType: string + init(module: Module): void + getDecoder(field: Field, indent?: string): string + getEncoder(field: Field, accessor: string): string + getValueTest(field: Field, accessor: string): string +} + +export interface Parent { + flags: Flags + findType (type: string, jsOverride?: 'string' | 'number'): Type + addImport (module: string, symbol: string, alias?: string): void + addTypeImport (module: string, symbol: string, alias?: string): void + addEslintIgnore (rule: string): void +} diff --git a/packages/protons/src/types/message.ts b/packages/protons/src/types/message.ts new file mode 100644 index 0000000..7e49e4a --- /dev/null +++ b/packages/protons/src/types/message.ts @@ -0,0 +1,495 @@ +import { ArrayField, isArrayFieldDef } from '../fields/array-field.ts' +import { EnumField } from '../fields/enum-field.ts' +import { Field } from '../fields/field.ts' +import { isMapFieldDef, MapField } from '../fields/map-field.ts' +import { MessageField } from '../fields/message-field.ts' +import { Enum } from './enum.ts' +import { isPrimitiveType, Primitive } from './primitive.ts' +import type { EnumDef } from './enum.ts' +import type { Parent, Type } from './index.ts' +import type { FieldDef } from '../fields/field.ts' +import type { Flags } from '../index.ts' + +interface StreamEvent { + name: string + fields: string[] + type: 'field' + | 'collection-primitive-member' + | 'collection-message-member-field' + | 'sub-message-field' + | 'sub-message-collection-primitive-member' + | 'sub-message-collection-message-member-field' +} + +function camelize (input: string): string { + return `${input.substring(0, 1).toUpperCase()}${input.substring(1)}` +} + +export interface MessageDef { + fields?: Record + oneofs?: Record + nested?: Record +} + +export function isMessageDef (obj?: any): obj is MessageDef { + return obj?.fields != null +} + +export class Message implements Type { + public pbType: string + public jsType: string + public fields: Field[] + public oneOfs: string[][] + public nested: Record + private def: MessageDef + private parent: Parent + + constructor (pbType: string, jsType: string, def: MessageDef, parent: Parent) { + this.pbType = pbType + this.jsType = jsType + this.oneOfs = [] + this.nested = {} + this.fields = [] + this.def = def + this.parent = parent + + def.fields ??= {} + def.nested ??= {} + def.oneofs ??= {} + + // create extra message types for map type backwards compatibility + // https://developers.google.com/protocol-buffers/docs/proto3#backwards + for (const [fieldName, fieldDef] of Object.entries(def.fields)) { + if (fieldDef.keyType == null) { + continue + } + + const mapEntryType = `${this.pbType}$${fieldName}Entry` + + def.nested[mapEntryType] = { + fields: { + key: { + type: fieldDef.keyType, + id: 1 + }, + value: { + type: fieldDef.type, + id: 2 + } + } + } + + fieldDef.valueType = fieldDef.type + fieldDef.type = mapEntryType + fieldDef.rule = 'repeated' + } + + Object.entries(def.nested ?? {}).forEach(([name, def]) => { + const fullName = `${this.jsType}.${name}` + + if (isMessageDef(def)) { + this.nested[name] = new Message(name, fullName, def, this) + } else { + this.nested[name] = new Enum(name, fullName, def) + } + }) + + for (const [, { oneof: fields }] of Object.entries(def.oneofs)) { + for (const field of fields) { + if (def.fields[field] == null) { + continue + } + + def.fields[field].options ??= {} + def.fields[field].options.proto3_optional = true + def.fields[field].oneof = fields + } + } + + // reverse order of oneofs as spec says last field overwrites all others + this.oneOfs = Object.values(def.oneofs).map(({ oneof }) => oneof.reverse()) + } + + init (): void { + for (const [name, fieldDef] of Object.entries(this.def.fields ?? {})) { + if (isMapFieldDef(fieldDef)) { + this.fields.push(new MapField(name, fieldDef, this)) + } else if (isArrayFieldDef(fieldDef)) { + this.fields.push(new ArrayField(name, fieldDef, this)) + } else { + const type = this.findType(fieldDef.type) + + if (type instanceof Enum) { + this.fields.push(new EnumField(name, fieldDef, this)) + } else if (type instanceof Primitive) { + this.fields.push(new Field(name, fieldDef, this)) + } else { + this.fields.push(new MessageField(name, fieldDef, this)) + } + } + } + + Object.values(this.nested).forEach(type => type.init()) + } + + findType (jsType: string, override?: 'string' | 'number'): Type { + const type = this.nested[override ?? jsType] + + if (type == null) { + return this.parent.findType(jsType, override) + } + + return type + } + + addImport (module: string, symbol: string, alias?: string): void { + this.parent.addImport(module, symbol, alias) + } + + addTypeImport (module: string, symbol: string, alias?: string): void { + this.parent.addTypeImport(module, symbol, alias) + } + + addEslintIgnore (rule: string): void { + this.parent.addEslintIgnore(rule) + } + + get flags (): Flags { + return this.parent.flags + } + + getDecoder (field: Field, indent = ''): string { + let opts = '' + + if (field instanceof MessageField) { + opts = `, { +${indent} limits: opts.limits?.${field.name} +${indent} }` + } else if (field instanceof ArrayField) { + opts = `, { +${indent} limits: opts.limits?.${field.name}$ +${indent} }` + } else if (field instanceof MapField) { + opts = `, { +${indent} limits: { +${indent} value: opts.limits?.${field.name}$value + } +${indent} }` + } + + return `${this.jsType}.codec().decode(reader, reader.uint32()${opts})` + } + + getEncoder (field: Field, accessor: string): string { + if (field instanceof ArrayField) { + // message fields are only written if they have values. But if a message + // is part of a repeated field, and consists of only default values it + // won't be written, so write a zero-length buffer if that's the case + // writeField = (): string => `w.uint32(${id}) + // ${type.jsType}.codec().encode(${valueVar}, w)` + } + + return `${this.jsType}.codec().encode(${accessor}, w)` + } + + getValueTest (field: Field): string { + return `obj.${field.name} != null` + } + + public compile (parent: Parent, indent: string = ''): string { + // import required modules + parent.addImport('protons-runtime', 'encodeMessage') + parent.addImport('protons-runtime', 'decodeMessage') + parent.addImport('protons-runtime', 'streamMessage') + parent.addImport('protons-runtime', 'message') + parent.addTypeImport('protons-runtime', 'Codec') + parent.addTypeImport('protons-runtime', 'DecodeOptions') + parent.addTypeImport('uint8arraylist', 'Uint8ArrayList') + + let nested = '' + + if (this.nested != null && [...Object.values(this.nested)].length > 0) { + nested += Object.values(this.nested) + .map(def => def.compile(this, `${indent} `).trim()) + .join('\n\n') + nested = nested.split('\n').join('\n ') + nested = ` + ${nested} +` + } + + const interfaceFields = this.fields.map(field => field.getInterfaceField(this)) + .join('\n ') + .trim() + + let interfaceDef = '' + let interfaceCodecDef = '' + + if (interfaceFields === '') { + interfaceDef = ` +export interface ${this.pbType} {}` + } else { + interfaceDef = ` +export interface ${this.pbType} { + ${interfaceFields} +}` + } + + const enforceOneOfEncoding = this.createOneOfEncoding() + const enforceOneOfDecoding = this.createOneOfDecoding() + const streamEvents = this.getStreamEvents() + + const encodeFields = this.fields.map(field => field.getEncoder(this)) + const decodeFields = this.fields.map(field => field.getDecoder(this)) + const streamFields = this.fields.map(field => field.getStreamingDecoder(this)) + + const streamGeneratorEvents = streamEvents.map(evt => evt.name) + + if (streamGeneratorEvents.length === 0) { + this.addEslintIgnore('require-yield') + streamGeneratorEvents.push('{}') + } + + interfaceCodecDef = ` + let _codec: Codec<${this.pbType}> + + export const codec = (): Codec<${this.pbType}> => { + if (_codec == null) { + _codec = message<${this.pbType}>((obj, w, opts = {}) => { + if (opts.lengthDelimited !== false) { + w.fork() + }${enforceOneOfEncoding}${this.formatFields(encodeFields)} + + if (opts.lengthDelimited !== false) { + w.ldelim() + } + }, (reader, length, opts = {}) => { + const obj: any = {${this.createDefaultObject()}} + + const end = length == null ? reader.len : reader.pos + length + + while (reader.pos < end) { + const tag = reader.uint32() + + switch (tag >>> 3) {${this.formatFields(decodeFields, '\n ')} + default: { + reader.skipType(tag & 7) + break + } + } + } +${enforceOneOfDecoding === '' ? '' : `${enforceOneOfDecoding}\n`} + return obj + }, function * (reader, length, prefix, opts = {}) { + ${this.createLimitObject()}const end = length == null ? reader.len : reader.pos + length + + while (reader.pos < end) { + const tag = reader.uint32() + + switch (tag >>> 3) {${this.formatFields(streamFields, '\n ')} + default: { + reader.skipType(tag & 7) + break + } + } + } + }) + } + + return _codec + }${this.formatStreamEvents(streamEvents)} + + export function encode (obj: Partial<${this.pbType}>): Uint8Array { + return encodeMessage(obj, ${this.pbType}.codec()) + } + + export function decode (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions<${this.pbType}>): ${this.pbType} { + return decodeMessage(buf, ${this.pbType}.codec(), opts) + } + + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions<${this.pbType}>): Generator<${streamGeneratorEvents.join(' | ')}> { + return streamMessage(buf, ${this.pbType}.codec(), opts) + }` + + return ` +${interfaceDef} + +export namespace ${this.pbType} {${nested}${interfaceCodecDef.trimEnd()} +} +`.trimStart() + } + + private createOneOfEncoding (): string { + let oneOfs = this.oneOfs.map(fields => { + if (fields.length < 2) { + return '' + } + + let oneOf = '' + + for (const name of fields) { + oneOf += ` + if (obj.${name} != null) { +${fields + .filter(field => field !== name) + .map(name => ` obj.${name} = undefined`).join('\n')} + } +` + } + + return oneOf.trimEnd() + }).join('\n').trimEnd() + + if (oneOfs !== '') { + oneOfs = ` + + obj = { ...obj } +${oneOfs}` + } + + return oneOfs + } + + private createOneOfDecoding (): string { + return this.oneOfs.map(fields => { + if (fields.length < 2) { + return '' + } + + let oneOf = '' + + for (const name of fields) { + oneOf += ` + if (obj.${name} != null) { +${fields + .filter(field => field !== name) + .map(name => ` delete obj.${name}`).join('\n')} + } +` + } + + return oneOf.trimEnd() + }).join('\n').trimEnd() + } + + createDefaultObject (indent = ''): string { + const output = this.fields + .map((field) => field.getDefaultField(this)) + .filter(Boolean) + .join(`,\n ${indent}`) + + if (output !== '') { + return ` + ${indent}${output} + ${indent}` + } + + return '' + } + + createLimitObject (): string { + const output = this.fields.map(field => field.getLimitField()) + .filter(Boolean) + .join(',\n ') + + if (output !== '') { + return `const obj = { + ${output} + } + + ` + } + + return '' + } + + formatStreamEvents (streamEvents: StreamEvent[]): string { + if (streamEvents.length === 0) { + return '' + } + + return ` + + ${streamEvents.map(evt => `export interface ${evt.name} { + ${evt.fields.join('\n ')} + }`).join('\n\n ')}` + } + + formatFields (fields: string[], delimiter = '\n'): string { + if (fields.length === 0) { + return '' + } + + return ` + ${fields.join(delimiter)}` + } + + getStreamEvents (): StreamEvent[] { + const streamEvents: StreamEvent[] = [] + + this.fields.forEach(field => { + if (field instanceof MapField) { + const keyType = this.findType(field.keyType) + const valueType = this.findType(field.valueType) + + if (isPrimitiveType(valueType.pbType)) { + streamEvents.push({ + name: `${this.pbType}${camelize(field.name)}FieldEvent`, + fields: [ + `field: '${field.name}$entry'`, + `key: ${keyType.jsType}`, + `value: ${valueType.jsType}` + ], + type: 'collection-primitive-member' + }) + } + } else if (field instanceof ArrayField) { + const type = this.findType(field.type) + + if (isPrimitiveType(type.pbType)) { + streamEvents.push({ + name: `${this.pbType}${camelize(field.name)}FieldEvent`, + fields: [ + `field: '${field.name}$entry'`, + 'index: number', + `value: ${type.jsType}` + ], + type: 'collection-primitive-member' + }) + } + } else if (field instanceof MessageField) { + // include sub messages + streamEvents.push(...field.getMessage(this).getStreamEvents().map(evt => { + let type = evt.type + + if (evt.type === 'field') { + type = 'sub-message-field' + } else if (evt.type === 'collection-primitive-member') { + type = 'sub-message-collection-primitive-member' + } else if (evt.type === 'collection-message-member-field') { + type = 'sub-message-collection-message-member-field' + } + + return { + ...evt, + name: `${this.pbType}${camelize(field.name)}${evt.name}`, + type + } + })) + } else { + const type = this.findType(field.type) + + streamEvents.push({ + name: `${this.pbType}${camelize(field.name)}FieldEvent`, + fields: [ + `field: '${field.name}'`, + `value: ${type.jsType}` + ], + type: 'field' + }) + } + }) + + return streamEvents + } +} diff --git a/packages/protons/src/types/module.ts b/packages/protons/src/types/module.ts new file mode 100644 index 0000000..c9b99d9 --- /dev/null +++ b/packages/protons/src/types/module.ts @@ -0,0 +1,234 @@ +import { NoMessagesFoundError } from 'protons-runtime' +import { Enum, isEnumDef } from './enum.ts' +import { Message } from './message.ts' +import { Primitive } from './primitive.ts' +import type { EnumDef } from './enum.ts' +import type { MessageDef } from './message.ts' +import type { Flags } from '../index.ts' +import type { Type } from './index.ts' + +const types: Record = { + bool: 'boolean', + bytes: 'Uint8Array', + double: 'number', + fixed32: 'number', + fixed64: 'bigint', + float: 'number', + int32: 'number', + int64: 'bigint', + sfixed32: 'number', + sfixed64: 'bigint', + sint32: 'number', + sint64: 'bigint', + string: 'string', + uint32: 'number', + uint64: 'bigint' +} + +interface Import { + symbol: string + alias?: string + type: boolean +} + +export interface ModuleDef { + nested?: Record +} + +export class Module { + private imports: Map + private types: Record + private eslintIgnores: string[] + public flags: Flags + public globals: Array + + constructor (def: ModuleDef, flags: Flags) { + this.imports = new Map() + this.flags = flags + this.types = {} + this.globals = [] + this.eslintIgnores = [] + + Object.entries(types).forEach(([pbType, jsType]) => { + this.types[pbType] = new Primitive(pbType, jsType) + }) + + const defs = def.nested + + if (defs == null) { + throw new NoMessagesFoundError('No top-level messages found in protobuf') + } + + for (const [name, def] of Object.entries(defs)) { + let type: Message | Enum + + if (isEnumDef(def)) { + type = new Enum(name, name, def) + } else { + type = new Message(name, name, def, this) + } + + this.globals.push(type) + this.types[name] = type + } + + this.globals.forEach(type => type.init()) + } + + addImport (module: string, symbol: string, alias?: string): void { + const defs = this._findDefs(module) + + for (const def of defs) { + // check if we already have a definition for this symbol + if (def.symbol === symbol) { + if (alias !== def.alias) { + throw new Error(`Type symbol ${symbol} imported from ${module} with alias ${def.alias} does not match alias ${alias}`) + } + + // if it was a type before it's not now + def.type = false + return + } + } + + defs.push({ + symbol, + alias, + type: false + }) + } + + addTypeImport (module: string, symbol: string, alias?: string): void { + const defs = this._findDefs(module) + + for (const def of defs) { + // check if we already have a definition for this symbol + if (def.symbol === symbol) { + if (alias !== def.alias) { + throw new Error(`Type symbol ${symbol} imported from ${module} with alias ${def.alias} does not match alias ${alias}`) + } + + return + } + } + + defs.push({ + symbol, + alias, + type: true + }) + } + + addEslintIgnore (rule: string): void { + if (this.eslintIgnores.includes(rule)) { + return + } + + this.eslintIgnores.push(rule) + } + + _findDefs (module: string): Import[] { + let defs = this.imports.get(module) + + if (defs == null) { + defs = [] + this.imports.set(module, defs) + } + + return defs + } + + compile (): string { + const compiled = this.globals.map(def => def.compile(this)).flat() + + // TODO: make these conditional + // const ignores: string[] = [ + // '/* eslint-disable import/export */', + // '/* eslint-disable complexity */', + // '/* eslint-disable @typescript-eslint/no-namespace */', + // '/* eslint-disable @typescript-eslint/no-unnecessary-boolean-literal-compare */', + // '/* eslint-disable @typescript-eslint/no-empty-interface */', + // '/* eslint-disable import/consistent-type-specifier-style */', + // '/* eslint-disable @typescript-eslint/no-unused-vars */', + // '/* eslint-disable require-yield */' + // ] + + const imports = [] + const importedModules = Array.from([...this.imports.entries()]) + .sort((a, b) => { + return a[0].localeCompare(b[0]) + }) + .sort((a, b) => { + const aAllTypes = a[1].reduce((acc, curr) => { + return acc && curr.type + }, true) + + const bAllTypes = b[1].reduce((acc, curr) => { + return acc && curr.type + }, true) + + if (aAllTypes && !bAllTypes) { + return 1 + } + + if (!aAllTypes && bAllTypes) { + return -1 + } + + return 0 + }) + + // add imports + for (const imp of importedModules) { + const symbols = imp[1] + .filter(imp => !imp.type) + .sort((a, b) => { + return a.symbol.localeCompare(b.symbol) + }).map(imp => { + return `${imp.symbol}${imp.alias != null ? ` as ${imp.alias}` : ''}` + }).join(', ') + + if (symbols.length > 0) { + imports.push(`import { ${symbols} } from '${imp[0]}'`) + } + } + + // add type imports + for (const imp of importedModules) { + const symbols = imp[1] + .filter(imp => imp.type) + .sort((a, b) => { + return a.symbol.localeCompare(b.symbol) + }).map(imp => { + return `${imp.symbol}${imp.alias != null ? ` as ${imp.alias}` : ''}` + }).join(', ') + + if (symbols.length > 0) { + imports.push(`import type { ${symbols} } from '${imp[0]}'`) + } + } + + return [ + ...this.eslintIgnores.map(rule => `/* eslint-disable ${rule} */`), + '', + ...imports, + '', + ...compiled + ] + .join('\n') + .split('\n') + .map((line) => line.trim() === '' ? '' : line) + .join('\n') + .trim() + } + + findType (jsType: string, override?: 'string' | 'number'): Type { + const type = this.types[override ?? jsType] + + if (type == null) { + throw new Error(`Type for "${jsType}"${override == null ? '' : ` (overridden to "${override}")`} not found in ${[...Object.keys(this.types)].join(', ')}`) + } + + return type + } +} diff --git a/packages/protons/src/types/primitive.ts b/packages/protons/src/types/primitive.ts new file mode 100644 index 0000000..6ca0d47 --- /dev/null +++ b/packages/protons/src/types/primitive.ts @@ -0,0 +1,204 @@ +import type { Type } from './index.ts' +import type { Field } from '../fields/field.ts' + +const decoderGenerators: Record string> = { + bool: () => 'reader.bool()', + bytes: () => 'reader.bytes()', + double: () => 'reader.double()', + fixed32: () => 'reader.fixed32()', + fixed64: (jsTypeOverride) => { + if (jsTypeOverride === 'number') { + return 'reader.fixed64Number()' + } + + if (jsTypeOverride === 'string') { + return 'reader.fixed64String()' + } + + return 'reader.fixed64()' + }, + float: () => 'reader.float()', + int32: () => 'reader.int32()', + int64: (jsTypeOverride) => { + if (jsTypeOverride === 'number') { + return 'reader.int64Number()' + } + + if (jsTypeOverride === 'string') { + return 'reader.int64String()' + } + + return 'reader.int64()' + }, + sfixed32: () => 'reader.sfixed32()', + sfixed64: (jsTypeOverride) => { + if (jsTypeOverride === 'number') { + return 'reader.sfixed64Number()' + } + + if (jsTypeOverride === 'string') { + return 'reader.sfixed64String()' + } + + return 'reader.sfixed64()' + }, + sint32: () => 'reader.sint32()', + sint64: (jsTypeOverride) => { + if (jsTypeOverride === 'number') { + return 'reader.sint64Number()' + } + + if (jsTypeOverride === 'string') { + return 'reader.sint64String()' + } + + return 'reader.sint64()' + }, + string: () => 'reader.string()', + uint32: () => 'reader.uint32()', + uint64: (jsTypeOverride) => { + if (jsTypeOverride === 'number') { + return 'reader.uint64Number()' + } + + if (jsTypeOverride === 'string') { + return 'reader.uint64String()' + } + + return 'reader.uint64()' + } +} + +const encoderGenerators: Record string> = { + bool: (val) => `w.bool(${val})`, + bytes: (val) => `w.bytes(${val})`, + double: (val) => `w.double(${val})`, + fixed32: (val) => `w.fixed32(${val})`, + fixed64: (val, jsTypeOverride) => { + if (jsTypeOverride === 'number') { + return `w.fixed64Number(${val})` + } + + if (jsTypeOverride === 'string') { + return `w.fixed64String(${val})` + } + + return `w.fixed64(${val})` + }, + float: (val) => `w.float(${val})`, + int32: (val) => `w.int32(${val})`, + int64: (val, jsTypeOverride) => { + if (jsTypeOverride === 'number') { + return `w.int64Number(${val})` + } + + if (jsTypeOverride === 'string') { + return `w.int64String(${val})` + } + + return `w.int64(${val})` + }, + sfixed32: (val) => `w.sfixed32(${val})`, + sfixed64: (val, jsTypeOverride) => { + if (jsTypeOverride === 'number') { + return `w.sfixed64Number(${val})` + } + + if (jsTypeOverride === 'string') { + return `w.sfixed64String(${val})` + } + + return `w.sfixed64(${val})` + }, + sint32: (val) => `w.sint32(${val})`, + sint64: (val, jsTypeOverride) => { + if (jsTypeOverride === 'number') { + return `w.sint64Number(${val})` + } + + if (jsTypeOverride === 'string') { + return `w.sint64String(${val})` + } + + return `w.sint64(${val})` + }, + string: (val) => `w.string(${val})`, + uint32: (val) => `w.uint32(${val})`, + uint64: (val, jsTypeOverride) => { + if (jsTypeOverride === 'number') { + return `w.uint64Number(${val})` + } + + if (jsTypeOverride === 'string') { + return `w.uint64String(${val})` + } + + return `w.uint64(${val})` + } +} + +interface DefaultValueTestGenerator { + (field: string): string +} + +const defaultValueTestGenerators: Record = { + bool: (field) => `(${field} != null && ${field} !== false)`, + bytes: (field) => `(${field} != null && ${field}.byteLength > 0)`, + double: (field) => `(${field} != null && ${field} !== 0)`, + fixed32: (field) => `(${field} != null && ${field} !== 0)`, + fixed64: (field) => `(${field} != null && ${field} !== 0n)`, + float: (field) => `(${field} != null && ${field} !== 0)`, + int32: (field) => `(${field} != null && ${field} !== 0)`, + int64: (field) => `(${field} != null && ${field} !== 0n)`, + sfixed32: (field) => `(${field} != null && ${field} !== 0)`, + sfixed64: (field) => `(${field} != null && ${field} !== 0n)`, + sint32: (field) => `(${field} != null && ${field} !== 0)`, + sint64: (field) => `(${field} != null && ${field} !== 0n)`, + string: (field) => `(${field} != null && ${field} !== '')`, + uint32: (field) => `(${field} != null && ${field} !== 0)`, + uint64: (field) => `(${field} != null && ${field} !== 0n)` +} + +const defaultValueTestGeneratorsJsTypeOverrides: Record = { + number: (field) => `(${field} != null && ${field} !== 0)`, + string: (field) => `(${field} != null && ${field} !== '')` +} + +export function isPrimitiveType (pbType: string): boolean { + return [...Object.keys(decoderGenerators)].includes(pbType) +} + +export class Primitive implements Type { + public jsType: string + public pbType: string + + constructor (pbType: string, jsType: string) { + this.jsType = jsType + this.pbType = pbType + } + + init (): void { + + } + + getDecoder (field: Field): string { + return decoderGenerators[this.pbType](field.jsTypeOverride) + } + + getValueTest (field: Field, accessor: string): string { + // proto3 singular fields should only be written out if they are not the default value + if (!field.optional && !field.proto2Required) { + if (field.jsTypeOverride != null) { + return defaultValueTestGeneratorsJsTypeOverrides[field.jsTypeOverride](accessor) + } + + return defaultValueTestGenerators[field.type](accessor) + } + + return `${accessor} != null` + } + + getEncoder (field: Field, accessor: string): string { + return encoderGenerators[this.pbType](accessor, field.jsTypeOverride) + } +} diff --git a/packages/protons/test/fixtures/basic.ts b/packages/protons/test/fixtures/basic.ts index 07526f0..94a62db 100644 --- a/packages/protons/test/fixtures/basic.ts +++ b/packages/protons/test/fixtures/basic.ts @@ -1,5 +1,7 @@ +/* eslint-disable require-yield */ + import { decodeMessage, encodeMessage, message, streamMessage } from 'protons-runtime' -import type { Codec, DecodeOptions, StreamingDecodeOptions, StreamingDecodeWithCollectionsOptions } from 'protons-runtime' +import type { Codec, DecodeOptions } from 'protons-runtime' import type { Uint8ArrayList } from 'uint8arraylist' export interface Basic { @@ -8,11 +10,11 @@ export interface Basic { } export namespace Basic { - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -57,17 +59,7 @@ export namespace Basic { } return obj - }, function * (reader, length, opts = {}) { - let obj: any - - if (opts.emitCollections === true) { - obj = { - num: 0 - } - } else { - obj = {} - } - + }, function * (reader, length, prefix, opts = {}) { const end = length == null ? reader.len : reader.pos + length while (reader.pos < end) { @@ -76,14 +68,14 @@ export namespace Basic { switch (tag >>> 3) { case 1: { yield { - field: 'foo', + field: `${prefix != null ? `${prefix}.` : ''}foo`, value: reader.string() } break } case 2: { yield { - field: 'num', + field: `${prefix != null ? `${prefix}.` : ''}num`, value: reader.int32() } break @@ -94,17 +86,6 @@ export namespace Basic { } } } - - if (opts.emitCollections === true) { - for (const [key, value] of Object.entries(obj)) { - if (Array.isArray(value) || value instanceof Map) { - yield { - field: key, - value - } - } - } - } }) } @@ -121,9 +102,6 @@ export namespace Basic { value: number } - export type BasicStreamEvent = BasicFooFieldEvent | BasicNumFieldEvent - export type BasicStreamCollectionsEvent = {} - export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, Basic.codec()) } @@ -132,9 +110,7 @@ export namespace Basic { return decodeMessage(buf, Basic.codec(), opts) } - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Generator { return streamMessage(buf, Basic.codec(), opts) } } @@ -142,11 +118,11 @@ export namespace Basic { export interface Empty {} export namespace Empty { - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -171,15 +147,7 @@ export namespace Empty { } return obj - }, function * (reader, length, opts = {}) { - let obj: any - - if (opts.emitCollections === true) { - obj = {} - } else { - obj = {} - } - + }, function * (reader, length, prefix, opts = {}) { const end = length == null ? reader.len : reader.pos + length while (reader.pos < end) { @@ -192,26 +160,12 @@ export namespace Empty { } } } - - if (opts.emitCollections === true) { - for (const [key, value] of Object.entries(obj)) { - if (Array.isArray(value) || value instanceof Map) { - yield { - field: key, - value - } - } - } - } }) } return _codec } - export type EmptyStreamEvent = {} - export type EmptyStreamCollectionsEvent = {} - export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, Empty.codec()) } @@ -220,9 +174,7 @@ export namespace Empty { return decodeMessage(buf, Empty.codec(), opts) } - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Generator<{}> { return streamMessage(buf, Empty.codec(), opts) } } diff --git a/packages/protons/test/fixtures/bitswap.ts b/packages/protons/test/fixtures/bitswap.ts index b6aa20b..4489ca8 100644 --- a/packages/protons/test/fixtures/bitswap.ts +++ b/packages/protons/test/fixtures/bitswap.ts @@ -1,8 +1,6 @@ -/* eslint-disable complexity */ - import { decodeMessage, encodeMessage, enumeration, MaxLengthError, message, streamMessage } from 'protons-runtime' import { alloc as uint8ArrayAlloc } from 'uint8arrays/alloc' -import type { Codec, DecodeOptions, StreamingDecodeOptions, StreamingDecodeWithCollectionsOptions } from 'protons-runtime' +import type { Codec, DecodeOptions } from 'protons-runtime' import type { Uint8ArrayList } from 'uint8arraylist' export interface Message { @@ -31,7 +29,7 @@ export namespace Message { } export namespace WantType { - export const codec = (): Codec => { + export const codec = (): Codec => { return enumeration(__WantTypeValues) } } @@ -45,11 +43,11 @@ export namespace Message { } export namespace Entry { - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -124,20 +122,7 @@ export namespace Message { } return obj - }, function * (reader, length, opts = {}) { - let obj: any - - if (opts.emitCollections === true) { - obj = { - block: uint8ArrayAlloc(0), - priority: 0, - wantType: WantType.Block, - sendDontHave: false - } - } else { - obj = {} - } - + }, function * (reader, length, prefix, opts = {}) { const end = length == null ? reader.len : reader.pos + length while (reader.pos < end) { @@ -146,35 +131,35 @@ export namespace Message { switch (tag >>> 3) { case 1: { yield { - field: 'block', + field: `${prefix != null ? `${prefix}.` : ''}block`, value: reader.bytes() } break } case 2: { yield { - field: 'priority', + field: `${prefix != null ? `${prefix}.` : ''}priority`, value: reader.int32() } break } case 3: { yield { - field: 'cancel', + field: `${prefix != null ? `${prefix}.` : ''}cancel`, value: reader.bool() } break } case 4: { yield { - field: 'wantType', + field: `${prefix != null ? `${prefix}.` : ''}wantType`, value: Message.Wantlist.WantType.codec().decode(reader) } break } case 5: { yield { - field: 'sendDontHave', + field: `${prefix != null ? `${prefix}.` : ''}sendDontHave`, value: reader.bool() } break @@ -185,17 +170,6 @@ export namespace Message { } } } - - if (opts.emitCollections === true) { - for (const [key, value] of Object.entries(obj)) { - if (Array.isArray(value) || value instanceof Map) { - yield { - field: key, - value - } - } - } - } }) } @@ -227,9 +201,6 @@ export namespace Message { value: boolean } - export type EntryStreamEvent = EntryBlockFieldEvent | EntryPriorityFieldEvent | EntryCancelFieldEvent | EntryWantTypeFieldEvent | EntrySendDontHaveFieldEvent - export type EntryStreamCollectionsEvent = {} - export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, Entry.codec()) } @@ -238,18 +209,16 @@ export namespace Message { return decodeMessage(buf, Entry.codec(), opts) } - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Generator { return streamMessage(buf, Entry.codec(), opts) } } - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -283,7 +252,7 @@ export namespace Message { switch (tag >>> 3) { case 1: { if (opts.limits?.entries != null && obj.entries.length === opts.limits.entries) { - throw new MaxLengthError('Decode error - map field "entries" had too many elements') + throw new MaxLengthError('Decode error - repeated field "entries" had too many elements') } obj.entries.push(Message.Wantlist.Entry.codec().decode(reader, reader.uint32(), { @@ -303,18 +272,9 @@ export namespace Message { } return obj - }, function * (reader, length, opts = {}) { - let obj: any - - if (opts.emitCollections === true) { - obj = { - entries: [], - full: false - } - } else { - obj = { - entries: 0 - } + }, function * (reader, length, prefix, opts = {}) { + const obj = { + entries: 0 } const end = length == null ? reader.len : reader.pos + length @@ -324,31 +284,26 @@ export namespace Message { switch (tag >>> 3) { case 1: { - if (opts.limits?.entries != null && (opts.emitCollections === true ? obj.entries.length === opts.limits.entries : obj.entries === opts.limits.entries)) { - throw new MaxLengthError('Decode error - map field "entries" had too many elements') + if (opts.limits?.entries != null && obj.entries === opts.limits.entries) { + throw new MaxLengthError('Decode error - repeated field "entries" had too many elements') } const value = Message.Wantlist.Entry.codec().decode(reader, reader.uint32(), { limits: opts.limits?.entries$ }) + obj.entries++ yield { - field: 'entries$value', - index: opts.emitCollections === true ? obj.entries.length : obj.entries, + field: `${prefix != null ? `${prefix}.` : ''}entries`, + index: obj.entries, value } - if (opts.emitCollections === true) { - obj.entries.push(value) - } else { - obj.entries++ - } - break } case 2: { yield { - field: 'full', + field: `${prefix != null ? `${prefix}.` : ''}full`, value: reader.bool() } break @@ -359,42 +314,17 @@ export namespace Message { } } } - - if (opts.emitCollections === true) { - for (const [key, value] of Object.entries(obj)) { - if (Array.isArray(value) || value instanceof Map) { - yield { - field: key, - value - } - } - } - } }) } return _codec } - export interface WantlistEntriesFieldEvent { - field: 'entries' - value: Message.Wantlist.Entry[] - } - - export interface WantlistEntriesValueEvent { - field: 'entries$value' - index: number - value: Message.Wantlist.Entry - } - export interface WantlistFullFieldEvent { field: 'full' value: boolean } - export type WantlistStreamEvent = WantlistEntriesValueEvent | WantlistFullFieldEvent - export type WantlistStreamCollectionsEvent = WantlistEntriesFieldEvent - export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, Wantlist.codec()) } @@ -403,9 +333,7 @@ export namespace Message { return decodeMessage(buf, Wantlist.codec(), opts) } - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Generator { return streamMessage(buf, Wantlist.codec(), opts) } } @@ -416,11 +344,11 @@ export namespace Message { } export namespace Block { - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -466,18 +394,7 @@ export namespace Message { } return obj - }, function * (reader, length, opts = {}) { - let obj: any - - if (opts.emitCollections === true) { - obj = { - prefix: uint8ArrayAlloc(0), - data: uint8ArrayAlloc(0) - } - } else { - obj = {} - } - + }, function * (reader, length, prefix, opts = {}) { const end = length == null ? reader.len : reader.pos + length while (reader.pos < end) { @@ -486,14 +403,14 @@ export namespace Message { switch (tag >>> 3) { case 1: { yield { - field: 'prefix', + field: `${prefix != null ? `${prefix}.` : ''}prefix`, value: reader.bytes() } break } case 2: { yield { - field: 'data', + field: `${prefix != null ? `${prefix}.` : ''}data`, value: reader.bytes() } break @@ -504,17 +421,6 @@ export namespace Message { } } } - - if (opts.emitCollections === true) { - for (const [key, value] of Object.entries(obj)) { - if (Array.isArray(value) || value instanceof Map) { - yield { - field: key, - value - } - } - } - } }) } @@ -531,9 +437,6 @@ export namespace Message { value: Uint8Array } - export type BlockStreamEvent = BlockPrefixFieldEvent | BlockDataFieldEvent - export type BlockStreamCollectionsEvent = {} - export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, Block.codec()) } @@ -542,9 +445,7 @@ export namespace Message { return decodeMessage(buf, Block.codec(), opts) } - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Generator { return streamMessage(buf, Block.codec(), opts) } } @@ -560,7 +461,7 @@ export namespace Message { } export namespace BlockPresenceType { - export const codec = (): Codec => { + export const codec = (): Codec => { return enumeration(__BlockPresenceTypeValues) } } @@ -571,11 +472,11 @@ export namespace Message { } export namespace BlockPresence { - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -621,18 +522,7 @@ export namespace Message { } return obj - }, function * (reader, length, opts = {}) { - let obj: any - - if (opts.emitCollections === true) { - obj = { - cid: uint8ArrayAlloc(0), - type: BlockPresenceType.Have - } - } else { - obj = {} - } - + }, function * (reader, length, prefix, opts = {}) { const end = length == null ? reader.len : reader.pos + length while (reader.pos < end) { @@ -641,14 +531,14 @@ export namespace Message { switch (tag >>> 3) { case 1: { yield { - field: 'cid', + field: `${prefix != null ? `${prefix}.` : ''}cid`, value: reader.bytes() } break } case 2: { yield { - field: 'type', + field: `${prefix != null ? `${prefix}.` : ''}type`, value: Message.BlockPresenceType.codec().decode(reader) } break @@ -659,17 +549,6 @@ export namespace Message { } } } - - if (opts.emitCollections === true) { - for (const [key, value] of Object.entries(obj)) { - if (Array.isArray(value) || value instanceof Map) { - yield { - field: key, - value - } - } - } - } }) } @@ -686,9 +565,6 @@ export namespace Message { value: Message.BlockPresenceType } - export type BlockPresenceStreamEvent = BlockPresenceCidFieldEvent | BlockPresenceTypeFieldEvent - export type BlockPresenceStreamCollectionsEvent = {} - export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, BlockPresence.codec()) } @@ -697,18 +573,16 @@ export namespace Message { return decodeMessage(buf, BlockPresence.codec(), opts) } - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Generator { return streamMessage(buf, BlockPresence.codec(), opts) } } - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -769,7 +643,7 @@ export namespace Message { } case 2: { if (opts.limits?.blocks != null && obj.blocks.length === opts.limits.blocks) { - throw new MaxLengthError('Decode error - map field "blocks" had too many elements') + throw new MaxLengthError('Decode error - repeated field "blocks" had too many elements') } obj.blocks.push(reader.bytes()) @@ -777,7 +651,7 @@ export namespace Message { } case 3: { if (opts.limits?.payload != null && obj.payload.length === opts.limits.payload) { - throw new MaxLengthError('Decode error - map field "payload" had too many elements') + throw new MaxLengthError('Decode error - repeated field "payload" had too many elements') } obj.payload.push(Message.Block.codec().decode(reader, reader.uint32(), { @@ -787,7 +661,7 @@ export namespace Message { } case 4: { if (opts.limits?.blockPresences != null && obj.blockPresences.length === opts.limits.blockPresences) { - throw new MaxLengthError('Decode error - map field "blockPresences" had too many elements') + throw new MaxLengthError('Decode error - repeated field "blockPresences" had too many elements') } obj.blockPresences.push(Message.BlockPresence.codec().decode(reader, reader.uint32(), { @@ -807,22 +681,11 @@ export namespace Message { } return obj - }, function * (reader, length, opts = {}) { - let obj: any - - if (opts.emitCollections === true) { - obj = { - blocks: [], - payload: [], - blockPresences: [], - pendingBytes: 0 - } - } else { - obj = { - blocks: 0, - payload: 0, - blockPresences: 0 - } + }, function * (reader, length, prefix, opts = {}) { + const obj = { + blocks: 0, + payload: 0, + blockPresences: 0 } const end = length == null ? reader.len : reader.pos + length @@ -833,7 +696,7 @@ export namespace Message { switch (tag >>> 3) { case 1: { yield { - field: 'wantlist', + field: `${prefix != null ? `${prefix}.` : ''}wantlist`, value: Message.Wantlist.codec().decode(reader, reader.uint32(), { limits: opts.limits?.wantlist }) @@ -841,75 +704,60 @@ export namespace Message { break } case 2: { - if (opts.limits?.blocks != null && (opts.emitCollections === true ? obj.blocks.length === opts.limits.blocks : obj.blocks === opts.limits.blocks)) { - throw new MaxLengthError('Decode error - map field "blocks" had too many elements') + if (opts.limits?.blocks != null && obj.blocks === opts.limits.blocks) { + throw new MaxLengthError('Decode error - repeated field "blocks" had too many elements') } const value = reader.bytes() + obj.blocks++ yield { - field: 'blocks$value', - index: opts.emitCollections === true ? obj.blocks.length : obj.blocks, + field: `${prefix != null ? `${prefix}.` : ''}blocks`, + index: obj.blocks, value } - if (opts.emitCollections === true) { - obj.blocks.push(value) - } else { - obj.blocks++ - } - break } case 3: { - if (opts.limits?.payload != null && (opts.emitCollections === true ? obj.payload.length === opts.limits.payload : obj.payload === opts.limits.payload)) { - throw new MaxLengthError('Decode error - map field "payload" had too many elements') + if (opts.limits?.payload != null && obj.payload === opts.limits.payload) { + throw new MaxLengthError('Decode error - repeated field "payload" had too many elements') } const value = Message.Block.codec().decode(reader, reader.uint32(), { limits: opts.limits?.payload$ }) + obj.payload++ yield { - field: 'payload$value', - index: opts.emitCollections === true ? obj.payload.length : obj.payload, + field: `${prefix != null ? `${prefix}.` : ''}payload`, + index: obj.payload, value } - if (opts.emitCollections === true) { - obj.payload.push(value) - } else { - obj.payload++ - } - break } case 4: { - if (opts.limits?.blockPresences != null && (opts.emitCollections === true ? obj.blockPresences.length === opts.limits.blockPresences : obj.blockPresences === opts.limits.blockPresences)) { - throw new MaxLengthError('Decode error - map field "blockPresences" had too many elements') + if (opts.limits?.blockPresences != null && obj.blockPresences === opts.limits.blockPresences) { + throw new MaxLengthError('Decode error - repeated field "blockPresences" had too many elements') } const value = Message.BlockPresence.codec().decode(reader, reader.uint32(), { limits: opts.limits?.blockPresences$ }) + obj.blockPresences++ yield { - field: 'blockPresences$value', - index: opts.emitCollections === true ? obj.blockPresences.length : obj.blockPresences, + field: `${prefix != null ? `${prefix}.` : ''}blockPresences`, + index: obj.blockPresences, value } - if (opts.emitCollections === true) { - obj.blockPresences.push(value) - } else { - obj.blockPresences++ - } - break } case 5: { yield { - field: 'pendingBytes', + field: `${prefix != null ? `${prefix}.` : ''}pendingBytes`, value: reader.int32() } break @@ -920,69 +768,28 @@ export namespace Message { } } } - - if (opts.emitCollections === true) { - for (const [key, value] of Object.entries(obj)) { - if (Array.isArray(value) || value instanceof Map) { - yield { - field: key, - value - } - } - } - } }) } return _codec } - export interface MessageWantlistFieldEvent { - field: 'wantlist' - value: Message.Wantlist + export interface MessageWantlistWantlistFullFieldEvent { + field: 'full' + value: boolean } export interface MessageBlocksFieldEvent { - field: 'blocks' - value: Uint8Array[] - } - - export interface MessageBlocksValueEvent { - field: 'blocks$value' + field: 'blocks$entry' index: number value: Uint8Array } - export interface MessagePayloadFieldEvent { - field: 'payload' - value: Message.Block[] - } - - export interface MessagePayloadValueEvent { - field: 'payload$value' - index: number - value: Message.Block - } - - export interface MessageBlockPresencesFieldEvent { - field: 'blockPresences' - value: Message.BlockPresence[] - } - - export interface MessageBlockPresencesValueEvent { - field: 'blockPresences$value' - index: number - value: Message.BlockPresence - } - export interface MessagePendingBytesFieldEvent { field: 'pendingBytes' value: number } - export type MessageStreamEvent = MessageWantlistFieldEvent | MessageBlocksValueEvent | MessagePayloadValueEvent | MessageBlockPresencesValueEvent | MessagePendingBytesFieldEvent - export type MessageStreamCollectionsEvent = MessageBlocksFieldEvent | MessagePayloadFieldEvent | MessageBlockPresencesFieldEvent - export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, Message.codec()) } @@ -991,9 +798,7 @@ export namespace Message { return decodeMessage(buf, Message.codec(), opts) } - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Generator { return streamMessage(buf, Message.codec(), opts) } } diff --git a/packages/protons/test/fixtures/circuit.ts b/packages/protons/test/fixtures/circuit.ts index e1eedd8..8c69c98 100644 --- a/packages/protons/test/fixtures/circuit.ts +++ b/packages/protons/test/fixtures/circuit.ts @@ -1,6 +1,6 @@ import { decodeMessage, encodeMessage, enumeration, MaxLengthError, message, streamMessage } from 'protons-runtime' import { alloc as uint8ArrayAlloc } from 'uint8arrays/alloc' -import type { Codec, DecodeOptions, StreamingDecodeOptions, StreamingDecodeWithCollectionsOptions } from 'protons-runtime' +import type { Codec, DecodeOptions } from 'protons-runtime' import type { Uint8ArrayList } from 'uint8arraylist' export interface CircuitRelay { @@ -50,7 +50,7 @@ export namespace CircuitRelay { } export namespace Status { - export const codec = (): Codec => { + export const codec = (): Codec => { return enumeration(__StatusValues) } } @@ -70,7 +70,7 @@ export namespace CircuitRelay { } export namespace Type { - export const codec = (): Codec => { + export const codec = (): Codec => { return enumeration(__TypeValues) } } @@ -81,11 +81,11 @@ export namespace CircuitRelay { } export namespace Peer { - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -123,7 +123,7 @@ export namespace CircuitRelay { } case 2: { if (opts.limits?.addrs != null && obj.addrs.length === opts.limits.addrs) { - throw new MaxLengthError('Decode error - map field "addrs" had too many elements') + throw new MaxLengthError('Decode error - repeated field "addrs" had too many elements') } obj.addrs.push(reader.bytes()) @@ -137,18 +137,9 @@ export namespace CircuitRelay { } return obj - }, function * (reader, length, opts = {}) { - let obj: any - - if (opts.emitCollections === true) { - obj = { - id: uint8ArrayAlloc(0), - addrs: [] - } - } else { - obj = { - addrs: 0 - } + }, function * (reader, length, prefix, opts = {}) { + const obj = { + addrs: 0 } const end = length == null ? reader.len : reader.pos + length @@ -159,30 +150,25 @@ export namespace CircuitRelay { switch (tag >>> 3) { case 1: { yield { - field: 'id', + field: `${prefix != null ? `${prefix}.` : ''}id`, value: reader.bytes() } break } case 2: { - if (opts.limits?.addrs != null && (opts.emitCollections === true ? obj.addrs.length === opts.limits.addrs : obj.addrs === opts.limits.addrs)) { - throw new MaxLengthError('Decode error - map field "addrs" had too many elements') + if (opts.limits?.addrs != null && obj.addrs === opts.limits.addrs) { + throw new MaxLengthError('Decode error - repeated field "addrs" had too many elements') } const value = reader.bytes() + obj.addrs++ yield { - field: 'addrs$value', - index: opts.emitCollections === true ? obj.addrs.length : obj.addrs, + field: `${prefix != null ? `${prefix}.` : ''}addrs`, + index: obj.addrs, value } - if (opts.emitCollections === true) { - obj.addrs.push(value) - } else { - obj.addrs++ - } - break } default: { @@ -191,17 +177,6 @@ export namespace CircuitRelay { } } } - - if (opts.emitCollections === true) { - for (const [key, value] of Object.entries(obj)) { - if (Array.isArray(value) || value instanceof Map) { - yield { - field: key, - value - } - } - } - } }) } @@ -214,19 +189,11 @@ export namespace CircuitRelay { } export interface PeerAddrsFieldEvent { - field: 'addrs' - value: Uint8Array[] - } - - export interface PeerAddrsValueEvent { - field: 'addrs$value' + field: 'addrs$entry' index: number value: Uint8Array } - export type PeerStreamEvent = PeerIdFieldEvent | PeerAddrsValueEvent - export type PeerStreamCollectionsEvent = PeerAddrsFieldEvent - export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, Peer.codec()) } @@ -235,18 +202,16 @@ export namespace CircuitRelay { return decodeMessage(buf, Peer.codec(), opts) } - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Generator { return streamMessage(buf, Peer.codec(), opts) } } - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -311,15 +276,7 @@ export namespace CircuitRelay { } return obj - }, function * (reader, length, opts = {}) { - let obj: any - - if (opts.emitCollections === true) { - obj = {} - } else { - obj = {} - } - + }, function * (reader, length, prefix, opts = {}) { const end = length == null ? reader.len : reader.pos + length while (reader.pos < end) { @@ -328,14 +285,14 @@ export namespace CircuitRelay { switch (tag >>> 3) { case 1: { yield { - field: 'type', + field: `${prefix != null ? `${prefix}.` : ''}type`, value: CircuitRelay.Type.codec().decode(reader) } break } case 2: { yield { - field: 'srcPeer', + field: `${prefix != null ? `${prefix}.` : ''}srcPeer`, value: CircuitRelay.Peer.codec().decode(reader, reader.uint32(), { limits: opts.limits?.srcPeer }) @@ -344,7 +301,7 @@ export namespace CircuitRelay { } case 3: { yield { - field: 'dstPeer', + field: `${prefix != null ? `${prefix}.` : ''}dstPeer`, value: CircuitRelay.Peer.codec().decode(reader, reader.uint32(), { limits: opts.limits?.dstPeer }) @@ -353,7 +310,7 @@ export namespace CircuitRelay { } case 4: { yield { - field: 'code', + field: `${prefix != null ? `${prefix}.` : ''}code`, value: CircuitRelay.Status.codec().decode(reader) } break @@ -364,17 +321,6 @@ export namespace CircuitRelay { } } } - - if (opts.emitCollections === true) { - for (const [key, value] of Object.entries(obj)) { - if (Array.isArray(value) || value instanceof Map) { - yield { - field: key, - value - } - } - } - } }) } @@ -386,14 +332,26 @@ export namespace CircuitRelay { value: CircuitRelay.Type } - export interface CircuitRelaySrcPeerFieldEvent { - field: 'srcPeer' - value: CircuitRelay.Peer + export interface CircuitRelaySrcPeerPeerIdFieldEvent { + field: 'id' + value: Uint8Array + } + + export interface CircuitRelaySrcPeerPeerAddrsFieldEvent { + field: 'addrs$entry' + index: number + value: Uint8Array } - export interface CircuitRelayDstPeerFieldEvent { - field: 'dstPeer' - value: CircuitRelay.Peer + export interface CircuitRelayDstPeerPeerIdFieldEvent { + field: 'id' + value: Uint8Array + } + + export interface CircuitRelayDstPeerPeerAddrsFieldEvent { + field: 'addrs$entry' + index: number + value: Uint8Array } export interface CircuitRelayCodeFieldEvent { @@ -401,9 +359,6 @@ export namespace CircuitRelay { value: CircuitRelay.Status } - export type CircuitRelayStreamEvent = CircuitRelayTypeFieldEvent | CircuitRelaySrcPeerFieldEvent | CircuitRelayDstPeerFieldEvent | CircuitRelayCodeFieldEvent - export type CircuitRelayStreamCollectionsEvent = {} - export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, CircuitRelay.codec()) } @@ -412,9 +367,7 @@ export namespace CircuitRelay { return decodeMessage(buf, CircuitRelay.codec(), opts) } - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Generator { return streamMessage(buf, CircuitRelay.codec(), opts) } } diff --git a/packages/protons/test/fixtures/custom-option-jstype.ts b/packages/protons/test/fixtures/custom-option-jstype.ts index ae8ff9c..f5ef167 100644 --- a/packages/protons/test/fixtures/custom-option-jstype.ts +++ b/packages/protons/test/fixtures/custom-option-jstype.ts @@ -1,5 +1,5 @@ import { decodeMessage, encodeMessage, message, streamMessage } from 'protons-runtime' -import type { Codec, DecodeOptions, StreamingDecodeOptions, StreamingDecodeWithCollectionsOptions } from 'protons-runtime' +import type { Codec, DecodeOptions } from 'protons-runtime' import type { Uint8ArrayList } from 'uint8arraylist' export interface CustomOptionNumber { @@ -12,11 +12,11 @@ export interface CustomOptionNumber { } export namespace CustomOptionNumber { - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -102,22 +102,7 @@ export namespace CustomOptionNumber { } return obj - }, function * (reader, length, opts = {}) { - let obj: any - - if (opts.emitCollections === true) { - obj = { - num: 0, - i64: 0, - ui64: 0, - si64: 0, - f64: 0, - sf64: 0 - } - } else { - obj = {} - } - + }, function * (reader, length, prefix, opts = {}) { const end = length == null ? reader.len : reader.pos + length while (reader.pos < end) { @@ -126,42 +111,42 @@ export namespace CustomOptionNumber { switch (tag >>> 3) { case 1: { yield { - field: 'num', + field: `${prefix != null ? `${prefix}.` : ''}num`, value: reader.int32() } break } case 2: { yield { - field: 'i64', + field: `${prefix != null ? `${prefix}.` : ''}i64`, value: reader.int64Number() } break } case 3: { yield { - field: 'ui64', + field: `${prefix != null ? `${prefix}.` : ''}ui64`, value: reader.uint64Number() } break } case 4: { yield { - field: 'si64', + field: `${prefix != null ? `${prefix}.` : ''}si64`, value: reader.sint64Number() } break } case 5: { yield { - field: 'f64', + field: `${prefix != null ? `${prefix}.` : ''}f64`, value: reader.fixed64Number() } break } case 6: { yield { - field: 'sf64', + field: `${prefix != null ? `${prefix}.` : ''}sf64`, value: reader.sfixed64Number() } break @@ -172,17 +157,6 @@ export namespace CustomOptionNumber { } } } - - if (opts.emitCollections === true) { - for (const [key, value] of Object.entries(obj)) { - if (Array.isArray(value) || value instanceof Map) { - yield { - field: key, - value - } - } - } - } }) } @@ -196,32 +170,29 @@ export namespace CustomOptionNumber { export interface CustomOptionNumberI64FieldEvent { field: 'i64' - value: number + value: bigint } export interface CustomOptionNumberUi64FieldEvent { field: 'ui64' - value: number + value: bigint } export interface CustomOptionNumberSi64FieldEvent { field: 'si64' - value: number + value: bigint } export interface CustomOptionNumberF64FieldEvent { field: 'f64' - value: number + value: bigint } export interface CustomOptionNumberSf64FieldEvent { field: 'sf64' - value: number + value: bigint } - export type CustomOptionNumberStreamEvent = CustomOptionNumberNumFieldEvent | CustomOptionNumberI64FieldEvent | CustomOptionNumberUi64FieldEvent | CustomOptionNumberSi64FieldEvent | CustomOptionNumberF64FieldEvent | CustomOptionNumberSf64FieldEvent - export type CustomOptionNumberStreamCollectionsEvent = {} - export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, CustomOptionNumber.codec()) } @@ -230,9 +201,7 @@ export namespace CustomOptionNumber { return decodeMessage(buf, CustomOptionNumber.codec(), opts) } - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Generator { return streamMessage(buf, CustomOptionNumber.codec(), opts) } } @@ -247,11 +216,11 @@ export interface CustomOptionString { } export namespace CustomOptionString { - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -337,22 +306,7 @@ export namespace CustomOptionString { } return obj - }, function * (reader, length, opts = {}) { - let obj: any - - if (opts.emitCollections === true) { - obj = { - num: 0, - i64: '', - ui64: '', - si64: '', - f64: '', - sf64: '' - } - } else { - obj = {} - } - + }, function * (reader, length, prefix, opts = {}) { const end = length == null ? reader.len : reader.pos + length while (reader.pos < end) { @@ -361,42 +315,42 @@ export namespace CustomOptionString { switch (tag >>> 3) { case 1: { yield { - field: 'num', + field: `${prefix != null ? `${prefix}.` : ''}num`, value: reader.int32() } break } case 2: { yield { - field: 'i64', + field: `${prefix != null ? `${prefix}.` : ''}i64`, value: reader.int64String() } break } case 3: { yield { - field: 'ui64', + field: `${prefix != null ? `${prefix}.` : ''}ui64`, value: reader.uint64String() } break } case 4: { yield { - field: 'si64', + field: `${prefix != null ? `${prefix}.` : ''}si64`, value: reader.sint64String() } break } case 5: { yield { - field: 'f64', + field: `${prefix != null ? `${prefix}.` : ''}f64`, value: reader.fixed64String() } break } case 6: { yield { - field: 'sf64', + field: `${prefix != null ? `${prefix}.` : ''}sf64`, value: reader.sfixed64String() } break @@ -407,17 +361,6 @@ export namespace CustomOptionString { } } } - - if (opts.emitCollections === true) { - for (const [key, value] of Object.entries(obj)) { - if (Array.isArray(value) || value instanceof Map) { - yield { - field: key, - value - } - } - } - } }) } @@ -431,32 +374,29 @@ export namespace CustomOptionString { export interface CustomOptionStringI64FieldEvent { field: 'i64' - value: string + value: bigint } export interface CustomOptionStringUi64FieldEvent { field: 'ui64' - value: string + value: bigint } export interface CustomOptionStringSi64FieldEvent { field: 'si64' - value: string + value: bigint } export interface CustomOptionStringF64FieldEvent { field: 'f64' - value: string + value: bigint } export interface CustomOptionStringSf64FieldEvent { field: 'sf64' - value: string + value: bigint } - export type CustomOptionStringStreamEvent = CustomOptionStringNumFieldEvent | CustomOptionStringI64FieldEvent | CustomOptionStringUi64FieldEvent | CustomOptionStringSi64FieldEvent | CustomOptionStringF64FieldEvent | CustomOptionStringSf64FieldEvent - export type CustomOptionStringStreamCollectionsEvent = {} - export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, CustomOptionString.codec()) } @@ -465,9 +405,7 @@ export namespace CustomOptionString { return decodeMessage(buf, CustomOptionString.codec(), opts) } - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Generator { return streamMessage(buf, CustomOptionString.codec(), opts) } } diff --git a/packages/protons/test/fixtures/daemon.ts b/packages/protons/test/fixtures/daemon.ts index a67d442..2fbe286 100644 --- a/packages/protons/test/fixtures/daemon.ts +++ b/packages/protons/test/fixtures/daemon.ts @@ -1,8 +1,6 @@ -/* eslint-disable complexity */ - import { decodeMessage, encodeMessage, enumeration, MaxLengthError, message, streamMessage } from 'protons-runtime' import { alloc as uint8ArrayAlloc } from 'uint8arrays/alloc' -import type { Codec, DecodeOptions, StreamingDecodeOptions, StreamingDecodeWithCollectionsOptions } from 'protons-runtime' +import type { Codec, DecodeOptions } from 'protons-runtime' import type { Uint8ArrayList } from 'uint8arraylist' export interface Request { @@ -45,16 +43,16 @@ export namespace Request { } export namespace Type { - export const codec = (): Codec => { + export const codec = (): Codec => { return enumeration(__TypeValues) } } - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -178,17 +176,7 @@ export namespace Request { } return obj - }, function * (reader, length, opts = {}) { - let obj: any - - if (opts.emitCollections === true) { - obj = { - type: Type.IDENTIFY - } - } else { - obj = {} - } - + }, function * (reader, length, prefix, opts = {}) { const end = length == null ? reader.len : reader.pos + length while (reader.pos < end) { @@ -197,14 +185,14 @@ export namespace Request { switch (tag >>> 3) { case 1: { yield { - field: 'type', + field: `${prefix != null ? `${prefix}.` : ''}type`, value: Request.Type.codec().decode(reader) } break } case 2: { yield { - field: 'connect', + field: `${prefix != null ? `${prefix}.` : ''}connect`, value: ConnectRequest.codec().decode(reader, reader.uint32(), { limits: opts.limits?.connect }) @@ -213,7 +201,7 @@ export namespace Request { } case 3: { yield { - field: 'streamOpen', + field: `${prefix != null ? `${prefix}.` : ''}streamOpen`, value: StreamOpenRequest.codec().decode(reader, reader.uint32(), { limits: opts.limits?.streamOpen }) @@ -222,7 +210,7 @@ export namespace Request { } case 4: { yield { - field: 'streamHandler', + field: `${prefix != null ? `${prefix}.` : ''}streamHandler`, value: StreamHandlerRequest.codec().decode(reader, reader.uint32(), { limits: opts.limits?.streamHandler }) @@ -231,7 +219,7 @@ export namespace Request { } case 5: { yield { - field: 'dht', + field: `${prefix != null ? `${prefix}.` : ''}dht`, value: DHTRequest.codec().decode(reader, reader.uint32(), { limits: opts.limits?.dht }) @@ -240,7 +228,7 @@ export namespace Request { } case 6: { yield { - field: 'connManager', + field: `${prefix != null ? `${prefix}.` : ''}connManager`, value: ConnManagerRequest.codec().decode(reader, reader.uint32(), { limits: opts.limits?.connManager }) @@ -249,7 +237,7 @@ export namespace Request { } case 7: { yield { - field: 'disconnect', + field: `${prefix != null ? `${prefix}.` : ''}disconnect`, value: DisconnectRequest.codec().decode(reader, reader.uint32(), { limits: opts.limits?.disconnect }) @@ -258,7 +246,7 @@ export namespace Request { } case 8: { yield { - field: 'pubsub', + field: `${prefix != null ? `${prefix}.` : ''}pubsub`, value: PSRequest.codec().decode(reader, reader.uint32(), { limits: opts.limits?.pubsub }) @@ -267,7 +255,7 @@ export namespace Request { } case 9: { yield { - field: 'peerStore', + field: `${prefix != null ? `${prefix}.` : ''}peerStore`, value: PeerstoreRequest.codec().decode(reader, reader.uint32(), { limits: opts.limits?.peerStore }) @@ -280,17 +268,6 @@ export namespace Request { } } } - - if (opts.emitCollections === true) { - for (const [key, value] of Object.entries(obj)) { - if (Array.isArray(value) || value instanceof Map) { - yield { - field: key, - value - } - } - } - } }) } @@ -302,48 +279,139 @@ export namespace Request { value: Request.Type } - export interface RequestConnectFieldEvent { - field: 'connect' - value: ConnectRequest + export interface RequestConnectConnectRequestPeerFieldEvent { + field: 'peer' + value: Uint8Array + } + + export interface RequestConnectConnectRequestAddrsFieldEvent { + field: 'addrs$entry' + index: number + value: Uint8Array + } + + export interface RequestConnectConnectRequestTimeoutFieldEvent { + field: 'timeout' + value: bigint + } + + export interface RequestStreamOpenStreamOpenRequestPeerFieldEvent { + field: 'peer' + value: Uint8Array + } + + export interface RequestStreamOpenStreamOpenRequestProtoFieldEvent { + field: 'proto$entry' + index: number + value: string + } + + export interface RequestStreamOpenStreamOpenRequestTimeoutFieldEvent { + field: 'timeout' + value: bigint + } + + export interface RequestStreamHandlerStreamHandlerRequestAddrFieldEvent { + field: 'addr' + value: Uint8Array + } + + export interface RequestStreamHandlerStreamHandlerRequestProtoFieldEvent { + field: 'proto$entry' + index: number + value: string + } + + export interface RequestDhtDHTRequestTypeFieldEvent { + field: 'type' + value: DHTRequest.Type + } + + export interface RequestDhtDHTRequestPeerFieldEvent { + field: 'peer' + value: Uint8Array + } + + export interface RequestDhtDHTRequestCidFieldEvent { + field: 'cid' + value: Uint8Array } - export interface RequestStreamOpenFieldEvent { - field: 'streamOpen' - value: StreamOpenRequest + export interface RequestDhtDHTRequestKeyFieldEvent { + field: 'key' + value: Uint8Array } - export interface RequestStreamHandlerFieldEvent { - field: 'streamHandler' - value: StreamHandlerRequest + export interface RequestDhtDHTRequestValueFieldEvent { + field: 'value' + value: Uint8Array } - export interface RequestDhtFieldEvent { - field: 'dht' - value: DHTRequest + export interface RequestDhtDHTRequestCountFieldEvent { + field: 'count' + value: number } - export interface RequestConnManagerFieldEvent { - field: 'connManager' - value: ConnManagerRequest + export interface RequestDhtDHTRequestTimeoutFieldEvent { + field: 'timeout' + value: bigint } - export interface RequestDisconnectFieldEvent { - field: 'disconnect' - value: DisconnectRequest + export interface RequestConnManagerConnManagerRequestTypeFieldEvent { + field: 'type' + value: ConnManagerRequest.Type } - export interface RequestPubsubFieldEvent { - field: 'pubsub' - value: PSRequest + export interface RequestConnManagerConnManagerRequestPeerFieldEvent { + field: 'peer' + value: Uint8Array } - export interface RequestPeerStoreFieldEvent { - field: 'peerStore' - value: PeerstoreRequest + export interface RequestConnManagerConnManagerRequestTagFieldEvent { + field: 'tag' + value: string } - export type RequestStreamEvent = RequestTypeFieldEvent | RequestConnectFieldEvent | RequestStreamOpenFieldEvent | RequestStreamHandlerFieldEvent | RequestDhtFieldEvent | RequestConnManagerFieldEvent | RequestDisconnectFieldEvent | RequestPubsubFieldEvent | RequestPeerStoreFieldEvent - export type RequestStreamCollectionsEvent = {} + export interface RequestConnManagerConnManagerRequestWeightFieldEvent { + field: 'weight' + value: bigint + } + + export interface RequestDisconnectDisconnectRequestPeerFieldEvent { + field: 'peer' + value: Uint8Array + } + + export interface RequestPubsubPSRequestTypeFieldEvent { + field: 'type' + value: PSRequest.Type + } + + export interface RequestPubsubPSRequestTopicFieldEvent { + field: 'topic' + value: string + } + + export interface RequestPubsubPSRequestDataFieldEvent { + field: 'data' + value: Uint8Array + } + + export interface RequestPeerStorePeerstoreRequestTypeFieldEvent { + field: 'type' + value: PeerstoreRequest.Type + } + + export interface RequestPeerStorePeerstoreRequestIdFieldEvent { + field: 'id' + value: Uint8Array + } + + export interface RequestPeerStorePeerstoreRequestProtosFieldEvent { + field: 'protos$entry' + index: number + value: string + } export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, Request.codec()) @@ -353,9 +421,7 @@ export namespace Request { return decodeMessage(buf, Request.codec(), opts) } - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Generator { return streamMessage(buf, Request.codec(), opts) } } @@ -383,16 +449,16 @@ export namespace Response { } export namespace Type { - export const codec = (): Codec => { + export const codec = (): Codec => { return enumeration(__TypeValues) } } - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -484,7 +550,7 @@ export namespace Response { } case 6: { if (opts.limits?.peers != null && obj.peers.length === opts.limits.peers) { - throw new MaxLengthError('Decode error - map field "peers" had too many elements') + throw new MaxLengthError('Decode error - repeated field "peers" had too many elements') } obj.peers.push(PeerInfo.codec().decode(reader, reader.uint32(), { @@ -512,18 +578,9 @@ export namespace Response { } return obj - }, function * (reader, length, opts = {}) { - let obj: any - - if (opts.emitCollections === true) { - obj = { - type: Type.OK, - peers: [] - } - } else { - obj = { - peers: 0 - } + }, function * (reader, length, prefix, opts = {}) { + const obj = { + peers: 0 } const end = length == null ? reader.len : reader.pos + length @@ -534,14 +591,14 @@ export namespace Response { switch (tag >>> 3) { case 1: { yield { - field: 'type', + field: `${prefix != null ? `${prefix}.` : ''}type`, value: Response.Type.codec().decode(reader) } break } case 2: { yield { - field: 'error', + field: `${prefix != null ? `${prefix}.` : ''}error`, value: ErrorResponse.codec().decode(reader, reader.uint32(), { limits: opts.limits?.error }) @@ -550,7 +607,7 @@ export namespace Response { } case 3: { yield { - field: 'streamInfo', + field: `${prefix != null ? `${prefix}.` : ''}streamInfo`, value: StreamInfo.codec().decode(reader, reader.uint32(), { limits: opts.limits?.streamInfo }) @@ -559,7 +616,7 @@ export namespace Response { } case 4: { yield { - field: 'identify', + field: `${prefix != null ? `${prefix}.` : ''}identify`, value: IdentifyResponse.codec().decode(reader, reader.uint32(), { limits: opts.limits?.identify }) @@ -568,7 +625,7 @@ export namespace Response { } case 5: { yield { - field: 'dht', + field: `${prefix != null ? `${prefix}.` : ''}dht`, value: DHTResponse.codec().decode(reader, reader.uint32(), { limits: opts.limits?.dht }) @@ -576,31 +633,26 @@ export namespace Response { break } case 6: { - if (opts.limits?.peers != null && (opts.emitCollections === true ? obj.peers.length === opts.limits.peers : obj.peers === opts.limits.peers)) { - throw new MaxLengthError('Decode error - map field "peers" had too many elements') + if (opts.limits?.peers != null && obj.peers === opts.limits.peers) { + throw new MaxLengthError('Decode error - repeated field "peers" had too many elements') } const value = PeerInfo.codec().decode(reader, reader.uint32(), { limits: opts.limits?.peers$ }) + obj.peers++ yield { - field: 'peers$value', - index: opts.emitCollections === true ? obj.peers.length : obj.peers, + field: `${prefix != null ? `${prefix}.` : ''}peers`, + index: obj.peers, value } - if (opts.emitCollections === true) { - obj.peers.push(value) - } else { - obj.peers++ - } - break } case 7: { yield { - field: 'pubsub', + field: `${prefix != null ? `${prefix}.` : ''}pubsub`, value: PSResponse.codec().decode(reader, reader.uint32(), { limits: opts.limits?.pubsub }) @@ -609,7 +661,7 @@ export namespace Response { } case 8: { yield { - field: 'peerStore', + field: `${prefix != null ? `${prefix}.` : ''}peerStore`, value: PeerstoreResponse.codec().decode(reader, reader.uint32(), { limits: opts.limits?.peerStore }) @@ -622,17 +674,6 @@ export namespace Response { } } } - - if (opts.emitCollections === true) { - for (const [key, value] of Object.entries(obj)) { - if (Array.isArray(value) || value instanceof Map) { - yield { - field: key, - value - } - } - } - } }) } @@ -644,49 +685,86 @@ export namespace Response { value: Response.Type } - export interface ResponseErrorFieldEvent { - field: 'error' - value: ErrorResponse + export interface ResponseErrorErrorResponseMsgFieldEvent { + field: 'msg' + value: string } - export interface ResponseStreamInfoFieldEvent { - field: 'streamInfo' - value: StreamInfo + export interface ResponseStreamInfoStreamInfoPeerFieldEvent { + field: 'peer' + value: Uint8Array } - export interface ResponseIdentifyFieldEvent { - field: 'identify' - value: IdentifyResponse + export interface ResponseStreamInfoStreamInfoAddrFieldEvent { + field: 'addr' + value: Uint8Array } - export interface ResponseDhtFieldEvent { - field: 'dht' - value: DHTResponse + export interface ResponseStreamInfoStreamInfoProtoFieldEvent { + field: 'proto' + value: string } - export interface ResponsePeersFieldEvent { - field: 'peers' - value: PeerInfo[] + export interface ResponseIdentifyIdentifyResponseIdFieldEvent { + field: 'id' + value: Uint8Array } - export interface ResponsePeersValueEvent { - field: 'peers$value' + export interface ResponseIdentifyIdentifyResponseAddrsFieldEvent { + field: 'addrs$entry' index: number - value: PeerInfo + value: Uint8Array } - export interface ResponsePubsubFieldEvent { - field: 'pubsub' - value: PSResponse + export interface ResponseDhtDHTResponseTypeFieldEvent { + field: 'type' + value: DHTResponse.Type + } + + export interface ResponseDhtDHTResponsePeerPeerInfoIdFieldEvent { + field: 'id' + value: Uint8Array + } + + export interface ResponseDhtDHTResponsePeerPeerInfoAddrsFieldEvent { + field: 'addrs$entry' + index: number + value: Uint8Array + } + + export interface ResponseDhtDHTResponseValueFieldEvent { + field: 'value' + value: Uint8Array + } + + export interface ResponsePubsubPSResponseTopicsFieldEvent { + field: 'topics$entry' + index: number + value: string } - export interface ResponsePeerStoreFieldEvent { - field: 'peerStore' - value: PeerstoreResponse + export interface ResponsePubsubPSResponsePeerIDsFieldEvent { + field: 'peerIDs$entry' + index: number + value: Uint8Array } - export type ResponseStreamEvent = ResponseTypeFieldEvent | ResponseErrorFieldEvent | ResponseStreamInfoFieldEvent | ResponseIdentifyFieldEvent | ResponseDhtFieldEvent | ResponsePeersValueEvent | ResponsePubsubFieldEvent | ResponsePeerStoreFieldEvent - export type ResponseStreamCollectionsEvent = ResponsePeersFieldEvent + export interface ResponsePeerStorePeerstoreResponsePeerPeerInfoIdFieldEvent { + field: 'id' + value: Uint8Array + } + + export interface ResponsePeerStorePeerstoreResponsePeerPeerInfoAddrsFieldEvent { + field: 'addrs$entry' + index: number + value: Uint8Array + } + + export interface ResponsePeerStorePeerstoreResponseProtosFieldEvent { + field: 'protos$entry' + index: number + value: string + } export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, Response.codec()) @@ -696,9 +774,7 @@ export namespace Response { return decodeMessage(buf, Response.codec(), opts) } - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Generator { return streamMessage(buf, Response.codec(), opts) } } @@ -709,11 +785,11 @@ export interface IdentifyResponse { } export namespace IdentifyResponse { - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -751,7 +827,7 @@ export namespace IdentifyResponse { } case 2: { if (opts.limits?.addrs != null && obj.addrs.length === opts.limits.addrs) { - throw new MaxLengthError('Decode error - map field "addrs" had too many elements') + throw new MaxLengthError('Decode error - repeated field "addrs" had too many elements') } obj.addrs.push(reader.bytes()) @@ -765,18 +841,9 @@ export namespace IdentifyResponse { } return obj - }, function * (reader, length, opts = {}) { - let obj: any - - if (opts.emitCollections === true) { - obj = { - id: uint8ArrayAlloc(0), - addrs: [] - } - } else { - obj = { - addrs: 0 - } + }, function * (reader, length, prefix, opts = {}) { + const obj = { + addrs: 0 } const end = length == null ? reader.len : reader.pos + length @@ -787,30 +854,25 @@ export namespace IdentifyResponse { switch (tag >>> 3) { case 1: { yield { - field: 'id', + field: `${prefix != null ? `${prefix}.` : ''}id`, value: reader.bytes() } break } case 2: { - if (opts.limits?.addrs != null && (opts.emitCollections === true ? obj.addrs.length === opts.limits.addrs : obj.addrs === opts.limits.addrs)) { - throw new MaxLengthError('Decode error - map field "addrs" had too many elements') + if (opts.limits?.addrs != null && obj.addrs === opts.limits.addrs) { + throw new MaxLengthError('Decode error - repeated field "addrs" had too many elements') } const value = reader.bytes() + obj.addrs++ yield { - field: 'addrs$value', - index: opts.emitCollections === true ? obj.addrs.length : obj.addrs, + field: `${prefix != null ? `${prefix}.` : ''}addrs`, + index: obj.addrs, value } - if (opts.emitCollections === true) { - obj.addrs.push(value) - } else { - obj.addrs++ - } - break } default: { @@ -819,17 +881,6 @@ export namespace IdentifyResponse { } } } - - if (opts.emitCollections === true) { - for (const [key, value] of Object.entries(obj)) { - if (Array.isArray(value) || value instanceof Map) { - yield { - field: key, - value - } - } - } - } }) } @@ -842,19 +893,11 @@ export namespace IdentifyResponse { } export interface IdentifyResponseAddrsFieldEvent { - field: 'addrs' - value: Uint8Array[] - } - - export interface IdentifyResponseAddrsValueEvent { - field: 'addrs$value' + field: 'addrs$entry' index: number value: Uint8Array } - export type IdentifyResponseStreamEvent = IdentifyResponseIdFieldEvent | IdentifyResponseAddrsValueEvent - export type IdentifyResponseStreamCollectionsEvent = IdentifyResponseAddrsFieldEvent - export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, IdentifyResponse.codec()) } @@ -863,9 +906,7 @@ export namespace IdentifyResponse { return decodeMessage(buf, IdentifyResponse.codec(), opts) } - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Generator { return streamMessage(buf, IdentifyResponse.codec(), opts) } } @@ -877,11 +918,11 @@ export interface ConnectRequest { } export namespace ConnectRequest { - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -924,7 +965,7 @@ export namespace ConnectRequest { } case 2: { if (opts.limits?.addrs != null && obj.addrs.length === opts.limits.addrs) { - throw new MaxLengthError('Decode error - map field "addrs" had too many elements') + throw new MaxLengthError('Decode error - repeated field "addrs" had too many elements') } obj.addrs.push(reader.bytes()) @@ -942,18 +983,9 @@ export namespace ConnectRequest { } return obj - }, function * (reader, length, opts = {}) { - let obj: any - - if (opts.emitCollections === true) { - obj = { - peer: uint8ArrayAlloc(0), - addrs: [] - } - } else { - obj = { - addrs: 0 - } + }, function * (reader, length, prefix, opts = {}) { + const obj = { + addrs: 0 } const end = length == null ? reader.len : reader.pos + length @@ -964,35 +996,30 @@ export namespace ConnectRequest { switch (tag >>> 3) { case 1: { yield { - field: 'peer', + field: `${prefix != null ? `${prefix}.` : ''}peer`, value: reader.bytes() } break } case 2: { - if (opts.limits?.addrs != null && (opts.emitCollections === true ? obj.addrs.length === opts.limits.addrs : obj.addrs === opts.limits.addrs)) { - throw new MaxLengthError('Decode error - map field "addrs" had too many elements') + if (opts.limits?.addrs != null && obj.addrs === opts.limits.addrs) { + throw new MaxLengthError('Decode error - repeated field "addrs" had too many elements') } const value = reader.bytes() + obj.addrs++ yield { - field: 'addrs$value', - index: opts.emitCollections === true ? obj.addrs.length : obj.addrs, + field: `${prefix != null ? `${prefix}.` : ''}addrs`, + index: obj.addrs, value } - if (opts.emitCollections === true) { - obj.addrs.push(value) - } else { - obj.addrs++ - } - break } case 3: { yield { - field: 'timeout', + field: `${prefix != null ? `${prefix}.` : ''}timeout`, value: reader.int64() } break @@ -1003,17 +1030,6 @@ export namespace ConnectRequest { } } } - - if (opts.emitCollections === true) { - for (const [key, value] of Object.entries(obj)) { - if (Array.isArray(value) || value instanceof Map) { - yield { - field: key, - value - } - } - } - } }) } @@ -1026,12 +1042,7 @@ export namespace ConnectRequest { } export interface ConnectRequestAddrsFieldEvent { - field: 'addrs' - value: Uint8Array[] - } - - export interface ConnectRequestAddrsValueEvent { - field: 'addrs$value' + field: 'addrs$entry' index: number value: Uint8Array } @@ -1041,9 +1052,6 @@ export namespace ConnectRequest { value: bigint } - export type ConnectRequestStreamEvent = ConnectRequestPeerFieldEvent | ConnectRequestAddrsValueEvent | ConnectRequestTimeoutFieldEvent - export type ConnectRequestStreamCollectionsEvent = ConnectRequestAddrsFieldEvent - export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, ConnectRequest.codec()) } @@ -1052,9 +1060,7 @@ export namespace ConnectRequest { return decodeMessage(buf, ConnectRequest.codec(), opts) } - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Generator { return streamMessage(buf, ConnectRequest.codec(), opts) } } @@ -1066,11 +1072,11 @@ export interface StreamOpenRequest { } export namespace StreamOpenRequest { - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -1113,7 +1119,7 @@ export namespace StreamOpenRequest { } case 2: { if (opts.limits?.proto != null && obj.proto.length === opts.limits.proto) { - throw new MaxLengthError('Decode error - map field "proto" had too many elements') + throw new MaxLengthError('Decode error - repeated field "proto" had too many elements') } obj.proto.push(reader.string()) @@ -1131,18 +1137,9 @@ export namespace StreamOpenRequest { } return obj - }, function * (reader, length, opts = {}) { - let obj: any - - if (opts.emitCollections === true) { - obj = { - peer: uint8ArrayAlloc(0), - proto: [] - } - } else { - obj = { - proto: 0 - } + }, function * (reader, length, prefix, opts = {}) { + const obj = { + proto: 0 } const end = length == null ? reader.len : reader.pos + length @@ -1153,35 +1150,30 @@ export namespace StreamOpenRequest { switch (tag >>> 3) { case 1: { yield { - field: 'peer', + field: `${prefix != null ? `${prefix}.` : ''}peer`, value: reader.bytes() } break } case 2: { - if (opts.limits?.proto != null && (opts.emitCollections === true ? obj.proto.length === opts.limits.proto : obj.proto === opts.limits.proto)) { - throw new MaxLengthError('Decode error - map field "proto" had too many elements') + if (opts.limits?.proto != null && obj.proto === opts.limits.proto) { + throw new MaxLengthError('Decode error - repeated field "proto" had too many elements') } const value = reader.string() + obj.proto++ yield { - field: 'proto$value', - index: opts.emitCollections === true ? obj.proto.length : obj.proto, + field: `${prefix != null ? `${prefix}.` : ''}proto`, + index: obj.proto, value } - if (opts.emitCollections === true) { - obj.proto.push(value) - } else { - obj.proto++ - } - break } case 3: { yield { - field: 'timeout', + field: `${prefix != null ? `${prefix}.` : ''}timeout`, value: reader.int64() } break @@ -1192,17 +1184,6 @@ export namespace StreamOpenRequest { } } } - - if (opts.emitCollections === true) { - for (const [key, value] of Object.entries(obj)) { - if (Array.isArray(value) || value instanceof Map) { - yield { - field: key, - value - } - } - } - } }) } @@ -1215,12 +1196,7 @@ export namespace StreamOpenRequest { } export interface StreamOpenRequestProtoFieldEvent { - field: 'proto' - value: string[] - } - - export interface StreamOpenRequestProtoValueEvent { - field: 'proto$value' + field: 'proto$entry' index: number value: string } @@ -1230,9 +1206,6 @@ export namespace StreamOpenRequest { value: bigint } - export type StreamOpenRequestStreamEvent = StreamOpenRequestPeerFieldEvent | StreamOpenRequestProtoValueEvent | StreamOpenRequestTimeoutFieldEvent - export type StreamOpenRequestStreamCollectionsEvent = StreamOpenRequestProtoFieldEvent - export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, StreamOpenRequest.codec()) } @@ -1241,9 +1214,7 @@ export namespace StreamOpenRequest { return decodeMessage(buf, StreamOpenRequest.codec(), opts) } - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Generator { return streamMessage(buf, StreamOpenRequest.codec(), opts) } } @@ -1254,11 +1225,11 @@ export interface StreamHandlerRequest { } export namespace StreamHandlerRequest { - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -1296,7 +1267,7 @@ export namespace StreamHandlerRequest { } case 2: { if (opts.limits?.proto != null && obj.proto.length === opts.limits.proto) { - throw new MaxLengthError('Decode error - map field "proto" had too many elements') + throw new MaxLengthError('Decode error - repeated field "proto" had too many elements') } obj.proto.push(reader.string()) @@ -1310,18 +1281,9 @@ export namespace StreamHandlerRequest { } return obj - }, function * (reader, length, opts = {}) { - let obj: any - - if (opts.emitCollections === true) { - obj = { - addr: uint8ArrayAlloc(0), - proto: [] - } - } else { - obj = { - proto: 0 - } + }, function * (reader, length, prefix, opts = {}) { + const obj = { + proto: 0 } const end = length == null ? reader.len : reader.pos + length @@ -1332,30 +1294,25 @@ export namespace StreamHandlerRequest { switch (tag >>> 3) { case 1: { yield { - field: 'addr', + field: `${prefix != null ? `${prefix}.` : ''}addr`, value: reader.bytes() } break } case 2: { - if (opts.limits?.proto != null && (opts.emitCollections === true ? obj.proto.length === opts.limits.proto : obj.proto === opts.limits.proto)) { - throw new MaxLengthError('Decode error - map field "proto" had too many elements') + if (opts.limits?.proto != null && obj.proto === opts.limits.proto) { + throw new MaxLengthError('Decode error - repeated field "proto" had too many elements') } const value = reader.string() + obj.proto++ yield { - field: 'proto$value', - index: opts.emitCollections === true ? obj.proto.length : obj.proto, + field: `${prefix != null ? `${prefix}.` : ''}proto`, + index: obj.proto, value } - if (opts.emitCollections === true) { - obj.proto.push(value) - } else { - obj.proto++ - } - break } default: { @@ -1364,17 +1321,6 @@ export namespace StreamHandlerRequest { } } } - - if (opts.emitCollections === true) { - for (const [key, value] of Object.entries(obj)) { - if (Array.isArray(value) || value instanceof Map) { - yield { - field: key, - value - } - } - } - } }) } @@ -1387,19 +1333,11 @@ export namespace StreamHandlerRequest { } export interface StreamHandlerRequestProtoFieldEvent { - field: 'proto' - value: string[] - } - - export interface StreamHandlerRequestProtoValueEvent { - field: 'proto$value' + field: 'proto$entry' index: number value: string } - export type StreamHandlerRequestStreamEvent = StreamHandlerRequestAddrFieldEvent | StreamHandlerRequestProtoValueEvent - export type StreamHandlerRequestStreamCollectionsEvent = StreamHandlerRequestProtoFieldEvent - export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, StreamHandlerRequest.codec()) } @@ -1408,9 +1346,7 @@ export namespace StreamHandlerRequest { return decodeMessage(buf, StreamHandlerRequest.codec(), opts) } - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Generator { return streamMessage(buf, StreamHandlerRequest.codec(), opts) } } @@ -1420,11 +1356,11 @@ export interface ErrorResponse { } export namespace ErrorResponse { - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -1460,17 +1396,7 @@ export namespace ErrorResponse { } return obj - }, function * (reader, length, opts = {}) { - let obj: any - - if (opts.emitCollections === true) { - obj = { - msg: '' - } - } else { - obj = {} - } - + }, function * (reader, length, prefix, opts = {}) { const end = length == null ? reader.len : reader.pos + length while (reader.pos < end) { @@ -1479,7 +1405,7 @@ export namespace ErrorResponse { switch (tag >>> 3) { case 1: { yield { - field: 'msg', + field: `${prefix != null ? `${prefix}.` : ''}msg`, value: reader.string() } break @@ -1490,17 +1416,6 @@ export namespace ErrorResponse { } } } - - if (opts.emitCollections === true) { - for (const [key, value] of Object.entries(obj)) { - if (Array.isArray(value) || value instanceof Map) { - yield { - field: key, - value - } - } - } - } }) } @@ -1512,9 +1427,6 @@ export namespace ErrorResponse { value: string } - export type ErrorResponseStreamEvent = ErrorResponseMsgFieldEvent - export type ErrorResponseStreamCollectionsEvent = {} - export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, ErrorResponse.codec()) } @@ -1523,9 +1435,7 @@ export namespace ErrorResponse { return decodeMessage(buf, ErrorResponse.codec(), opts) } - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Generator { return streamMessage(buf, ErrorResponse.codec(), opts) } } @@ -1537,11 +1447,11 @@ export interface StreamInfo { } export namespace StreamInfo { - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -1597,19 +1507,7 @@ export namespace StreamInfo { } return obj - }, function * (reader, length, opts = {}) { - let obj: any - - if (opts.emitCollections === true) { - obj = { - peer: uint8ArrayAlloc(0), - addr: uint8ArrayAlloc(0), - proto: '' - } - } else { - obj = {} - } - + }, function * (reader, length, prefix, opts = {}) { const end = length == null ? reader.len : reader.pos + length while (reader.pos < end) { @@ -1618,21 +1516,21 @@ export namespace StreamInfo { switch (tag >>> 3) { case 1: { yield { - field: 'peer', + field: `${prefix != null ? `${prefix}.` : ''}peer`, value: reader.bytes() } break } case 2: { yield { - field: 'addr', + field: `${prefix != null ? `${prefix}.` : ''}addr`, value: reader.bytes() } break } case 3: { yield { - field: 'proto', + field: `${prefix != null ? `${prefix}.` : ''}proto`, value: reader.string() } break @@ -1643,17 +1541,6 @@ export namespace StreamInfo { } } } - - if (opts.emitCollections === true) { - for (const [key, value] of Object.entries(obj)) { - if (Array.isArray(value) || value instanceof Map) { - yield { - field: key, - value - } - } - } - } }) } @@ -1675,9 +1562,6 @@ export namespace StreamInfo { value: string } - export type StreamInfoStreamEvent = StreamInfoPeerFieldEvent | StreamInfoAddrFieldEvent | StreamInfoProtoFieldEvent - export type StreamInfoStreamCollectionsEvent = {} - export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, StreamInfo.codec()) } @@ -1686,9 +1570,7 @@ export namespace StreamInfo { return decodeMessage(buf, StreamInfo.codec(), opts) } - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Generator { return streamMessage(buf, StreamInfo.codec(), opts) } } @@ -1729,16 +1611,16 @@ export namespace DHTRequest { } export namespace Type { - export const codec = (): Codec => { + export const codec = (): Codec => { return enumeration(__TypeValues) } } - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -1828,17 +1710,7 @@ export namespace DHTRequest { } return obj - }, function * (reader, length, opts = {}) { - let obj: any - - if (opts.emitCollections === true) { - obj = { - type: Type.FIND_PEER - } - } else { - obj = {} - } - + }, function * (reader, length, prefix, opts = {}) { const end = length == null ? reader.len : reader.pos + length while (reader.pos < end) { @@ -1847,49 +1719,49 @@ export namespace DHTRequest { switch (tag >>> 3) { case 1: { yield { - field: 'type', + field: `${prefix != null ? `${prefix}.` : ''}type`, value: DHTRequest.Type.codec().decode(reader) } break } case 2: { yield { - field: 'peer', + field: `${prefix != null ? `${prefix}.` : ''}peer`, value: reader.bytes() } break } case 3: { yield { - field: 'cid', + field: `${prefix != null ? `${prefix}.` : ''}cid`, value: reader.bytes() } break } case 4: { yield { - field: 'key', + field: `${prefix != null ? `${prefix}.` : ''}key`, value: reader.bytes() } break } case 5: { yield { - field: 'value', + field: `${prefix != null ? `${prefix}.` : ''}value`, value: reader.bytes() } break } case 6: { yield { - field: 'count', + field: `${prefix != null ? `${prefix}.` : ''}count`, value: reader.int32() } break } case 7: { yield { - field: 'timeout', + field: `${prefix != null ? `${prefix}.` : ''}timeout`, value: reader.int64() } break @@ -1900,17 +1772,6 @@ export namespace DHTRequest { } } } - - if (opts.emitCollections === true) { - for (const [key, value] of Object.entries(obj)) { - if (Array.isArray(value) || value instanceof Map) { - yield { - field: key, - value - } - } - } - } }) } @@ -1952,9 +1813,6 @@ export namespace DHTRequest { value: bigint } - export type DHTRequestStreamEvent = DHTRequestTypeFieldEvent | DHTRequestPeerFieldEvent | DHTRequestCidFieldEvent | DHTRequestKeyFieldEvent | DHTRequestValueFieldEvent | DHTRequestCountFieldEvent | DHTRequestTimeoutFieldEvent - export type DHTRequestStreamCollectionsEvent = {} - export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, DHTRequest.codec()) } @@ -1963,9 +1821,7 @@ export namespace DHTRequest { return decodeMessage(buf, DHTRequest.codec(), opts) } - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Generator { return streamMessage(buf, DHTRequest.codec(), opts) } } @@ -1990,16 +1846,16 @@ export namespace DHTResponse { } export namespace Type { - export const codec = (): Codec => { + export const codec = (): Codec => { return enumeration(__TypeValues) } } - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -2055,17 +1911,7 @@ export namespace DHTResponse { } return obj - }, function * (reader, length, opts = {}) { - let obj: any - - if (opts.emitCollections === true) { - obj = { - type: Type.BEGIN - } - } else { - obj = {} - } - + }, function * (reader, length, prefix, opts = {}) { const end = length == null ? reader.len : reader.pos + length while (reader.pos < end) { @@ -2074,14 +1920,14 @@ export namespace DHTResponse { switch (tag >>> 3) { case 1: { yield { - field: 'type', + field: `${prefix != null ? `${prefix}.` : ''}type`, value: DHTResponse.Type.codec().decode(reader) } break } case 2: { yield { - field: 'peer', + field: `${prefix != null ? `${prefix}.` : ''}peer`, value: PeerInfo.codec().decode(reader, reader.uint32(), { limits: opts.limits?.peer }) @@ -2090,7 +1936,7 @@ export namespace DHTResponse { } case 3: { yield { - field: 'value', + field: `${prefix != null ? `${prefix}.` : ''}value`, value: reader.bytes() } break @@ -2101,17 +1947,6 @@ export namespace DHTResponse { } } } - - if (opts.emitCollections === true) { - for (const [key, value] of Object.entries(obj)) { - if (Array.isArray(value) || value instanceof Map) { - yield { - field: key, - value - } - } - } - } }) } @@ -2123,9 +1958,15 @@ export namespace DHTResponse { value: DHTResponse.Type } - export interface DHTResponsePeerFieldEvent { - field: 'peer' - value: PeerInfo + export interface DHTResponsePeerPeerInfoIdFieldEvent { + field: 'id' + value: Uint8Array + } + + export interface DHTResponsePeerPeerInfoAddrsFieldEvent { + field: 'addrs$entry' + index: number + value: Uint8Array } export interface DHTResponseValueFieldEvent { @@ -2133,9 +1974,6 @@ export namespace DHTResponse { value: Uint8Array } - export type DHTResponseStreamEvent = DHTResponseTypeFieldEvent | DHTResponsePeerFieldEvent | DHTResponseValueFieldEvent - export type DHTResponseStreamCollectionsEvent = {} - export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, DHTResponse.codec()) } @@ -2144,9 +1982,7 @@ export namespace DHTResponse { return decodeMessage(buf, DHTResponse.codec(), opts) } - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Generator { return streamMessage(buf, DHTResponse.codec(), opts) } } @@ -2157,11 +1993,11 @@ export interface PeerInfo { } export namespace PeerInfo { - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -2199,7 +2035,7 @@ export namespace PeerInfo { } case 2: { if (opts.limits?.addrs != null && obj.addrs.length === opts.limits.addrs) { - throw new MaxLengthError('Decode error - map field "addrs" had too many elements') + throw new MaxLengthError('Decode error - repeated field "addrs" had too many elements') } obj.addrs.push(reader.bytes()) @@ -2213,18 +2049,9 @@ export namespace PeerInfo { } return obj - }, function * (reader, length, opts = {}) { - let obj: any - - if (opts.emitCollections === true) { - obj = { - id: uint8ArrayAlloc(0), - addrs: [] - } - } else { - obj = { - addrs: 0 - } + }, function * (reader, length, prefix, opts = {}) { + const obj = { + addrs: 0 } const end = length == null ? reader.len : reader.pos + length @@ -2235,30 +2062,25 @@ export namespace PeerInfo { switch (tag >>> 3) { case 1: { yield { - field: 'id', + field: `${prefix != null ? `${prefix}.` : ''}id`, value: reader.bytes() } break } case 2: { - if (opts.limits?.addrs != null && (opts.emitCollections === true ? obj.addrs.length === opts.limits.addrs : obj.addrs === opts.limits.addrs)) { - throw new MaxLengthError('Decode error - map field "addrs" had too many elements') + if (opts.limits?.addrs != null && obj.addrs === opts.limits.addrs) { + throw new MaxLengthError('Decode error - repeated field "addrs" had too many elements') } const value = reader.bytes() + obj.addrs++ yield { - field: 'addrs$value', - index: opts.emitCollections === true ? obj.addrs.length : obj.addrs, + field: `${prefix != null ? `${prefix}.` : ''}addrs`, + index: obj.addrs, value } - if (opts.emitCollections === true) { - obj.addrs.push(value) - } else { - obj.addrs++ - } - break } default: { @@ -2267,17 +2089,6 @@ export namespace PeerInfo { } } } - - if (opts.emitCollections === true) { - for (const [key, value] of Object.entries(obj)) { - if (Array.isArray(value) || value instanceof Map) { - yield { - field: key, - value - } - } - } - } }) } @@ -2290,19 +2101,11 @@ export namespace PeerInfo { } export interface PeerInfoAddrsFieldEvent { - field: 'addrs' - value: Uint8Array[] - } - - export interface PeerInfoAddrsValueEvent { - field: 'addrs$value' + field: 'addrs$entry' index: number value: Uint8Array } - export type PeerInfoStreamEvent = PeerInfoIdFieldEvent | PeerInfoAddrsValueEvent - export type PeerInfoStreamCollectionsEvent = PeerInfoAddrsFieldEvent - export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, PeerInfo.codec()) } @@ -2311,9 +2114,7 @@ export namespace PeerInfo { return decodeMessage(buf, PeerInfo.codec(), opts) } - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Generator { return streamMessage(buf, PeerInfo.codec(), opts) } } @@ -2339,16 +2140,16 @@ export namespace ConnManagerRequest { } export namespace Type { - export const codec = (): Codec => { + export const codec = (): Codec => { return enumeration(__TypeValues) } } - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -2411,17 +2212,7 @@ export namespace ConnManagerRequest { } return obj - }, function * (reader, length, opts = {}) { - let obj: any - - if (opts.emitCollections === true) { - obj = { - type: Type.TAG_PEER - } - } else { - obj = {} - } - + }, function * (reader, length, prefix, opts = {}) { const end = length == null ? reader.len : reader.pos + length while (reader.pos < end) { @@ -2430,28 +2221,28 @@ export namespace ConnManagerRequest { switch (tag >>> 3) { case 1: { yield { - field: 'type', + field: `${prefix != null ? `${prefix}.` : ''}type`, value: ConnManagerRequest.Type.codec().decode(reader) } break } case 2: { yield { - field: 'peer', + field: `${prefix != null ? `${prefix}.` : ''}peer`, value: reader.bytes() } break } case 3: { yield { - field: 'tag', + field: `${prefix != null ? `${prefix}.` : ''}tag`, value: reader.string() } break } case 4: { yield { - field: 'weight', + field: `${prefix != null ? `${prefix}.` : ''}weight`, value: reader.int64() } break @@ -2462,17 +2253,6 @@ export namespace ConnManagerRequest { } } } - - if (opts.emitCollections === true) { - for (const [key, value] of Object.entries(obj)) { - if (Array.isArray(value) || value instanceof Map) { - yield { - field: key, - value - } - } - } - } }) } @@ -2499,9 +2279,6 @@ export namespace ConnManagerRequest { value: bigint } - export type ConnManagerRequestStreamEvent = ConnManagerRequestTypeFieldEvent | ConnManagerRequestPeerFieldEvent | ConnManagerRequestTagFieldEvent | ConnManagerRequestWeightFieldEvent - export type ConnManagerRequestStreamCollectionsEvent = {} - export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, ConnManagerRequest.codec()) } @@ -2510,9 +2287,7 @@ export namespace ConnManagerRequest { return decodeMessage(buf, ConnManagerRequest.codec(), opts) } - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Generator { return streamMessage(buf, ConnManagerRequest.codec(), opts) } } @@ -2522,11 +2297,11 @@ export interface DisconnectRequest { } export namespace DisconnectRequest { - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -2562,17 +2337,7 @@ export namespace DisconnectRequest { } return obj - }, function * (reader, length, opts = {}) { - let obj: any - - if (opts.emitCollections === true) { - obj = { - peer: uint8ArrayAlloc(0) - } - } else { - obj = {} - } - + }, function * (reader, length, prefix, opts = {}) { const end = length == null ? reader.len : reader.pos + length while (reader.pos < end) { @@ -2581,7 +2346,7 @@ export namespace DisconnectRequest { switch (tag >>> 3) { case 1: { yield { - field: 'peer', + field: `${prefix != null ? `${prefix}.` : ''}peer`, value: reader.bytes() } break @@ -2592,17 +2357,6 @@ export namespace DisconnectRequest { } } } - - if (opts.emitCollections === true) { - for (const [key, value] of Object.entries(obj)) { - if (Array.isArray(value) || value instanceof Map) { - yield { - field: key, - value - } - } - } - } }) } @@ -2614,9 +2368,6 @@ export namespace DisconnectRequest { value: Uint8Array } - export type DisconnectRequestStreamEvent = DisconnectRequestPeerFieldEvent - export type DisconnectRequestStreamCollectionsEvent = {} - export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, DisconnectRequest.codec()) } @@ -2625,9 +2376,7 @@ export namespace DisconnectRequest { return decodeMessage(buf, DisconnectRequest.codec(), opts) } - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Generator { return streamMessage(buf, DisconnectRequest.codec(), opts) } } @@ -2654,16 +2403,16 @@ export namespace PSRequest { } export namespace Type { - export const codec = (): Codec => { + export const codec = (): Codec => { return enumeration(__TypeValues) } } - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -2717,17 +2466,7 @@ export namespace PSRequest { } return obj - }, function * (reader, length, opts = {}) { - let obj: any - - if (opts.emitCollections === true) { - obj = { - type: Type.GET_TOPICS - } - } else { - obj = {} - } - + }, function * (reader, length, prefix, opts = {}) { const end = length == null ? reader.len : reader.pos + length while (reader.pos < end) { @@ -2736,21 +2475,21 @@ export namespace PSRequest { switch (tag >>> 3) { case 1: { yield { - field: 'type', + field: `${prefix != null ? `${prefix}.` : ''}type`, value: PSRequest.Type.codec().decode(reader) } break } case 2: { yield { - field: 'topic', + field: `${prefix != null ? `${prefix}.` : ''}topic`, value: reader.string() } break } case 3: { yield { - field: 'data', + field: `${prefix != null ? `${prefix}.` : ''}data`, value: reader.bytes() } break @@ -2761,17 +2500,6 @@ export namespace PSRequest { } } } - - if (opts.emitCollections === true) { - for (const [key, value] of Object.entries(obj)) { - if (Array.isArray(value) || value instanceof Map) { - yield { - field: key, - value - } - } - } - } }) } @@ -2793,9 +2521,6 @@ export namespace PSRequest { value: Uint8Array } - export type PSRequestStreamEvent = PSRequestTypeFieldEvent | PSRequestTopicFieldEvent | PSRequestDataFieldEvent - export type PSRequestStreamCollectionsEvent = {} - export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, PSRequest.codec()) } @@ -2804,9 +2529,7 @@ export namespace PSRequest { return decodeMessage(buf, PSRequest.codec(), opts) } - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Generator { return streamMessage(buf, PSRequest.codec(), opts) } } @@ -2821,11 +2544,11 @@ export interface PSMessage { } export namespace PSMessage { - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -2890,7 +2613,7 @@ export namespace PSMessage { } case 4: { if (opts.limits?.topicIDs != null && obj.topicIDs.length === opts.limits.topicIDs) { - throw new MaxLengthError('Decode error - map field "topicIDs" had too many elements') + throw new MaxLengthError('Decode error - repeated field "topicIDs" had too many elements') } obj.topicIDs.push(reader.string()) @@ -2912,17 +2635,9 @@ export namespace PSMessage { } return obj - }, function * (reader, length, opts = {}) { - let obj: any - - if (opts.emitCollections === true) { - obj = { - topicIDs: [] - } - } else { - obj = { - topicIDs: 0 - } + }, function * (reader, length, prefix, opts = {}) { + const obj = { + topicIDs: 0 } const end = length == null ? reader.len : reader.pos + length @@ -2933,56 +2648,51 @@ export namespace PSMessage { switch (tag >>> 3) { case 1: { yield { - field: 'from', + field: `${prefix != null ? `${prefix}.` : ''}from`, value: reader.bytes() } break } case 2: { yield { - field: 'data', + field: `${prefix != null ? `${prefix}.` : ''}data`, value: reader.bytes() } break } case 3: { yield { - field: 'seqno', + field: `${prefix != null ? `${prefix}.` : ''}seqno`, value: reader.bytes() } break } case 4: { - if (opts.limits?.topicIDs != null && (opts.emitCollections === true ? obj.topicIDs.length === opts.limits.topicIDs : obj.topicIDs === opts.limits.topicIDs)) { - throw new MaxLengthError('Decode error - map field "topicIDs" had too many elements') + if (opts.limits?.topicIDs != null && obj.topicIDs === opts.limits.topicIDs) { + throw new MaxLengthError('Decode error - repeated field "topicIDs" had too many elements') } const value = reader.string() + obj.topicIDs++ yield { - field: 'topicIDs$value', - index: opts.emitCollections === true ? obj.topicIDs.length : obj.topicIDs, + field: `${prefix != null ? `${prefix}.` : ''}topicIDs`, + index: obj.topicIDs, value } - if (opts.emitCollections === true) { - obj.topicIDs.push(value) - } else { - obj.topicIDs++ - } - break } case 5: { yield { - field: 'signature', + field: `${prefix != null ? `${prefix}.` : ''}signature`, value: reader.bytes() } break } case 6: { yield { - field: 'key', + field: `${prefix != null ? `${prefix}.` : ''}key`, value: reader.bytes() } break @@ -2993,17 +2703,6 @@ export namespace PSMessage { } } } - - if (opts.emitCollections === true) { - for (const [key, value] of Object.entries(obj)) { - if (Array.isArray(value) || value instanceof Map) { - yield { - field: key, - value - } - } - } - } }) } @@ -3026,12 +2725,7 @@ export namespace PSMessage { } export interface PSMessageTopicIDsFieldEvent { - field: 'topicIDs' - value: string[] - } - - export interface PSMessageTopicIDsValueEvent { - field: 'topicIDs$value' + field: 'topicIDs$entry' index: number value: string } @@ -3046,9 +2740,6 @@ export namespace PSMessage { value: Uint8Array } - export type PSMessageStreamEvent = PSMessageFromFieldEvent | PSMessageDataFieldEvent | PSMessageSeqnoFieldEvent | PSMessageTopicIDsValueEvent | PSMessageSignatureFieldEvent | PSMessageKeyFieldEvent - export type PSMessageStreamCollectionsEvent = PSMessageTopicIDsFieldEvent - export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, PSMessage.codec()) } @@ -3057,9 +2748,7 @@ export namespace PSMessage { return decodeMessage(buf, PSMessage.codec(), opts) } - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Generator { return streamMessage(buf, PSMessage.codec(), opts) } } @@ -3070,11 +2759,11 @@ export interface PSResponse { } export namespace PSResponse { - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -3110,7 +2799,7 @@ export namespace PSResponse { switch (tag >>> 3) { case 1: { if (opts.limits?.topics != null && obj.topics.length === opts.limits.topics) { - throw new MaxLengthError('Decode error - map field "topics" had too many elements') + throw new MaxLengthError('Decode error - repeated field "topics" had too many elements') } obj.topics.push(reader.string()) @@ -3118,7 +2807,7 @@ export namespace PSResponse { } case 2: { if (opts.limits?.peerIDs != null && obj.peerIDs.length === opts.limits.peerIDs) { - throw new MaxLengthError('Decode error - map field "peerIDs" had too many elements') + throw new MaxLengthError('Decode error - repeated field "peerIDs" had too many elements') } obj.peerIDs.push(reader.bytes()) @@ -3132,19 +2821,10 @@ export namespace PSResponse { } return obj - }, function * (reader, length, opts = {}) { - let obj: any - - if (opts.emitCollections === true) { - obj = { - topics: [], - peerIDs: [] - } - } else { - obj = { - topics: 0, - peerIDs: 0 - } + }, function * (reader, length, prefix, opts = {}) { + const obj = { + topics: 0, + peerIDs: 0 } const end = length == null ? reader.len : reader.pos + length @@ -3154,45 +2834,35 @@ export namespace PSResponse { switch (tag >>> 3) { case 1: { - if (opts.limits?.topics != null && (opts.emitCollections === true ? obj.topics.length === opts.limits.topics : obj.topics === opts.limits.topics)) { - throw new MaxLengthError('Decode error - map field "topics" had too many elements') + if (opts.limits?.topics != null && obj.topics === opts.limits.topics) { + throw new MaxLengthError('Decode error - repeated field "topics" had too many elements') } const value = reader.string() + obj.topics++ yield { - field: 'topics$value', - index: opts.emitCollections === true ? obj.topics.length : obj.topics, + field: `${prefix != null ? `${prefix}.` : ''}topics`, + index: obj.topics, value } - if (opts.emitCollections === true) { - obj.topics.push(value) - } else { - obj.topics++ - } - break } case 2: { - if (opts.limits?.peerIDs != null && (opts.emitCollections === true ? obj.peerIDs.length === opts.limits.peerIDs : obj.peerIDs === opts.limits.peerIDs)) { - throw new MaxLengthError('Decode error - map field "peerIDs" had too many elements') + if (opts.limits?.peerIDs != null && obj.peerIDs === opts.limits.peerIDs) { + throw new MaxLengthError('Decode error - repeated field "peerIDs" had too many elements') } const value = reader.bytes() + obj.peerIDs++ yield { - field: 'peerIDs$value', - index: opts.emitCollections === true ? obj.peerIDs.length : obj.peerIDs, + field: `${prefix != null ? `${prefix}.` : ''}peerIDs`, + index: obj.peerIDs, value } - if (opts.emitCollections === true) { - obj.peerIDs.push(value) - } else { - obj.peerIDs++ - } - break } default: { @@ -3201,17 +2871,6 @@ export namespace PSResponse { } } } - - if (opts.emitCollections === true) { - for (const [key, value] of Object.entries(obj)) { - if (Array.isArray(value) || value instanceof Map) { - yield { - field: key, - value - } - } - } - } }) } @@ -3219,30 +2878,17 @@ export namespace PSResponse { } export interface PSResponseTopicsFieldEvent { - field: 'topics' - value: string[] - } - - export interface PSResponseTopicsValueEvent { - field: 'topics$value' + field: 'topics$entry' index: number value: string } export interface PSResponsePeerIDsFieldEvent { - field: 'peerIDs' - value: Uint8Array[] - } - - export interface PSResponsePeerIDsValueEvent { - field: 'peerIDs$value' + field: 'peerIDs$entry' index: number value: Uint8Array } - export type PSResponseStreamEvent = PSResponseTopicsValueEvent | PSResponsePeerIDsValueEvent - export type PSResponseStreamCollectionsEvent = PSResponseTopicsFieldEvent | PSResponsePeerIDsFieldEvent - export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, PSResponse.codec()) } @@ -3251,9 +2897,7 @@ export namespace PSResponse { return decodeMessage(buf, PSResponse.codec(), opts) } - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Generator { return streamMessage(buf, PSResponse.codec(), opts) } } @@ -3278,16 +2922,16 @@ export namespace PeerstoreRequest { } export namespace Type { - export const codec = (): Codec => { + export const codec = (): Codec => { return enumeration(__TypeValues) } } - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -3334,7 +2978,7 @@ export namespace PeerstoreRequest { } case 3: { if (opts.limits?.protos != null && obj.protos.length === opts.limits.protos) { - throw new MaxLengthError('Decode error - map field "protos" had too many elements') + throw new MaxLengthError('Decode error - repeated field "protos" had too many elements') } obj.protos.push(reader.string()) @@ -3348,18 +2992,9 @@ export namespace PeerstoreRequest { } return obj - }, function * (reader, length, opts = {}) { - let obj: any - - if (opts.emitCollections === true) { - obj = { - type: Type.INVALID, - protos: [] - } - } else { - obj = { - protos: 0 - } + }, function * (reader, length, prefix, opts = {}) { + const obj = { + protos: 0 } const end = length == null ? reader.len : reader.pos + length @@ -3370,37 +3005,32 @@ export namespace PeerstoreRequest { switch (tag >>> 3) { case 1: { yield { - field: 'type', + field: `${prefix != null ? `${prefix}.` : ''}type`, value: PeerstoreRequest.Type.codec().decode(reader) } break } case 2: { yield { - field: 'id', + field: `${prefix != null ? `${prefix}.` : ''}id`, value: reader.bytes() } break } case 3: { - if (opts.limits?.protos != null && (opts.emitCollections === true ? obj.protos.length === opts.limits.protos : obj.protos === opts.limits.protos)) { - throw new MaxLengthError('Decode error - map field "protos" had too many elements') + if (opts.limits?.protos != null && obj.protos === opts.limits.protos) { + throw new MaxLengthError('Decode error - repeated field "protos" had too many elements') } const value = reader.string() + obj.protos++ yield { - field: 'protos$value', - index: opts.emitCollections === true ? obj.protos.length : obj.protos, + field: `${prefix != null ? `${prefix}.` : ''}protos`, + index: obj.protos, value } - if (opts.emitCollections === true) { - obj.protos.push(value) - } else { - obj.protos++ - } - break } default: { @@ -3409,17 +3039,6 @@ export namespace PeerstoreRequest { } } } - - if (opts.emitCollections === true) { - for (const [key, value] of Object.entries(obj)) { - if (Array.isArray(value) || value instanceof Map) { - yield { - field: key, - value - } - } - } - } }) } @@ -3437,19 +3056,11 @@ export namespace PeerstoreRequest { } export interface PeerstoreRequestProtosFieldEvent { - field: 'protos' - value: string[] - } - - export interface PeerstoreRequestProtosValueEvent { - field: 'protos$value' + field: 'protos$entry' index: number value: string } - export type PeerstoreRequestStreamEvent = PeerstoreRequestTypeFieldEvent | PeerstoreRequestIdFieldEvent | PeerstoreRequestProtosValueEvent - export type PeerstoreRequestStreamCollectionsEvent = PeerstoreRequestProtosFieldEvent - export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, PeerstoreRequest.codec()) } @@ -3458,9 +3069,7 @@ export namespace PeerstoreRequest { return decodeMessage(buf, PeerstoreRequest.codec(), opts) } - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Generator { return streamMessage(buf, PeerstoreRequest.codec(), opts) } } @@ -3471,11 +3080,11 @@ export interface PeerstoreResponse { } export namespace PeerstoreResponse { - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -3514,7 +3123,7 @@ export namespace PeerstoreResponse { } case 2: { if (opts.limits?.protos != null && obj.protos.length === opts.limits.protos) { - throw new MaxLengthError('Decode error - map field "protos" had too many elements') + throw new MaxLengthError('Decode error - repeated field "protos" had too many elements') } obj.protos.push(reader.string()) @@ -3528,17 +3137,9 @@ export namespace PeerstoreResponse { } return obj - }, function * (reader, length, opts = {}) { - let obj: any - - if (opts.emitCollections === true) { - obj = { - protos: [] - } - } else { - obj = { - protos: 0 - } + }, function * (reader, length, prefix, opts = {}) { + const obj = { + protos: 0 } const end = length == null ? reader.len : reader.pos + length @@ -3549,7 +3150,7 @@ export namespace PeerstoreResponse { switch (tag >>> 3) { case 1: { yield { - field: 'peer', + field: `${prefix != null ? `${prefix}.` : ''}peer`, value: PeerInfo.codec().decode(reader, reader.uint32(), { limits: opts.limits?.peer }) @@ -3557,24 +3158,19 @@ export namespace PeerstoreResponse { break } case 2: { - if (opts.limits?.protos != null && (opts.emitCollections === true ? obj.protos.length === opts.limits.protos : obj.protos === opts.limits.protos)) { - throw new MaxLengthError('Decode error - map field "protos" had too many elements') + if (opts.limits?.protos != null && obj.protos === opts.limits.protos) { + throw new MaxLengthError('Decode error - repeated field "protos" had too many elements') } const value = reader.string() + obj.protos++ yield { - field: 'protos$value', - index: opts.emitCollections === true ? obj.protos.length : obj.protos, + field: `${prefix != null ? `${prefix}.` : ''}protos`, + index: obj.protos, value } - if (opts.emitCollections === true) { - obj.protos.push(value) - } else { - obj.protos++ - } - break } default: { @@ -3583,42 +3179,29 @@ export namespace PeerstoreResponse { } } } - - if (opts.emitCollections === true) { - for (const [key, value] of Object.entries(obj)) { - if (Array.isArray(value) || value instanceof Map) { - yield { - field: key, - value - } - } - } - } }) } return _codec } - export interface PeerstoreResponsePeerFieldEvent { - field: 'peer' - value: PeerInfo + export interface PeerstoreResponsePeerPeerInfoIdFieldEvent { + field: 'id' + value: Uint8Array } - export interface PeerstoreResponseProtosFieldEvent { - field: 'protos' - value: string[] + export interface PeerstoreResponsePeerPeerInfoAddrsFieldEvent { + field: 'addrs$entry' + index: number + value: Uint8Array } - export interface PeerstoreResponseProtosValueEvent { - field: 'protos$value' + export interface PeerstoreResponseProtosFieldEvent { + field: 'protos$entry' index: number value: string } - export type PeerstoreResponseStreamEvent = PeerstoreResponsePeerFieldEvent | PeerstoreResponseProtosValueEvent - export type PeerstoreResponseStreamCollectionsEvent = PeerstoreResponseProtosFieldEvent - export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, PeerstoreResponse.codec()) } @@ -3627,9 +3210,7 @@ export namespace PeerstoreResponse { return decodeMessage(buf, PeerstoreResponse.codec(), opts) } - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Generator { return streamMessage(buf, PeerstoreResponse.codec(), opts) } } diff --git a/packages/protons/test/fixtures/dht.ts b/packages/protons/test/fixtures/dht.ts index 5d1eeb0..3174a5e 100644 --- a/packages/protons/test/fixtures/dht.ts +++ b/packages/protons/test/fixtures/dht.ts @@ -1,7 +1,5 @@ -/* eslint-disable complexity */ - import { decodeMessage, encodeMessage, enumeration, MaxLengthError, message, streamMessage } from 'protons-runtime' -import type { Codec, DecodeOptions, StreamingDecodeOptions, StreamingDecodeWithCollectionsOptions } from 'protons-runtime' +import type { Codec, DecodeOptions } from 'protons-runtime' import type { Uint8ArrayList } from 'uint8arraylist' export interface Record { @@ -13,11 +11,11 @@ export interface Record { } export namespace Record { - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -87,15 +85,7 @@ export namespace Record { } return obj - }, function * (reader, length, opts = {}) { - let obj: any - - if (opts.emitCollections === true) { - obj = {} - } else { - obj = {} - } - + }, function * (reader, length, prefix, opts = {}) { const end = length == null ? reader.len : reader.pos + length while (reader.pos < end) { @@ -104,35 +94,35 @@ export namespace Record { switch (tag >>> 3) { case 1: { yield { - field: 'key', + field: `${prefix != null ? `${prefix}.` : ''}key`, value: reader.bytes() } break } case 2: { yield { - field: 'value', + field: `${prefix != null ? `${prefix}.` : ''}value`, value: reader.bytes() } break } case 3: { yield { - field: 'author', + field: `${prefix != null ? `${prefix}.` : ''}author`, value: reader.bytes() } break } case 4: { yield { - field: 'signature', + field: `${prefix != null ? `${prefix}.` : ''}signature`, value: reader.bytes() } break } case 5: { yield { - field: 'timeReceived', + field: `${prefix != null ? `${prefix}.` : ''}timeReceived`, value: reader.string() } break @@ -143,17 +133,6 @@ export namespace Record { } } } - - if (opts.emitCollections === true) { - for (const [key, value] of Object.entries(obj)) { - if (Array.isArray(value) || value instanceof Map) { - yield { - field: key, - value - } - } - } - } }) } @@ -185,9 +164,6 @@ export namespace Record { value: string } - export type RecordStreamEvent = RecordKeyFieldEvent | RecordValueFieldEvent | RecordAuthorFieldEvent | RecordSignatureFieldEvent | RecordTimeReceivedFieldEvent - export type RecordStreamCollectionsEvent = {} - export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, Record.codec()) } @@ -196,9 +172,7 @@ export namespace Record { return decodeMessage(buf, Record.codec(), opts) } - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Generator { return streamMessage(buf, Record.codec(), opts) } } @@ -232,7 +206,7 @@ export namespace Message { } export namespace MessageType { - export const codec = (): Codec => { + export const codec = (): Codec => { return enumeration(__MessageTypeValues) } } @@ -252,7 +226,7 @@ export namespace Message { } export namespace ConnectionType { - export const codec = (): Codec => { + export const codec = (): Codec => { return enumeration(__ConnectionTypeValues) } } @@ -264,11 +238,11 @@ export namespace Message { } export namespace Peer { - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -310,7 +284,7 @@ export namespace Message { } case 2: { if (opts.limits?.addrs != null && obj.addrs.length === opts.limits.addrs) { - throw new MaxLengthError('Decode error - map field "addrs" had too many elements') + throw new MaxLengthError('Decode error - repeated field "addrs" had too many elements') } obj.addrs.push(reader.bytes()) @@ -328,17 +302,9 @@ export namespace Message { } return obj - }, function * (reader, length, opts = {}) { - let obj: any - - if (opts.emitCollections === true) { - obj = { - addrs: [] - } - } else { - obj = { - addrs: 0 - } + }, function * (reader, length, prefix, opts = {}) { + const obj = { + addrs: 0 } const end = length == null ? reader.len : reader.pos + length @@ -349,35 +315,30 @@ export namespace Message { switch (tag >>> 3) { case 1: { yield { - field: 'id', + field: `${prefix != null ? `${prefix}.` : ''}id`, value: reader.bytes() } break } case 2: { - if (opts.limits?.addrs != null && (opts.emitCollections === true ? obj.addrs.length === opts.limits.addrs : obj.addrs === opts.limits.addrs)) { - throw new MaxLengthError('Decode error - map field "addrs" had too many elements') + if (opts.limits?.addrs != null && obj.addrs === opts.limits.addrs) { + throw new MaxLengthError('Decode error - repeated field "addrs" had too many elements') } const value = reader.bytes() + obj.addrs++ yield { - field: 'addrs$value', - index: opts.emitCollections === true ? obj.addrs.length : obj.addrs, + field: `${prefix != null ? `${prefix}.` : ''}addrs`, + index: obj.addrs, value } - if (opts.emitCollections === true) { - obj.addrs.push(value) - } else { - obj.addrs++ - } - break } case 3: { yield { - field: 'connection', + field: `${prefix != null ? `${prefix}.` : ''}connection`, value: Message.ConnectionType.codec().decode(reader) } break @@ -388,17 +349,6 @@ export namespace Message { } } } - - if (opts.emitCollections === true) { - for (const [key, value] of Object.entries(obj)) { - if (Array.isArray(value) || value instanceof Map) { - yield { - field: key, - value - } - } - } - } }) } @@ -411,12 +361,7 @@ export namespace Message { } export interface PeerAddrsFieldEvent { - field: 'addrs' - value: Uint8Array[] - } - - export interface PeerAddrsValueEvent { - field: 'addrs$value' + field: 'addrs$entry' index: number value: Uint8Array } @@ -426,9 +371,6 @@ export namespace Message { value: Message.ConnectionType } - export type PeerStreamEvent = PeerIdFieldEvent | PeerAddrsValueEvent | PeerConnectionFieldEvent - export type PeerStreamCollectionsEvent = PeerAddrsFieldEvent - export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, Peer.codec()) } @@ -437,18 +379,16 @@ export namespace Message { return decodeMessage(buf, Peer.codec(), opts) } - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Generator { return streamMessage(buf, Peer.codec(), opts) } } - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -520,7 +460,7 @@ export namespace Message { } case 8: { if (opts.limits?.closerPeers != null && obj.closerPeers.length === opts.limits.closerPeers) { - throw new MaxLengthError('Decode error - map field "closerPeers" had too many elements') + throw new MaxLengthError('Decode error - repeated field "closerPeers" had too many elements') } obj.closerPeers.push(Message.Peer.codec().decode(reader, reader.uint32(), { @@ -530,7 +470,7 @@ export namespace Message { } case 9: { if (opts.limits?.providerPeers != null && obj.providerPeers.length === opts.limits.providerPeers) { - throw new MaxLengthError('Decode error - map field "providerPeers" had too many elements') + throw new MaxLengthError('Decode error - repeated field "providerPeers" had too many elements') } obj.providerPeers.push(Message.Peer.codec().decode(reader, reader.uint32(), { @@ -546,19 +486,10 @@ export namespace Message { } return obj - }, function * (reader, length, opts = {}) { - let obj: any - - if (opts.emitCollections === true) { - obj = { - closerPeers: [], - providerPeers: [] - } - } else { - obj = { - closerPeers: 0, - providerPeers: 0 - } + }, function * (reader, length, prefix, opts = {}) { + const obj = { + closerPeers: 0, + providerPeers: 0 } const end = length == null ? reader.len : reader.pos + length @@ -569,76 +500,66 @@ export namespace Message { switch (tag >>> 3) { case 1: { yield { - field: 'type', + field: `${prefix != null ? `${prefix}.` : ''}type`, value: Message.MessageType.codec().decode(reader) } break } case 10: { yield { - field: 'clusterLevelRaw', + field: `${prefix != null ? `${prefix}.` : ''}clusterLevelRaw`, value: reader.int32() } break } case 2: { yield { - field: 'key', + field: `${prefix != null ? `${prefix}.` : ''}key`, value: reader.bytes() } break } case 3: { yield { - field: 'record', + field: `${prefix != null ? `${prefix}.` : ''}record`, value: reader.bytes() } break } case 8: { - if (opts.limits?.closerPeers != null && (opts.emitCollections === true ? obj.closerPeers.length === opts.limits.closerPeers : obj.closerPeers === opts.limits.closerPeers)) { - throw new MaxLengthError('Decode error - map field "closerPeers" had too many elements') + if (opts.limits?.closerPeers != null && obj.closerPeers === opts.limits.closerPeers) { + throw new MaxLengthError('Decode error - repeated field "closerPeers" had too many elements') } const value = Message.Peer.codec().decode(reader, reader.uint32(), { limits: opts.limits?.closerPeers$ }) + obj.closerPeers++ yield { - field: 'closerPeers$value', - index: opts.emitCollections === true ? obj.closerPeers.length : obj.closerPeers, + field: `${prefix != null ? `${prefix}.` : ''}closerPeers`, + index: obj.closerPeers, value } - if (opts.emitCollections === true) { - obj.closerPeers.push(value) - } else { - obj.closerPeers++ - } - break } case 9: { - if (opts.limits?.providerPeers != null && (opts.emitCollections === true ? obj.providerPeers.length === opts.limits.providerPeers : obj.providerPeers === opts.limits.providerPeers)) { - throw new MaxLengthError('Decode error - map field "providerPeers" had too many elements') + if (opts.limits?.providerPeers != null && obj.providerPeers === opts.limits.providerPeers) { + throw new MaxLengthError('Decode error - repeated field "providerPeers" had too many elements') } const value = Message.Peer.codec().decode(reader, reader.uint32(), { limits: opts.limits?.providerPeers$ }) + obj.providerPeers++ yield { - field: 'providerPeers$value', - index: opts.emitCollections === true ? obj.providerPeers.length : obj.providerPeers, + field: `${prefix != null ? `${prefix}.` : ''}providerPeers`, + index: obj.providerPeers, value } - if (opts.emitCollections === true) { - obj.providerPeers.push(value) - } else { - obj.providerPeers++ - } - break } default: { @@ -647,17 +568,6 @@ export namespace Message { } } } - - if (opts.emitCollections === true) { - for (const [key, value] of Object.entries(obj)) { - if (Array.isArray(value) || value instanceof Map) { - yield { - field: key, - value - } - } - } - } }) } @@ -684,31 +594,6 @@ export namespace Message { value: Uint8Array } - export interface MessageCloserPeersFieldEvent { - field: 'closerPeers' - value: Message.Peer[] - } - - export interface MessageCloserPeersValueEvent { - field: 'closerPeers$value' - index: number - value: Message.Peer - } - - export interface MessageProviderPeersFieldEvent { - field: 'providerPeers' - value: Message.Peer[] - } - - export interface MessageProviderPeersValueEvent { - field: 'providerPeers$value' - index: number - value: Message.Peer - } - - export type MessageStreamEvent = MessageTypeFieldEvent | MessageClusterLevelRawFieldEvent | MessageKeyFieldEvent | MessageRecordFieldEvent | MessageCloserPeersValueEvent | MessageProviderPeersValueEvent - export type MessageStreamCollectionsEvent = MessageCloserPeersFieldEvent | MessageProviderPeersFieldEvent - export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, Message.codec()) } @@ -717,9 +602,7 @@ export namespace Message { return decodeMessage(buf, Message.codec(), opts) } - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Generator { return streamMessage(buf, Message.codec(), opts) } } diff --git a/packages/protons/test/fixtures/maps.ts b/packages/protons/test/fixtures/maps.ts index 04c7f2a..165e4cc 100644 --- a/packages/protons/test/fixtures/maps.ts +++ b/packages/protons/test/fixtures/maps.ts @@ -1,7 +1,5 @@ -/* eslint-disable complexity */ - import { decodeMessage, encodeMessage, enumeration, MaxLengthError, MaxSizeError, message, streamMessage } from 'protons-runtime' -import type { Codec, DecodeOptions, StreamingDecodeOptions, StreamingDecodeWithCollectionsOptions } from 'protons-runtime' +import type { Codec, DecodeOptions } from 'protons-runtime' import type { Uint8ArrayList } from 'uint8arraylist' export enum EnumValue { @@ -17,7 +15,7 @@ enum __EnumValueValues { } export namespace EnumValue { - export const codec = (): Codec => { + export const codec = (): Codec => { return enumeration(__EnumValueValues) } } @@ -28,11 +26,11 @@ export interface SubMessage { } export namespace SubMessage { - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -70,7 +68,7 @@ export namespace SubMessage { } case 2: { if (opts.limits?.bar != null && obj.bar.length === opts.limits.bar) { - throw new MaxLengthError('Decode error - map field "bar" had too many elements') + throw new MaxLengthError('Decode error - repeated field "bar" had too many elements') } obj.bar.push(reader.uint32()) @@ -84,18 +82,9 @@ export namespace SubMessage { } return obj - }, function * (reader, length, opts = {}) { - let obj: any - - if (opts.emitCollections === true) { - obj = { - foo: '', - bar: [] - } - } else { - obj = { - bar: 0 - } + }, function * (reader, length, prefix, opts = {}) { + const obj = { + bar: 0 } const end = length == null ? reader.len : reader.pos + length @@ -106,30 +95,25 @@ export namespace SubMessage { switch (tag >>> 3) { case 1: { yield { - field: 'foo', + field: `${prefix != null ? `${prefix}.` : ''}foo`, value: reader.string() } break } case 2: { - if (opts.limits?.bar != null && (opts.emitCollections === true ? obj.bar.length === opts.limits.bar : obj.bar === opts.limits.bar)) { - throw new MaxLengthError('Decode error - map field "bar" had too many elements') + if (opts.limits?.bar != null && obj.bar === opts.limits.bar) { + throw new MaxLengthError('Decode error - repeated field "bar" had too many elements') } const value = reader.uint32() + obj.bar++ yield { - field: 'bar$value', - index: opts.emitCollections === true ? obj.bar.length : obj.bar, + field: `${prefix != null ? `${prefix}.` : ''}bar`, + index: obj.bar, value } - if (opts.emitCollections === true) { - obj.bar.push(value) - } else { - obj.bar++ - } - break } default: { @@ -138,17 +122,6 @@ export namespace SubMessage { } } } - - if (opts.emitCollections === true) { - for (const [key, value] of Object.entries(obj)) { - if (Array.isArray(value) || value instanceof Map) { - yield { - field: key, - value - } - } - } - } }) } @@ -161,19 +134,11 @@ export namespace SubMessage { } export interface SubMessageBarFieldEvent { - field: 'bar' - value: number[] - } - - export interface SubMessageBarValueEvent { - field: 'bar$value' + field: 'bar$entry' index: number value: number } - export type SubMessageStreamEvent = SubMessageFooFieldEvent | SubMessageBarValueEvent - export type SubMessageStreamCollectionsEvent = SubMessageBarFieldEvent - export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, SubMessage.codec()) } @@ -182,9 +147,7 @@ export namespace SubMessage { return decodeMessage(buf, SubMessage.codec(), opts) } - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Generator { return streamMessage(buf, SubMessage.codec(), opts) } } @@ -204,11 +167,11 @@ export namespace MapTypes { } export namespace MapTypes$stringMapEntry { - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -254,18 +217,7 @@ export namespace MapTypes { } return obj - }, function * (reader, length, opts = {}) { - let obj: any - - if (opts.emitCollections === true) { - obj = { - key: '', - value: '' - } - } else { - obj = {} - } - + }, function * (reader, length, prefix, opts = {}) { const end = length == null ? reader.len : reader.pos + length while (reader.pos < end) { @@ -274,14 +226,14 @@ export namespace MapTypes { switch (tag >>> 3) { case 1: { yield { - field: 'key', + field: `${prefix != null ? `${prefix}.` : ''}key`, value: reader.string() } break } case 2: { yield { - field: 'value', + field: `${prefix != null ? `${prefix}.` : ''}value`, value: reader.string() } break @@ -292,17 +244,6 @@ export namespace MapTypes { } } } - - if (opts.emitCollections === true) { - for (const [key, value] of Object.entries(obj)) { - if (Array.isArray(value) || value instanceof Map) { - yield { - field: key, - value - } - } - } - } }) } @@ -319,9 +260,6 @@ export namespace MapTypes { value: string } - export type MapTypes$stringMapEntryStreamEvent = MapTypes$stringMapEntryKeyFieldEvent | MapTypes$stringMapEntryValueFieldEvent - export type MapTypes$stringMapEntryStreamCollectionsEvent = {} - export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, MapTypes$stringMapEntry.codec()) } @@ -330,9 +268,7 @@ export namespace MapTypes { return decodeMessage(buf, MapTypes$stringMapEntry.codec(), opts) } - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Generator { return streamMessage(buf, MapTypes$stringMapEntry.codec(), opts) } } @@ -343,11 +279,11 @@ export namespace MapTypes { } export namespace MapTypes$intMapEntry { - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -393,18 +329,7 @@ export namespace MapTypes { } return obj - }, function * (reader, length, opts = {}) { - let obj: any - - if (opts.emitCollections === true) { - obj = { - key: 0, - value: 0 - } - } else { - obj = {} - } - + }, function * (reader, length, prefix, opts = {}) { const end = length == null ? reader.len : reader.pos + length while (reader.pos < end) { @@ -413,14 +338,14 @@ export namespace MapTypes { switch (tag >>> 3) { case 1: { yield { - field: 'key', + field: `${prefix != null ? `${prefix}.` : ''}key`, value: reader.int32() } break } case 2: { yield { - field: 'value', + field: `${prefix != null ? `${prefix}.` : ''}value`, value: reader.int32() } break @@ -431,17 +356,6 @@ export namespace MapTypes { } } } - - if (opts.emitCollections === true) { - for (const [key, value] of Object.entries(obj)) { - if (Array.isArray(value) || value instanceof Map) { - yield { - field: key, - value - } - } - } - } }) } @@ -458,9 +372,6 @@ export namespace MapTypes { value: number } - export type MapTypes$intMapEntryStreamEvent = MapTypes$intMapEntryKeyFieldEvent | MapTypes$intMapEntryValueFieldEvent - export type MapTypes$intMapEntryStreamCollectionsEvent = {} - export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, MapTypes$intMapEntry.codec()) } @@ -469,9 +380,7 @@ export namespace MapTypes { return decodeMessage(buf, MapTypes$intMapEntry.codec(), opts) } - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Generator { return streamMessage(buf, MapTypes$intMapEntry.codec(), opts) } } @@ -482,11 +391,11 @@ export namespace MapTypes { } export namespace MapTypes$boolMapEntry { - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -532,18 +441,7 @@ export namespace MapTypes { } return obj - }, function * (reader, length, opts = {}) { - let obj: any - - if (opts.emitCollections === true) { - obj = { - key: false, - value: false - } - } else { - obj = {} - } - + }, function * (reader, length, prefix, opts = {}) { const end = length == null ? reader.len : reader.pos + length while (reader.pos < end) { @@ -552,14 +450,14 @@ export namespace MapTypes { switch (tag >>> 3) { case 1: { yield { - field: 'key', + field: `${prefix != null ? `${prefix}.` : ''}key`, value: reader.bool() } break } case 2: { yield { - field: 'value', + field: `${prefix != null ? `${prefix}.` : ''}value`, value: reader.bool() } break @@ -570,17 +468,6 @@ export namespace MapTypes { } } } - - if (opts.emitCollections === true) { - for (const [key, value] of Object.entries(obj)) { - if (Array.isArray(value) || value instanceof Map) { - yield { - field: key, - value - } - } - } - } }) } @@ -597,9 +484,6 @@ export namespace MapTypes { value: boolean } - export type MapTypes$boolMapEntryStreamEvent = MapTypes$boolMapEntryKeyFieldEvent | MapTypes$boolMapEntryValueFieldEvent - export type MapTypes$boolMapEntryStreamCollectionsEvent = {} - export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, MapTypes$boolMapEntry.codec()) } @@ -608,9 +492,7 @@ export namespace MapTypes { return decodeMessage(buf, MapTypes$boolMapEntry.codec(), opts) } - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Generator { return streamMessage(buf, MapTypes$boolMapEntry.codec(), opts) } } @@ -621,11 +503,11 @@ export namespace MapTypes { } export namespace MapTypes$messageMapEntry { - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -672,17 +554,7 @@ export namespace MapTypes { } return obj - }, function * (reader, length, opts = {}) { - let obj: any - - if (opts.emitCollections === true) { - obj = { - key: '' - } - } else { - obj = {} - } - + }, function * (reader, length, prefix, opts = {}) { const end = length == null ? reader.len : reader.pos + length while (reader.pos < end) { @@ -691,14 +563,14 @@ export namespace MapTypes { switch (tag >>> 3) { case 1: { yield { - field: 'key', + field: `${prefix != null ? `${prefix}.` : ''}key`, value: reader.string() } break } case 2: { yield { - field: 'value', + field: `${prefix != null ? `${prefix}.` : ''}value`, value: SubMessage.codec().decode(reader, reader.uint32(), { limits: opts.limits?.value }) @@ -711,17 +583,6 @@ export namespace MapTypes { } } } - - if (opts.emitCollections === true) { - for (const [key, value] of Object.entries(obj)) { - if (Array.isArray(value) || value instanceof Map) { - yield { - field: key, - value - } - } - } - } }) } @@ -733,13 +594,16 @@ export namespace MapTypes { value: string } - export interface MapTypes$messageMapEntryValueFieldEvent { - field: 'value' - value: SubMessage + export interface MapTypes$messageMapEntryValueSubMessageFooFieldEvent { + field: 'foo' + value: string } - export type MapTypes$messageMapEntryStreamEvent = MapTypes$messageMapEntryKeyFieldEvent | MapTypes$messageMapEntryValueFieldEvent - export type MapTypes$messageMapEntryStreamCollectionsEvent = {} + export interface MapTypes$messageMapEntryValueSubMessageBarFieldEvent { + field: 'bar$entry' + index: number + value: number + } export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, MapTypes$messageMapEntry.codec()) @@ -749,9 +613,7 @@ export namespace MapTypes { return decodeMessage(buf, MapTypes$messageMapEntry.codec(), opts) } - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Generator { return streamMessage(buf, MapTypes$messageMapEntry.codec(), opts) } } @@ -762,11 +624,11 @@ export namespace MapTypes { } export namespace MapTypes$enumMapEntry { - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -812,18 +674,7 @@ export namespace MapTypes { } return obj - }, function * (reader, length, opts = {}) { - let obj: any - - if (opts.emitCollections === true) { - obj = { - key: '', - value: EnumValue.NO_VALUE - } - } else { - obj = {} - } - + }, function * (reader, length, prefix, opts = {}) { const end = length == null ? reader.len : reader.pos + length while (reader.pos < end) { @@ -832,14 +683,14 @@ export namespace MapTypes { switch (tag >>> 3) { case 1: { yield { - field: 'key', + field: `${prefix != null ? `${prefix}.` : ''}key`, value: reader.string() } break } case 2: { yield { - field: 'value', + field: `${prefix != null ? `${prefix}.` : ''}value`, value: EnumValue.codec().decode(reader) } break @@ -850,17 +701,6 @@ export namespace MapTypes { } } } - - if (opts.emitCollections === true) { - for (const [key, value] of Object.entries(obj)) { - if (Array.isArray(value) || value instanceof Map) { - yield { - field: key, - value - } - } - } - } }) } @@ -877,9 +717,6 @@ export namespace MapTypes { value: EnumValue } - export type MapTypes$enumMapEntryStreamEvent = MapTypes$enumMapEntryKeyFieldEvent | MapTypes$enumMapEntryValueFieldEvent - export type MapTypes$enumMapEntryStreamCollectionsEvent = {} - export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, MapTypes$enumMapEntry.codec()) } @@ -888,51 +725,49 @@ export namespace MapTypes { return decodeMessage(buf, MapTypes$enumMapEntry.codec(), opts) } - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Generator { return streamMessage(buf, MapTypes$enumMapEntry.codec(), opts) } } - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } - if (obj.stringMap != null && obj.stringMap.size !== 0) { + if (obj.stringMap != null) { for (const [key, value] of obj.stringMap.entries()) { w.uint32(10) MapTypes.MapTypes$stringMapEntry.codec().encode({ key, value }, w) } } - if (obj.intMap != null && obj.intMap.size !== 0) { + if (obj.intMap != null) { for (const [key, value] of obj.intMap.entries()) { w.uint32(18) MapTypes.MapTypes$intMapEntry.codec().encode({ key, value }, w) } } - if (obj.boolMap != null && obj.boolMap.size !== 0) { + if (obj.boolMap != null) { for (const [key, value] of obj.boolMap.entries()) { w.uint32(26) MapTypes.MapTypes$boolMapEntry.codec().encode({ key, value }, w) } } - if (obj.messageMap != null && obj.messageMap.size !== 0) { + if (obj.messageMap != null) { for (const [key, value] of obj.messageMap.entries()) { w.uint32(34) MapTypes.MapTypes$messageMapEntry.codec().encode({ key, value }, w) } } - if (obj.enumMap != null && obj.enumMap.size !== 0) { + if (obj.enumMap != null) { for (const [key, value] of obj.enumMap.entries()) { w.uint32(42) MapTypes.MapTypes$enumMapEntry.codec().encode({ key, value }, w) @@ -947,8 +782,8 @@ export namespace MapTypes { stringMap: new Map(), intMap: new Map(), boolMap: new Map(), - messageMap: new Map(), - enumMap: new Map() + messageMap: new Map(), + enumMap: new Map() } const end = length == null ? reader.len : reader.pos + length @@ -962,7 +797,11 @@ export namespace MapTypes { throw new MaxSizeError('Decode error - map field "stringMap" had too many elements') } - const entry = MapTypes.MapTypes$stringMapEntry.codec().decode(reader, reader.uint32()) + const entry = MapTypes.MapTypes$stringMapEntry.codec().decode(reader, reader.uint32(), { + limits: { + value: opts.limits?.stringMap$value + } + }) obj.stringMap.set(entry.key, entry.value) break } @@ -971,7 +810,11 @@ export namespace MapTypes { throw new MaxSizeError('Decode error - map field "intMap" had too many elements') } - const entry = MapTypes.MapTypes$intMapEntry.codec().decode(reader, reader.uint32()) + const entry = MapTypes.MapTypes$intMapEntry.codec().decode(reader, reader.uint32(), { + limits: { + value: opts.limits?.intMap$value + } + }) obj.intMap.set(entry.key, entry.value) break } @@ -980,7 +823,11 @@ export namespace MapTypes { throw new MaxSizeError('Decode error - map field "boolMap" had too many elements') } - const entry = MapTypes.MapTypes$boolMapEntry.codec().decode(reader, reader.uint32()) + const entry = MapTypes.MapTypes$boolMapEntry.codec().decode(reader, reader.uint32(), { + limits: { + value: opts.limits?.boolMap$value + } + }) obj.boolMap.set(entry.key, entry.value) break } @@ -1002,7 +849,11 @@ export namespace MapTypes { throw new MaxSizeError('Decode error - map field "enumMap" had too many elements') } - const entry = MapTypes.MapTypes$enumMapEntry.codec().decode(reader, reader.uint32()) + const entry = MapTypes.MapTypes$enumMapEntry.codec().decode(reader, reader.uint32(), { + limits: { + value: opts.limits?.enumMap$value + } + }) obj.enumMap.set(entry.key, entry.value) break } @@ -1014,25 +865,13 @@ export namespace MapTypes { } return obj - }, function * (reader, length, opts = {}) { - let obj: any - - if (opts.emitCollections === true) { - obj = { - stringMap: new Map(), - intMap: new Map(), - boolMap: new Map(), - messageMap: new Map(), - enumMap: new Map() - } - } else { - obj = { - stringMap: 0, - intMap: 0, - boolMap: 0, - messageMap: 0, - enumMap: 0 - } + }, function * (reader, length, prefix, opts = {}) { + const obj = { + stringMap: 0, + intMap: 0, + boolMap: 0, + messageMap: 0, + enumMap: 0 } const end = length == null ? reader.len : reader.pos + length @@ -1042,71 +881,68 @@ export namespace MapTypes { switch (tag >>> 3) { case 1: { - if (opts.limits?.stringMap != null && (opts.emitCollections === true ? obj.stringMap.size === opts.limits.stringMap : obj.stringMap === opts.limits.stringMap)) { - throw new MaxSizeError('Decode error - map field "stringMap" had too many elements') + if (opts.limits?.stringMap != null && obj.stringMap === opts.limits.stringMap) { + throw new MaxLengthError('Decode error - map field "stringMap" had too many elements') } - const entry = MapTypes.MapTypes$stringMapEntry.codec().decode(reader, reader.uint32()) + const entry = MapTypes.MapTypes$stringMapEntry.codec().decode(reader, reader.uint32(), { + limits: { + value: opts.limits?.stringMap$value + } + }) + obj.stringMap++ yield { - field: 'stringMap', + field: `${prefix != null ? `${prefix}.` : ''}stringMap`, key: entry.key, value: entry.value } - if (opts.emitCollections === true) { - obj.stringMap.set(entry.key, entry.value) - } else { - obj.stringMap++ - } - break } case 2: { - if (opts.limits?.intMap != null && (opts.emitCollections === true ? obj.intMap.size === opts.limits.intMap : obj.intMap === opts.limits.intMap)) { - throw new MaxSizeError('Decode error - map field "intMap" had too many elements') + if (opts.limits?.intMap != null && obj.intMap === opts.limits.intMap) { + throw new MaxLengthError('Decode error - map field "intMap" had too many elements') } - const entry = MapTypes.MapTypes$intMapEntry.codec().decode(reader, reader.uint32()) + const entry = MapTypes.MapTypes$intMapEntry.codec().decode(reader, reader.uint32(), { + limits: { + value: opts.limits?.intMap$value + } + }) + obj.intMap++ yield { - field: 'intMap', + field: `${prefix != null ? `${prefix}.` : ''}intMap`, key: entry.key, value: entry.value } - if (opts.emitCollections === true) { - obj.intMap.set(entry.key, entry.value) - } else { - obj.intMap++ - } - break } case 3: { - if (opts.limits?.boolMap != null && (opts.emitCollections === true ? obj.boolMap.size === opts.limits.boolMap : obj.boolMap === opts.limits.boolMap)) { - throw new MaxSizeError('Decode error - map field "boolMap" had too many elements') + if (opts.limits?.boolMap != null && obj.boolMap === opts.limits.boolMap) { + throw new MaxLengthError('Decode error - map field "boolMap" had too many elements') } - const entry = MapTypes.MapTypes$boolMapEntry.codec().decode(reader, reader.uint32()) + const entry = MapTypes.MapTypes$boolMapEntry.codec().decode(reader, reader.uint32(), { + limits: { + value: opts.limits?.boolMap$value + } + }) + obj.boolMap++ yield { - field: 'boolMap', + field: `${prefix != null ? `${prefix}.` : ''}boolMap`, key: entry.key, value: entry.value } - if (opts.emitCollections === true) { - obj.boolMap.set(entry.key, entry.value) - } else { - obj.boolMap++ - } - break } case 4: { - if (opts.limits?.messageMap != null && (opts.emitCollections === true ? obj.messageMap.size === opts.limits.messageMap : obj.messageMap === opts.limits.messageMap)) { - throw new MaxSizeError('Decode error - map field "messageMap" had too many elements') + if (opts.limits?.messageMap != null && obj.messageMap === opts.limits.messageMap) { + throw new MaxLengthError('Decode error - map field "messageMap" had too many elements') } const entry = MapTypes.MapTypes$messageMapEntry.codec().decode(reader, reader.uint32(), { @@ -1114,40 +950,34 @@ export namespace MapTypes { value: opts.limits?.messageMap$value } }) + obj.messageMap++ yield { - field: 'messageMap', + field: `${prefix != null ? `${prefix}.` : ''}messageMap`, key: entry.key, value: entry.value } - if (opts.emitCollections === true) { - obj.messageMap.set(entry.key, entry.value) - } else { - obj.messageMap++ - } - break } case 5: { - if (opts.limits?.enumMap != null && (opts.emitCollections === true ? obj.enumMap.size === opts.limits.enumMap : obj.enumMap === opts.limits.enumMap)) { - throw new MaxSizeError('Decode error - map field "enumMap" had too many elements') + if (opts.limits?.enumMap != null && obj.enumMap === opts.limits.enumMap) { + throw new MaxLengthError('Decode error - map field "enumMap" had too many elements') } - const entry = MapTypes.MapTypes$enumMapEntry.codec().decode(reader, reader.uint32()) + const entry = MapTypes.MapTypes$enumMapEntry.codec().decode(reader, reader.uint32(), { + limits: { + value: opts.limits?.enumMap$value + } + }) + obj.enumMap++ yield { - field: 'enumMap', + field: `${prefix != null ? `${prefix}.` : ''}enumMap`, key: entry.key, value: entry.value } - if (opts.emitCollections === true) { - obj.enumMap.set(entry.key, entry.value) - } else { - obj.enumMap++ - } - break } default: { @@ -1156,17 +986,6 @@ export namespace MapTypes { } } } - - if (opts.emitCollections === true) { - for (const [key, value] of Object.entries(obj)) { - if (Array.isArray(value) || value instanceof Map) { - yield { - field: key, - value - } - } - } - } }) } @@ -1174,63 +993,23 @@ export namespace MapTypes { } export interface MapTypesStringMapFieldEvent { - field: 'stringMap' - value: Map - } - - export interface MapTypesStringMapEntryEvent { field: 'stringMap$entry' key: string value: string } export interface MapTypesIntMapFieldEvent { - field: 'intMap' - value: Map - } - - export interface MapTypesIntMapEntryEvent { field: 'intMap$entry' key: number value: number } export interface MapTypesBoolMapFieldEvent { - field: 'boolMap' - value: Map - } - - export interface MapTypesBoolMapEntryEvent { field: 'boolMap$entry' key: boolean value: boolean } - export interface MapTypesMessageMapFieldEvent { - field: 'messageMap' - value: Map - } - - export interface MapTypesMessageMapEntryEvent { - field: 'messageMap$entry' - key: string - value: SubMessage - } - - export interface MapTypesEnumMapFieldEvent { - field: 'enumMap' - value: Map - } - - export interface MapTypesEnumMapEntryEvent { - field: 'enumMap$entry' - key: string - value: EnumValue - } - - export type MapTypesStreamEvent = MapTypesStringMapEntryEvent | MapTypesIntMapEntryEvent | MapTypesBoolMapEntryEvent | MapTypesMessageMapEntryEvent | MapTypesEnumMapEntryEvent - export type MapTypesStreamCollectionsEvent = MapTypesStringMapFieldEvent | MapTypesIntMapFieldEvent | MapTypesBoolMapFieldEvent | MapTypesMessageMapFieldEvent | MapTypesEnumMapFieldEvent - export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, MapTypes.codec()) } @@ -1239,9 +1018,7 @@ export namespace MapTypes { return decodeMessage(buf, MapTypes.codec(), opts) } - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Generator { return streamMessage(buf, MapTypes.codec(), opts) } } diff --git a/packages/protons/test/fixtures/noise.ts b/packages/protons/test/fixtures/noise.ts index e5cb241..aab5e56 100644 --- a/packages/protons/test/fixtures/noise.ts +++ b/packages/protons/test/fixtures/noise.ts @@ -1,6 +1,8 @@ +/* eslint-disable require-yield */ + import { decodeMessage, encodeMessage, message, streamMessage } from 'protons-runtime' import { alloc as uint8ArrayAlloc } from 'uint8arrays/alloc' -import type { Codec, DecodeOptions, StreamingDecodeOptions, StreamingDecodeWithCollectionsOptions } from 'protons-runtime' +import type { Codec, DecodeOptions } from 'protons-runtime' import type { Uint8ArrayList } from 'uint8arraylist' export interface pb {} @@ -13,11 +15,11 @@ export namespace pb { } export namespace NoiseHandshakePayload { - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -73,19 +75,7 @@ export namespace pb { } return obj - }, function * (reader, length, opts = {}) { - let obj: any - - if (opts.emitCollections === true) { - obj = { - identityKey: uint8ArrayAlloc(0), - identitySig: uint8ArrayAlloc(0), - data: uint8ArrayAlloc(0) - } - } else { - obj = {} - } - + }, function * (reader, length, prefix, opts = {}) { const end = length == null ? reader.len : reader.pos + length while (reader.pos < end) { @@ -94,21 +84,21 @@ export namespace pb { switch (tag >>> 3) { case 1: { yield { - field: 'identityKey', + field: `${prefix != null ? `${prefix}.` : ''}identityKey`, value: reader.bytes() } break } case 2: { yield { - field: 'identitySig', + field: `${prefix != null ? `${prefix}.` : ''}identitySig`, value: reader.bytes() } break } case 3: { yield { - field: 'data', + field: `${prefix != null ? `${prefix}.` : ''}data`, value: reader.bytes() } break @@ -119,17 +109,6 @@ export namespace pb { } } } - - if (opts.emitCollections === true) { - for (const [key, value] of Object.entries(obj)) { - if (Array.isArray(value) || value instanceof Map) { - yield { - field: key, - value - } - } - } - } }) } @@ -151,9 +130,6 @@ export namespace pb { value: Uint8Array } - export type NoiseHandshakePayloadStreamEvent = NoiseHandshakePayloadIdentityKeyFieldEvent | NoiseHandshakePayloadIdentitySigFieldEvent | NoiseHandshakePayloadDataFieldEvent - export type NoiseHandshakePayloadStreamCollectionsEvent = {} - export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, NoiseHandshakePayload.codec()) } @@ -162,18 +138,16 @@ export namespace pb { return decodeMessage(buf, NoiseHandshakePayload.codec(), opts) } - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Generator { return streamMessage(buf, NoiseHandshakePayload.codec(), opts) } } - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -198,15 +172,7 @@ export namespace pb { } return obj - }, function * (reader, length, opts = {}) { - let obj: any - - if (opts.emitCollections === true) { - obj = {} - } else { - obj = {} - } - + }, function * (reader, length, prefix, opts = {}) { const end = length == null ? reader.len : reader.pos + length while (reader.pos < end) { @@ -219,26 +185,12 @@ export namespace pb { } } } - - if (opts.emitCollections === true) { - for (const [key, value] of Object.entries(obj)) { - if (Array.isArray(value) || value instanceof Map) { - yield { - field: key, - value - } - } - } - } }) } return _codec } - export type pbStreamEvent = {} - export type pbStreamCollectionsEvent = {} - export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, pb.codec()) } @@ -247,9 +199,7 @@ export namespace pb { return decodeMessage(buf, pb.codec(), opts) } - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Generator<{}> { return streamMessage(buf, pb.codec(), opts) } } diff --git a/packages/protons/test/fixtures/oneof.ts b/packages/protons/test/fixtures/oneof.ts index 286ef97..5a69e3b 100644 --- a/packages/protons/test/fixtures/oneof.ts +++ b/packages/protons/test/fixtures/oneof.ts @@ -1,5 +1,5 @@ import { decodeMessage, encodeMessage, enumeration, message, streamMessage } from 'protons-runtime' -import type { Codec, DecodeOptions, StreamingDecodeOptions, StreamingDecodeWithCollectionsOptions } from 'protons-runtime' +import type { Codec, DecodeOptions } from 'protons-runtime' import type { Uint8ArrayList } from 'uint8arraylist' export enum EnumType { @@ -13,7 +13,7 @@ enum __EnumTypeValues { } export namespace EnumType { - export const codec = (): Codec => { + export const codec = (): Codec => { return enumeration(__EnumTypeValues) } } @@ -27,11 +27,11 @@ export interface OneOfMessage { } export namespace OneOfMessage { - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -137,17 +137,7 @@ export namespace OneOfMessage { } return obj - }, function * (reader, length, opts = {}) { - let obj: any - - if (opts.emitCollections === true) { - obj = { - fieldFive: '' - } - } else { - obj = {} - } - + }, function * (reader, length, prefix, opts = {}) { const end = length == null ? reader.len : reader.pos + length while (reader.pos < end) { @@ -156,35 +146,35 @@ export namespace OneOfMessage { switch (tag >>> 3) { case 1: { yield { - field: 'fieldOne', + field: `${prefix != null ? `${prefix}.` : ''}fieldOne`, value: reader.string() } break } case 2: { yield { - field: 'fieldTwo', + field: `${prefix != null ? `${prefix}.` : ''}fieldTwo`, value: reader.string() } break } case 3: { yield { - field: 'fieldThree', + field: `${prefix != null ? `${prefix}.` : ''}fieldThree`, value: EnumType.codec().decode(reader) } break } case 4: { yield { - field: 'fieldFour', + field: `${prefix != null ? `${prefix}.` : ''}fieldFour`, value: EnumType.codec().decode(reader) } break } case 5: { yield { - field: 'fieldFive', + field: `${prefix != null ? `${prefix}.` : ''}fieldFive`, value: reader.string() } break @@ -195,33 +185,6 @@ export namespace OneOfMessage { } } } - - if (obj.fieldTwo != null) { - delete obj.fieldOne - } - - if (obj.fieldOne != null) { - delete obj.fieldTwo - } - - if (obj.fieldFour != null) { - delete obj.fieldThree - } - - if (obj.fieldThree != null) { - delete obj.fieldFour - } - - if (opts.emitCollections === true) { - for (const [key, value] of Object.entries(obj)) { - if (Array.isArray(value) || value instanceof Map) { - yield { - field: key, - value - } - } - } - } }) } @@ -253,9 +216,6 @@ export namespace OneOfMessage { value: string } - export type OneOfMessageStreamEvent = OneOfMessageFieldOneFieldEvent | OneOfMessageFieldTwoFieldEvent | OneOfMessageFieldThreeFieldEvent | OneOfMessageFieldFourFieldEvent | OneOfMessageFieldFiveFieldEvent - export type OneOfMessageStreamCollectionsEvent = {} - export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, OneOfMessage.codec()) } @@ -264,9 +224,7 @@ export namespace OneOfMessage { return decodeMessage(buf, OneOfMessage.codec(), opts) } - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Generator { return streamMessage(buf, OneOfMessage.codec(), opts) } } @@ -280,11 +238,11 @@ export interface MessageWithoutOneOfs { } export namespace MessageWithoutOneOfs { - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -360,21 +318,7 @@ export namespace MessageWithoutOneOfs { } return obj - }, function * (reader, length, opts = {}) { - let obj: any - - if (opts.emitCollections === true) { - obj = { - fieldOne: '', - fieldTwo: '', - fieldThree: EnumType.Val1, - fieldFour: EnumType.Val1, - fieldFive: '' - } - } else { - obj = {} - } - + }, function * (reader, length, prefix, opts = {}) { const end = length == null ? reader.len : reader.pos + length while (reader.pos < end) { @@ -383,35 +327,35 @@ export namespace MessageWithoutOneOfs { switch (tag >>> 3) { case 1: { yield { - field: 'fieldOne', + field: `${prefix != null ? `${prefix}.` : ''}fieldOne`, value: reader.string() } break } case 2: { yield { - field: 'fieldTwo', + field: `${prefix != null ? `${prefix}.` : ''}fieldTwo`, value: reader.string() } break } case 3: { yield { - field: 'fieldThree', + field: `${prefix != null ? `${prefix}.` : ''}fieldThree`, value: EnumType.codec().decode(reader) } break } case 4: { yield { - field: 'fieldFour', + field: `${prefix != null ? `${prefix}.` : ''}fieldFour`, value: EnumType.codec().decode(reader) } break } case 5: { yield { - field: 'fieldFive', + field: `${prefix != null ? `${prefix}.` : ''}fieldFive`, value: reader.string() } break @@ -422,17 +366,6 @@ export namespace MessageWithoutOneOfs { } } } - - if (opts.emitCollections === true) { - for (const [key, value] of Object.entries(obj)) { - if (Array.isArray(value) || value instanceof Map) { - yield { - field: key, - value - } - } - } - } }) } @@ -464,9 +397,6 @@ export namespace MessageWithoutOneOfs { value: string } - export type MessageWithoutOneOfsStreamEvent = MessageWithoutOneOfsFieldOneFieldEvent | MessageWithoutOneOfsFieldTwoFieldEvent | MessageWithoutOneOfsFieldThreeFieldEvent | MessageWithoutOneOfsFieldFourFieldEvent | MessageWithoutOneOfsFieldFiveFieldEvent - export type MessageWithoutOneOfsStreamCollectionsEvent = {} - export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, MessageWithoutOneOfs.codec()) } @@ -475,9 +405,7 @@ export namespace MessageWithoutOneOfs { return decodeMessage(buf, MessageWithoutOneOfs.codec(), opts) } - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Generator { return streamMessage(buf, MessageWithoutOneOfs.codec(), opts) } } diff --git a/packages/protons/test/fixtures/optional.ts b/packages/protons/test/fixtures/optional.ts index 38140ff..05d0985 100644 --- a/packages/protons/test/fixtures/optional.ts +++ b/packages/protons/test/fixtures/optional.ts @@ -1,7 +1,5 @@ -/* eslint-disable complexity */ - import { decodeMessage, encodeMessage, enumeration, message, streamMessage } from 'protons-runtime' -import type { Codec, DecodeOptions, StreamingDecodeOptions, StreamingDecodeWithCollectionsOptions } from 'protons-runtime' +import type { Codec, DecodeOptions } from 'protons-runtime' import type { Uint8ArrayList } from 'uint8arraylist' export enum OptionalEnum { @@ -17,7 +15,7 @@ enum __OptionalEnumValues { } export namespace OptionalEnum { - export const codec = (): Codec => { + export const codec = (): Codec => { return enumeration(__OptionalEnumValues) } } @@ -28,11 +26,11 @@ export interface OptionalSubMessage { } export namespace OptionalSubMessage { - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -75,15 +73,7 @@ export namespace OptionalSubMessage { } return obj - }, function * (reader, length, opts = {}) { - let obj: any - - if (opts.emitCollections === true) { - obj = {} - } else { - obj = {} - } - + }, function * (reader, length, prefix, opts = {}) { const end = length == null ? reader.len : reader.pos + length while (reader.pos < end) { @@ -92,14 +82,14 @@ export namespace OptionalSubMessage { switch (tag >>> 3) { case 1: { yield { - field: 'foo', + field: `${prefix != null ? `${prefix}.` : ''}foo`, value: reader.string() } break } case 2: { yield { - field: 'bar', + field: `${prefix != null ? `${prefix}.` : ''}bar`, value: reader.int32() } break @@ -110,17 +100,6 @@ export namespace OptionalSubMessage { } } } - - if (opts.emitCollections === true) { - for (const [key, value] of Object.entries(obj)) { - if (Array.isArray(value) || value instanceof Map) { - yield { - field: key, - value - } - } - } - } }) } @@ -137,9 +116,6 @@ export namespace OptionalSubMessage { value: number } - export type OptionalSubMessageStreamEvent = OptionalSubMessageFooFieldEvent | OptionalSubMessageBarFieldEvent - export type OptionalSubMessageStreamCollectionsEvent = {} - export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, OptionalSubMessage.codec()) } @@ -148,9 +124,7 @@ export namespace OptionalSubMessage { return decodeMessage(buf, OptionalSubMessage.codec(), opts) } - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Generator { return streamMessage(buf, OptionalSubMessage.codec(), opts) } } @@ -176,11 +150,11 @@ export interface Optional { } export namespace Optional { - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -360,15 +334,7 @@ export namespace Optional { } return obj - }, function * (reader, length, opts = {}) { - let obj: any - - if (opts.emitCollections === true) { - obj = {} - } else { - obj = {} - } - + }, function * (reader, length, prefix, opts = {}) { const end = length == null ? reader.len : reader.pos + length while (reader.pos < end) { @@ -377,119 +343,119 @@ export namespace Optional { switch (tag >>> 3) { case 1: { yield { - field: 'double', + field: `${prefix != null ? `${prefix}.` : ''}double`, value: reader.double() } break } case 2: { yield { - field: 'float', + field: `${prefix != null ? `${prefix}.` : ''}float`, value: reader.float() } break } case 3: { yield { - field: 'int32', + field: `${prefix != null ? `${prefix}.` : ''}int32`, value: reader.int32() } break } case 4: { yield { - field: 'int64', + field: `${prefix != null ? `${prefix}.` : ''}int64`, value: reader.int64() } break } case 5: { yield { - field: 'uint32', + field: `${prefix != null ? `${prefix}.` : ''}uint32`, value: reader.uint32() } break } case 6: { yield { - field: 'uint64', + field: `${prefix != null ? `${prefix}.` : ''}uint64`, value: reader.uint64() } break } case 7: { yield { - field: 'sint32', + field: `${prefix != null ? `${prefix}.` : ''}sint32`, value: reader.sint32() } break } case 8: { yield { - field: 'sint64', + field: `${prefix != null ? `${prefix}.` : ''}sint64`, value: reader.sint64() } break } case 9: { yield { - field: 'fixed32', + field: `${prefix != null ? `${prefix}.` : ''}fixed32`, value: reader.fixed32() } break } case 10: { yield { - field: 'fixed64', + field: `${prefix != null ? `${prefix}.` : ''}fixed64`, value: reader.fixed64() } break } case 11: { yield { - field: 'sfixed32', + field: `${prefix != null ? `${prefix}.` : ''}sfixed32`, value: reader.sfixed32() } break } case 12: { yield { - field: 'sfixed64', + field: `${prefix != null ? `${prefix}.` : ''}sfixed64`, value: reader.sfixed64() } break } case 13: { yield { - field: 'bool', + field: `${prefix != null ? `${prefix}.` : ''}bool`, value: reader.bool() } break } case 14: { yield { - field: 'string', + field: `${prefix != null ? `${prefix}.` : ''}string`, value: reader.string() } break } case 15: { yield { - field: 'bytes', + field: `${prefix != null ? `${prefix}.` : ''}bytes`, value: reader.bytes() } break } case 16: { yield { - field: 'enum', + field: `${prefix != null ? `${prefix}.` : ''}enum`, value: OptionalEnum.codec().decode(reader) } break } case 17: { yield { - field: 'subMessage', + field: `${prefix != null ? `${prefix}.` : ''}subMessage`, value: OptionalSubMessage.codec().decode(reader, reader.uint32(), { limits: opts.limits?.subMessage }) @@ -502,17 +468,6 @@ export namespace Optional { } } } - - if (opts.emitCollections === true) { - for (const [key, value] of Object.entries(obj)) { - if (Array.isArray(value) || value instanceof Map) { - yield { - field: key, - value - } - } - } - } }) } @@ -599,13 +554,15 @@ export namespace Optional { value: OptionalEnum } - export interface OptionalSubMessageFieldEvent { - field: 'subMessage' - value: OptionalSubMessage + export interface OptionalSubMessageOptionalSubMessageFooFieldEvent { + field: 'foo' + value: string } - export type OptionalStreamEvent = OptionalDoubleFieldEvent | OptionalFloatFieldEvent | OptionalInt32FieldEvent | OptionalInt64FieldEvent | OptionalUint32FieldEvent | OptionalUint64FieldEvent | OptionalSint32FieldEvent | OptionalSint64FieldEvent | OptionalFixed32FieldEvent | OptionalFixed64FieldEvent | OptionalSfixed32FieldEvent | OptionalSfixed64FieldEvent | OptionalBoolFieldEvent | OptionalStringFieldEvent | OptionalBytesFieldEvent | OptionalEnumFieldEvent | OptionalSubMessageFieldEvent - export type OptionalStreamCollectionsEvent = {} + export interface OptionalSubMessageOptionalSubMessageBarFieldEvent { + field: 'bar' + value: number + } export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, Optional.codec()) @@ -615,9 +572,7 @@ export namespace Optional { return decodeMessage(buf, Optional.codec(), opts) } - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Generator { return streamMessage(buf, Optional.codec(), opts) } } diff --git a/packages/protons/test/fixtures/peer.ts b/packages/protons/test/fixtures/peer.ts index 958d45a..4be50bd 100644 --- a/packages/protons/test/fixtures/peer.ts +++ b/packages/protons/test/fixtures/peer.ts @@ -1,8 +1,6 @@ -/* eslint-disable complexity */ - import { decodeMessage, encodeMessage, MaxLengthError, message, streamMessage } from 'protons-runtime' import { alloc as uint8ArrayAlloc } from 'uint8arrays/alloc' -import type { Codec, DecodeOptions, StreamingDecodeOptions, StreamingDecodeWithCollectionsOptions } from 'protons-runtime' +import type { Codec, DecodeOptions } from 'protons-runtime' import type { Uint8ArrayList } from 'uint8arraylist' export interface Peer { @@ -14,11 +12,11 @@ export interface Peer { } export namespace Peer { - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -72,7 +70,7 @@ export namespace Peer { switch (tag >>> 3) { case 1: { if (opts.limits?.addresses != null && obj.addresses.length === opts.limits.addresses) { - throw new MaxLengthError('Decode error - map field "addresses" had too many elements') + throw new MaxLengthError('Decode error - repeated field "addresses" had too many elements') } obj.addresses.push(Address.codec().decode(reader, reader.uint32(), { @@ -82,7 +80,7 @@ export namespace Peer { } case 2: { if (opts.limits?.protocols != null && obj.protocols.length === opts.limits.protocols) { - throw new MaxLengthError('Decode error - map field "protocols" had too many elements') + throw new MaxLengthError('Decode error - repeated field "protocols" had too many elements') } obj.protocols.push(reader.string()) @@ -90,7 +88,7 @@ export namespace Peer { } case 3: { if (opts.limits?.metadata != null && obj.metadata.length === opts.limits.metadata) { - throw new MaxLengthError('Decode error - map field "metadata" had too many elements') + throw new MaxLengthError('Decode error - repeated field "metadata" had too many elements') } obj.metadata.push(Metadata.codec().decode(reader, reader.uint32(), { @@ -114,21 +112,11 @@ export namespace Peer { } return obj - }, function * (reader, length, opts = {}) { - let obj: any - - if (opts.emitCollections === true) { - obj = { - addresses: [], - protocols: [], - metadata: [] - } - } else { - obj = { - addresses: 0, - protocols: 0, - metadata: 0 - } + }, function * (reader, length, prefix, opts = {}) { + const obj = { + addresses: 0, + protocols: 0, + metadata: 0 } const end = length == null ? reader.len : reader.pos + length @@ -138,82 +126,67 @@ export namespace Peer { switch (tag >>> 3) { case 1: { - if (opts.limits?.addresses != null && (opts.emitCollections === true ? obj.addresses.length === opts.limits.addresses : obj.addresses === opts.limits.addresses)) { - throw new MaxLengthError('Decode error - map field "addresses" had too many elements') + if (opts.limits?.addresses != null && obj.addresses === opts.limits.addresses) { + throw new MaxLengthError('Decode error - repeated field "addresses" had too many elements') } const value = Address.codec().decode(reader, reader.uint32(), { limits: opts.limits?.addresses$ }) + obj.addresses++ yield { - field: 'addresses$value', - index: opts.emitCollections === true ? obj.addresses.length : obj.addresses, + field: `${prefix != null ? `${prefix}.` : ''}addresses`, + index: obj.addresses, value } - if (opts.emitCollections === true) { - obj.addresses.push(value) - } else { - obj.addresses++ - } - break } case 2: { - if (opts.limits?.protocols != null && (opts.emitCollections === true ? obj.protocols.length === opts.limits.protocols : obj.protocols === opts.limits.protocols)) { - throw new MaxLengthError('Decode error - map field "protocols" had too many elements') + if (opts.limits?.protocols != null && obj.protocols === opts.limits.protocols) { + throw new MaxLengthError('Decode error - repeated field "protocols" had too many elements') } const value = reader.string() + obj.protocols++ yield { - field: 'protocols$value', - index: opts.emitCollections === true ? obj.protocols.length : obj.protocols, + field: `${prefix != null ? `${prefix}.` : ''}protocols`, + index: obj.protocols, value } - if (opts.emitCollections === true) { - obj.protocols.push(value) - } else { - obj.protocols++ - } - break } case 3: { - if (opts.limits?.metadata != null && (opts.emitCollections === true ? obj.metadata.length === opts.limits.metadata : obj.metadata === opts.limits.metadata)) { - throw new MaxLengthError('Decode error - map field "metadata" had too many elements') + if (opts.limits?.metadata != null && obj.metadata === opts.limits.metadata) { + throw new MaxLengthError('Decode error - repeated field "metadata" had too many elements') } const value = Metadata.codec().decode(reader, reader.uint32(), { limits: opts.limits?.metadata$ }) + obj.metadata++ yield { - field: 'metadata$value', - index: opts.emitCollections === true ? obj.metadata.length : obj.metadata, + field: `${prefix != null ? `${prefix}.` : ''}metadata`, + index: obj.metadata, value } - if (opts.emitCollections === true) { - obj.metadata.push(value) - } else { - obj.metadata++ - } - break } case 4: { yield { - field: 'pubKey', + field: `${prefix != null ? `${prefix}.` : ''}pubKey`, value: reader.bytes() } break } case 5: { yield { - field: 'peerRecordEnvelope', + field: `${prefix != null ? `${prefix}.` : ''}peerRecordEnvelope`, value: reader.bytes() } break @@ -224,56 +197,18 @@ export namespace Peer { } } } - - if (opts.emitCollections === true) { - for (const [key, value] of Object.entries(obj)) { - if (Array.isArray(value) || value instanceof Map) { - yield { - field: key, - value - } - } - } - } }) } return _codec } - export interface PeerAddressesFieldEvent { - field: 'addresses' - value: Address[] - } - - export interface PeerAddressesValueEvent { - field: 'addresses$value' - index: number - value: Address - } - export interface PeerProtocolsFieldEvent { - field: 'protocols' - value: string[] - } - - export interface PeerProtocolsValueEvent { - field: 'protocols$value' + field: 'protocols$entry' index: number value: string } - export interface PeerMetadataFieldEvent { - field: 'metadata' - value: Metadata[] - } - - export interface PeerMetadataValueEvent { - field: 'metadata$value' - index: number - value: Metadata - } - export interface PeerPubKeyFieldEvent { field: 'pubKey' value: Uint8Array @@ -284,9 +219,6 @@ export namespace Peer { value: Uint8Array } - export type PeerStreamEvent = PeerAddressesValueEvent | PeerProtocolsValueEvent | PeerMetadataValueEvent | PeerPubKeyFieldEvent | PeerPeerRecordEnvelopeFieldEvent - export type PeerStreamCollectionsEvent = PeerAddressesFieldEvent | PeerProtocolsFieldEvent | PeerMetadataFieldEvent - export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, Peer.codec()) } @@ -295,9 +227,7 @@ export namespace Peer { return decodeMessage(buf, Peer.codec(), opts) } - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Generator { return streamMessage(buf, Peer.codec(), opts) } } @@ -308,11 +238,11 @@ export interface Address { } export namespace Address { - let _codec: Codec + let _codec: Codec
- export const codec = (): Codec => { + export const codec = (): Codec
=> { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message
((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -357,17 +287,7 @@ export namespace Address { } return obj - }, function * (reader, length, opts = {}) { - let obj: any - - if (opts.emitCollections === true) { - obj = { - multiaddr: uint8ArrayAlloc(0) - } - } else { - obj = {} - } - + }, function * (reader, length, prefix, opts = {}) { const end = length == null ? reader.len : reader.pos + length while (reader.pos < end) { @@ -376,14 +296,14 @@ export namespace Address { switch (tag >>> 3) { case 1: { yield { - field: 'multiaddr', + field: `${prefix != null ? `${prefix}.` : ''}multiaddr`, value: reader.bytes() } break } case 2: { yield { - field: 'isCertified', + field: `${prefix != null ? `${prefix}.` : ''}isCertified`, value: reader.bool() } break @@ -394,17 +314,6 @@ export namespace Address { } } } - - if (opts.emitCollections === true) { - for (const [key, value] of Object.entries(obj)) { - if (Array.isArray(value) || value instanceof Map) { - yield { - field: key, - value - } - } - } - } }) } @@ -421,9 +330,6 @@ export namespace Address { value: boolean } - export type AddressStreamEvent = AddressMultiaddrFieldEvent | AddressIsCertifiedFieldEvent - export type AddressStreamCollectionsEvent = {} - export function encode (obj: Partial
): Uint8Array { return encodeMessage(obj, Address.codec()) } @@ -432,9 +338,7 @@ export namespace Address { return decodeMessage(buf, Address.codec(), opts) } - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions
): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions
): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions
): Generator { return streamMessage(buf, Address.codec(), opts) } } @@ -445,11 +349,11 @@ export interface Metadata { } export namespace Metadata { - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -495,18 +399,7 @@ export namespace Metadata { } return obj - }, function * (reader, length, opts = {}) { - let obj: any - - if (opts.emitCollections === true) { - obj = { - key: '', - value: uint8ArrayAlloc(0) - } - } else { - obj = {} - } - + }, function * (reader, length, prefix, opts = {}) { const end = length == null ? reader.len : reader.pos + length while (reader.pos < end) { @@ -515,14 +408,14 @@ export namespace Metadata { switch (tag >>> 3) { case 1: { yield { - field: 'key', + field: `${prefix != null ? `${prefix}.` : ''}key`, value: reader.string() } break } case 2: { yield { - field: 'value', + field: `${prefix != null ? `${prefix}.` : ''}value`, value: reader.bytes() } break @@ -533,17 +426,6 @@ export namespace Metadata { } } } - - if (opts.emitCollections === true) { - for (const [key, value] of Object.entries(obj)) { - if (Array.isArray(value) || value instanceof Map) { - yield { - field: key, - value - } - } - } - } }) } @@ -560,9 +442,6 @@ export namespace Metadata { value: Uint8Array } - export type MetadataStreamEvent = MetadataKeyFieldEvent | MetadataValueFieldEvent - export type MetadataStreamCollectionsEvent = {} - export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, Metadata.codec()) } @@ -571,9 +450,7 @@ export namespace Metadata { return decodeMessage(buf, Metadata.codec(), opts) } - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Generator { return streamMessage(buf, Metadata.codec(), opts) } } diff --git a/packages/protons/test/fixtures/proto2.ts b/packages/protons/test/fixtures/proto2.ts index a81cf68..432a1d8 100644 --- a/packages/protons/test/fixtures/proto2.ts +++ b/packages/protons/test/fixtures/proto2.ts @@ -1,5 +1,5 @@ import { decodeMessage, encodeMessage, message, streamMessage } from 'protons-runtime' -import type { Codec, DecodeOptions, StreamingDecodeOptions, StreamingDecodeWithCollectionsOptions } from 'protons-runtime' +import type { Codec, DecodeOptions } from 'protons-runtime' import type { Uint8ArrayList } from 'uint8arraylist' export interface MessageWithRequired { @@ -7,11 +7,11 @@ export interface MessageWithRequired { } export namespace MessageWithRequired { - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -47,17 +47,7 @@ export namespace MessageWithRequired { } return obj - }, function * (reader, length, opts = {}) { - let obj: any - - if (opts.emitCollections === true) { - obj = { - scalarField: 0 - } - } else { - obj = {} - } - + }, function * (reader, length, prefix, opts = {}) { const end = length == null ? reader.len : reader.pos + length while (reader.pos < end) { @@ -66,7 +56,7 @@ export namespace MessageWithRequired { switch (tag >>> 3) { case 1: { yield { - field: 'scalarField', + field: `${prefix != null ? `${prefix}.` : ''}scalarField`, value: reader.int32() } break @@ -77,17 +67,6 @@ export namespace MessageWithRequired { } } } - - if (opts.emitCollections === true) { - for (const [key, value] of Object.entries(obj)) { - if (Array.isArray(value) || value instanceof Map) { - yield { - field: key, - value - } - } - } - } }) } @@ -99,9 +78,6 @@ export namespace MessageWithRequired { value: number } - export type MessageWithRequiredStreamEvent = MessageWithRequiredScalarFieldFieldEvent - export type MessageWithRequiredStreamCollectionsEvent = {} - export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, MessageWithRequired.codec()) } @@ -110,9 +86,7 @@ export namespace MessageWithRequired { return decodeMessage(buf, MessageWithRequired.codec(), opts) } - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Generator { return streamMessage(buf, MessageWithRequired.codec(), opts) } } diff --git a/packages/protons/test/fixtures/protons-options.ts b/packages/protons/test/fixtures/protons-options.ts index 96076f3..4a2185e 100644 --- a/packages/protons/test/fixtures/protons-options.ts +++ b/packages/protons/test/fixtures/protons-options.ts @@ -1,5 +1,5 @@ import { decodeMessage, encodeMessage, MaxLengthError, MaxSizeError, message, streamMessage } from 'protons-runtime' -import type { Codec, DecodeOptions, StreamingDecodeOptions, StreamingDecodeWithCollectionsOptions } from 'protons-runtime' +import type { Codec, DecodeOptions } from 'protons-runtime' import type { Uint8ArrayList } from 'uint8arraylist' export interface MessageWithSizeLimitedRepeatedField { @@ -7,11 +7,11 @@ export interface MessageWithSizeLimitedRepeatedField { } export namespace MessageWithSizeLimitedRepeatedField { - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -39,7 +39,7 @@ export namespace MessageWithSizeLimitedRepeatedField { switch (tag >>> 3) { case 1: { if (opts.limits?.repeatedField != null && obj.repeatedField.length === opts.limits.repeatedField) { - throw new MaxLengthError('Decode error - map field "repeatedField" had too many elements') + throw new MaxLengthError('Decode error - repeated field "repeatedField" had too many elements') } if (obj.repeatedField.length === 1) { @@ -57,17 +57,9 @@ export namespace MessageWithSizeLimitedRepeatedField { } return obj - }, function * (reader, length, opts = {}) { - let obj: any - - if (opts.emitCollections === true) { - obj = { - repeatedField: [] - } - } else { - obj = { - repeatedField: 0 - } + }, function * (reader, length, prefix, opts = {}) { + const obj = { + repeatedField: 1 } const end = length == null ? reader.len : reader.pos + length @@ -77,28 +69,23 @@ export namespace MessageWithSizeLimitedRepeatedField { switch (tag >>> 3) { case 1: { - if (opts.limits?.repeatedField != null && (opts.emitCollections === true ? obj.repeatedField.length === opts.limits.repeatedField : obj.repeatedField === opts.limits.repeatedField)) { - throw new MaxLengthError('Decode error - map field "repeatedField" had too many elements') + if (opts.limits?.repeatedField != null && obj.repeatedField === opts.limits.repeatedField) { + throw new MaxLengthError('Decode error - repeated field "repeatedField" had too many elements') } - if (opts.emitCollections === true ? obj.repeatedField.length === 1 : obj.repeatedField === 1) { + if (obj.repeatedField === 1) { throw new MaxLengthError('Decode error - repeated field "repeatedField" had too many elements') } const value = reader.string() + obj.repeatedField++ yield { - field: 'repeatedField$value', - index: opts.emitCollections === true ? obj.repeatedField.length : obj.repeatedField, + field: `${prefix != null ? `${prefix}.` : ''}repeatedField`, + index: obj.repeatedField, value } - if (opts.emitCollections === true) { - obj.repeatedField.push(value) - } else { - obj.repeatedField++ - } - break } default: { @@ -107,17 +94,6 @@ export namespace MessageWithSizeLimitedRepeatedField { } } } - - if (opts.emitCollections === true) { - for (const [key, value] of Object.entries(obj)) { - if (Array.isArray(value) || value instanceof Map) { - yield { - field: key, - value - } - } - } - } }) } @@ -125,19 +101,11 @@ export namespace MessageWithSizeLimitedRepeatedField { } export interface MessageWithSizeLimitedRepeatedFieldRepeatedFieldFieldEvent { - field: 'repeatedField' - value: string[] - } - - export interface MessageWithSizeLimitedRepeatedFieldRepeatedFieldValueEvent { - field: 'repeatedField$value' + field: 'repeatedField$entry' index: number value: string } - export type MessageWithSizeLimitedRepeatedFieldStreamEvent = MessageWithSizeLimitedRepeatedFieldRepeatedFieldValueEvent - export type MessageWithSizeLimitedRepeatedFieldStreamCollectionsEvent = MessageWithSizeLimitedRepeatedFieldRepeatedFieldFieldEvent - export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, MessageWithSizeLimitedRepeatedField.codec()) } @@ -146,9 +114,7 @@ export namespace MessageWithSizeLimitedRepeatedField { return decodeMessage(buf, MessageWithSizeLimitedRepeatedField.codec(), opts) } - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Generator { return streamMessage(buf, MessageWithSizeLimitedRepeatedField.codec(), opts) } } @@ -164,11 +130,11 @@ export namespace MessageWithSizeLimitedMap { } export namespace MessageWithSizeLimitedMap$mapFieldEntry { - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -214,18 +180,7 @@ export namespace MessageWithSizeLimitedMap { } return obj - }, function * (reader, length, opts = {}) { - let obj: any - - if (opts.emitCollections === true) { - obj = { - key: '', - value: '' - } - } else { - obj = {} - } - + }, function * (reader, length, prefix, opts = {}) { const end = length == null ? reader.len : reader.pos + length while (reader.pos < end) { @@ -234,14 +189,14 @@ export namespace MessageWithSizeLimitedMap { switch (tag >>> 3) { case 1: { yield { - field: 'key', + field: `${prefix != null ? `${prefix}.` : ''}key`, value: reader.string() } break } case 2: { yield { - field: 'value', + field: `${prefix != null ? `${prefix}.` : ''}value`, value: reader.string() } break @@ -252,17 +207,6 @@ export namespace MessageWithSizeLimitedMap { } } } - - if (opts.emitCollections === true) { - for (const [key, value] of Object.entries(obj)) { - if (Array.isArray(value) || value instanceof Map) { - yield { - field: key, - value - } - } - } - } }) } @@ -279,9 +223,6 @@ export namespace MessageWithSizeLimitedMap { value: string } - export type MessageWithSizeLimitedMap$mapFieldEntryStreamEvent = MessageWithSizeLimitedMap$mapFieldEntryKeyFieldEvent | MessageWithSizeLimitedMap$mapFieldEntryValueFieldEvent - export type MessageWithSizeLimitedMap$mapFieldEntryStreamCollectionsEvent = {} - export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, MessageWithSizeLimitedMap$mapFieldEntry.codec()) } @@ -290,23 +231,21 @@ export namespace MessageWithSizeLimitedMap { return decodeMessage(buf, MessageWithSizeLimitedMap$mapFieldEntry.codec(), opts) } - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Generator { return streamMessage(buf, MessageWithSizeLimitedMap$mapFieldEntry.codec(), opts) } } - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } - if (obj.mapField != null && obj.mapField.size !== 0) { + if (obj.mapField != null) { for (const [key, value] of obj.mapField.entries()) { w.uint32(10) MessageWithSizeLimitedMap.MessageWithSizeLimitedMap$mapFieldEntry.codec().encode({ key, value }, w) @@ -336,7 +275,11 @@ export namespace MessageWithSizeLimitedMap { throw new MaxSizeError('Decode error - map field "mapField" had too many elements') } - const entry = MessageWithSizeLimitedMap.MessageWithSizeLimitedMap$mapFieldEntry.codec().decode(reader, reader.uint32()) + const entry = MessageWithSizeLimitedMap.MessageWithSizeLimitedMap$mapFieldEntry.codec().decode(reader, reader.uint32(), { + limits: { + value: opts.limits?.mapField$value + } + }) obj.mapField.set(entry.key, entry.value) break } @@ -348,17 +291,9 @@ export namespace MessageWithSizeLimitedMap { } return obj - }, function * (reader, length, opts = {}) { - let obj: any - - if (opts.emitCollections === true) { - obj = { - mapField: new Map() - } - } else { - obj = { - mapField: 0 - } + }, function * (reader, length, prefix, opts = {}) { + const obj = { + mapField: 1 } const end = length == null ? reader.len : reader.pos + length @@ -368,28 +303,27 @@ export namespace MessageWithSizeLimitedMap { switch (tag >>> 3) { case 1: { - if (opts.limits?.mapField != null && (opts.emitCollections === true ? obj.mapField.size === opts.limits.mapField : obj.mapField === opts.limits.mapField)) { - throw new MaxSizeError('Decode error - map field "mapField" had too many elements') + if (opts.limits?.mapField != null && obj.mapField === opts.limits.mapField) { + throw new MaxLengthError('Decode error - map field "mapField" had too many elements') } - if (opts.emitCollections === true ? obj.mapField.size === 1 : obj.mapField === 1) { - throw new MaxSizeError('Decode error - map field "mapField" had too many elements') + if (obj.mapField === 1) { + throw new MaxLengthError('Decode error - repeated field "mapField" had too many elements') } - const entry = MessageWithSizeLimitedMap.MessageWithSizeLimitedMap$mapFieldEntry.codec().decode(reader, reader.uint32()) + const entry = MessageWithSizeLimitedMap.MessageWithSizeLimitedMap$mapFieldEntry.codec().decode(reader, reader.uint32(), { + limits: { + value: opts.limits?.mapField$value + } + }) + obj.mapField++ yield { - field: 'mapField', + field: `${prefix != null ? `${prefix}.` : ''}mapField`, key: entry.key, value: entry.value } - if (opts.emitCollections === true) { - obj.mapField.set(entry.key, entry.value) - } else { - obj.mapField++ - } - break } default: { @@ -398,17 +332,6 @@ export namespace MessageWithSizeLimitedMap { } } } - - if (opts.emitCollections === true) { - for (const [key, value] of Object.entries(obj)) { - if (Array.isArray(value) || value instanceof Map) { - yield { - field: key, - value - } - } - } - } }) } @@ -416,19 +339,11 @@ export namespace MessageWithSizeLimitedMap { } export interface MessageWithSizeLimitedMapMapFieldFieldEvent { - field: 'mapField' - value: Map - } - - export interface MessageWithSizeLimitedMapMapFieldEntryEvent { field: 'mapField$entry' key: string value: string } - export type MessageWithSizeLimitedMapStreamEvent = MessageWithSizeLimitedMapMapFieldEntryEvent - export type MessageWithSizeLimitedMapStreamCollectionsEvent = MessageWithSizeLimitedMapMapFieldFieldEvent - export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, MessageWithSizeLimitedMap.codec()) } @@ -437,9 +352,7 @@ export namespace MessageWithSizeLimitedMap { return decodeMessage(buf, MessageWithSizeLimitedMap.codec(), opts) } - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Generator { return streamMessage(buf, MessageWithSizeLimitedMap.codec(), opts) } } diff --git a/packages/protons/test/fixtures/repeated.ts b/packages/protons/test/fixtures/repeated.ts index 3e91f9f..b7e3d67 100644 --- a/packages/protons/test/fixtures/repeated.ts +++ b/packages/protons/test/fixtures/repeated.ts @@ -1,7 +1,5 @@ -/* eslint-disable complexity */ - import { decodeMessage, encodeMessage, MaxLengthError, message, streamMessage } from 'protons-runtime' -import type { Codec, DecodeOptions, StreamingDecodeOptions, StreamingDecodeWithCollectionsOptions } from 'protons-runtime' +import type { Codec, DecodeOptions } from 'protons-runtime' import type { Uint8ArrayList } from 'uint8arraylist' export interface SubSubMessage { @@ -10,11 +8,11 @@ export interface SubSubMessage { } export namespace SubSubMessage { - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -47,7 +45,7 @@ export namespace SubSubMessage { switch (tag >>> 3) { case 1: { if (opts.limits?.foo != null && obj.foo.length === opts.limits.foo) { - throw new MaxLengthError('Decode error - map field "foo" had too many elements') + throw new MaxLengthError('Decode error - repeated field "foo" had too many elements') } obj.foo.push(reader.string()) @@ -65,17 +63,9 @@ export namespace SubSubMessage { } return obj - }, function * (reader, length, opts = {}) { - let obj: any - - if (opts.emitCollections === true) { - obj = { - foo: [] - } - } else { - obj = { - foo: 0 - } + }, function * (reader, length, prefix, opts = {}) { + const obj = { + foo: 0 } const end = length == null ? reader.len : reader.pos + length @@ -85,29 +75,24 @@ export namespace SubSubMessage { switch (tag >>> 3) { case 1: { - if (opts.limits?.foo != null && (opts.emitCollections === true ? obj.foo.length === opts.limits.foo : obj.foo === opts.limits.foo)) { - throw new MaxLengthError('Decode error - map field "foo" had too many elements') + if (opts.limits?.foo != null && obj.foo === opts.limits.foo) { + throw new MaxLengthError('Decode error - repeated field "foo" had too many elements') } const value = reader.string() + obj.foo++ yield { - field: 'foo$value', - index: opts.emitCollections === true ? obj.foo.length : obj.foo, + field: `${prefix != null ? `${prefix}.` : ''}foo`, + index: obj.foo, value } - if (opts.emitCollections === true) { - obj.foo.push(value) - } else { - obj.foo++ - } - break } case 2: { yield { - field: 'nonRepeating', + field: `${prefix != null ? `${prefix}.` : ''}nonRepeating`, value: reader.uint32() } break @@ -118,17 +103,6 @@ export namespace SubSubMessage { } } } - - if (opts.emitCollections === true) { - for (const [key, value] of Object.entries(obj)) { - if (Array.isArray(value) || value instanceof Map) { - yield { - field: key, - value - } - } - } - } }) } @@ -136,12 +110,7 @@ export namespace SubSubMessage { } export interface SubSubMessageFooFieldEvent { - field: 'foo' - value: string[] - } - - export interface SubSubMessageFooValueEvent { - field: 'foo$value' + field: 'foo$entry' index: number value: string } @@ -151,9 +120,6 @@ export namespace SubSubMessage { value: number } - export type SubSubMessageStreamEvent = SubSubMessageFooValueEvent | SubSubMessageNonRepeatingFieldEvent - export type SubSubMessageStreamCollectionsEvent = SubSubMessageFooFieldEvent - export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, SubSubMessage.codec()) } @@ -162,9 +128,7 @@ export namespace SubSubMessage { return decodeMessage(buf, SubSubMessage.codec(), opts) } - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Generator { return streamMessage(buf, SubSubMessage.codec(), opts) } } @@ -177,11 +141,11 @@ export interface SubMessage { } export namespace SubMessage { - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -227,7 +191,7 @@ export namespace SubMessage { switch (tag >>> 3) { case 1: { if (opts.limits?.foo != null && obj.foo.length === opts.limits.foo) { - throw new MaxLengthError('Decode error - map field "foo" had too many elements') + throw new MaxLengthError('Decode error - repeated field "foo" had too many elements') } obj.foo.push(reader.string()) @@ -245,7 +209,7 @@ export namespace SubMessage { } case 4: { if (opts.limits?.messages != null && obj.messages.length === opts.limits.messages) { - throw new MaxLengthError('Decode error - map field "messages" had too many elements') + throw new MaxLengthError('Decode error - repeated field "messages" had too many elements') } obj.messages.push(SubSubMessage.codec().decode(reader, reader.uint32(), { @@ -261,19 +225,10 @@ export namespace SubMessage { } return obj - }, function * (reader, length, opts = {}) { - let obj: any - - if (opts.emitCollections === true) { - obj = { - foo: [], - messages: [] - } - } else { - obj = { - foo: 0, - messages: 0 - } + }, function * (reader, length, prefix, opts = {}) { + const obj = { + foo: 0, + messages: 0 } const end = length == null ? reader.len : reader.pos + length @@ -283,36 +238,31 @@ export namespace SubMessage { switch (tag >>> 3) { case 1: { - if (opts.limits?.foo != null && (opts.emitCollections === true ? obj.foo.length === opts.limits.foo : obj.foo === opts.limits.foo)) { - throw new MaxLengthError('Decode error - map field "foo" had too many elements') + if (opts.limits?.foo != null && obj.foo === opts.limits.foo) { + throw new MaxLengthError('Decode error - repeated field "foo" had too many elements') } const value = reader.string() + obj.foo++ yield { - field: 'foo$value', - index: opts.emitCollections === true ? obj.foo.length : obj.foo, + field: `${prefix != null ? `${prefix}.` : ''}foo`, + index: obj.foo, value } - if (opts.emitCollections === true) { - obj.foo.push(value) - } else { - obj.foo++ - } - break } case 2: { yield { - field: 'nonRepeating', + field: `${prefix != null ? `${prefix}.` : ''}nonRepeating`, value: reader.uint32() } break } case 3: { yield { - field: 'message', + field: `${prefix != null ? `${prefix}.` : ''}message`, value: SubSubMessage.codec().decode(reader, reader.uint32(), { limits: opts.limits?.message }) @@ -320,26 +270,21 @@ export namespace SubMessage { break } case 4: { - if (opts.limits?.messages != null && (opts.emitCollections === true ? obj.messages.length === opts.limits.messages : obj.messages === opts.limits.messages)) { - throw new MaxLengthError('Decode error - map field "messages" had too many elements') + if (opts.limits?.messages != null && obj.messages === opts.limits.messages) { + throw new MaxLengthError('Decode error - repeated field "messages" had too many elements') } const value = SubSubMessage.codec().decode(reader, reader.uint32(), { limits: opts.limits?.messages$ }) + obj.messages++ yield { - field: 'messages$value', - index: opts.emitCollections === true ? obj.messages.length : obj.messages, + field: `${prefix != null ? `${prefix}.` : ''}messages`, + index: obj.messages, value } - if (opts.emitCollections === true) { - obj.messages.push(value) - } else { - obj.messages++ - } - break } default: { @@ -348,17 +293,6 @@ export namespace SubMessage { } } } - - if (opts.emitCollections === true) { - for (const [key, value] of Object.entries(obj)) { - if (Array.isArray(value) || value instanceof Map) { - yield { - field: key, - value - } - } - } - } }) } @@ -366,12 +300,7 @@ export namespace SubMessage { } export interface SubMessageFooFieldEvent { - field: 'foo' - value: string[] - } - - export interface SubMessageFooValueEvent { - field: 'foo$value' + field: 'foo$entry' index: number value: string } @@ -381,24 +310,16 @@ export namespace SubMessage { value: number } - export interface SubMessageMessageFieldEvent { - field: 'message' - value: SubSubMessage - } - - export interface SubMessageMessagesFieldEvent { - field: 'messages' - value: SubSubMessage[] - } - - export interface SubMessageMessagesValueEvent { - field: 'messages$value' + export interface SubMessageMessageSubSubMessageFooFieldEvent { + field: 'foo$entry' index: number - value: SubSubMessage + value: string } - export type SubMessageStreamEvent = SubMessageFooValueEvent | SubMessageNonRepeatingFieldEvent | SubMessageMessageFieldEvent | SubMessageMessagesValueEvent - export type SubMessageStreamCollectionsEvent = SubMessageFooFieldEvent | SubMessageMessagesFieldEvent + export interface SubMessageMessageSubSubMessageNonRepeatingFieldEvent { + field: 'nonRepeating' + value: number + } export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, SubMessage.codec()) @@ -408,9 +329,7 @@ export namespace SubMessage { return decodeMessage(buf, SubMessage.codec(), opts) } - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Generator { return streamMessage(buf, SubMessage.codec(), opts) } } @@ -424,11 +343,11 @@ export interface RepeatedTypes { } export namespace RepeatedTypes { - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -482,7 +401,7 @@ export namespace RepeatedTypes { switch (tag >>> 3) { case 1: { if (opts.limits?.number != null && obj.number.length === opts.limits.number) { - throw new MaxLengthError('Decode error - map field "number" had too many elements') + throw new MaxLengthError('Decode error - repeated field "number" had too many elements') } obj.number.push(reader.uint32()) @@ -490,7 +409,7 @@ export namespace RepeatedTypes { } case 2: { if (opts.limits?.limitedNumber != null && obj.limitedNumber.length === opts.limits.limitedNumber) { - throw new MaxLengthError('Decode error - map field "limitedNumber" had too many elements') + throw new MaxLengthError('Decode error - repeated field "limitedNumber" had too many elements') } if (obj.limitedNumber.length === 1) { @@ -502,7 +421,7 @@ export namespace RepeatedTypes { } case 3: { if (opts.limits?.messages != null && obj.messages.length === opts.limits.messages) { - throw new MaxLengthError('Decode error - map field "messages" had too many elements') + throw new MaxLengthError('Decode error - repeated field "messages" had too many elements') } obj.messages.push(SubMessage.codec().decode(reader, reader.uint32(), { @@ -528,21 +447,11 @@ export namespace RepeatedTypes { } return obj - }, function * (reader, length, opts = {}) { - let obj: any - - if (opts.emitCollections === true) { - obj = { - number: [], - limitedNumber: [], - messages: [] - } - } else { - obj = { - number: 0, - limitedNumber: 0, - messages: 0 - } + }, function * (reader, length, prefix, opts = {}) { + const obj = { + number: 0, + limitedNumber: 1, + messages: 0 } const end = length == null ? reader.len : reader.pos + length @@ -552,77 +461,62 @@ export namespace RepeatedTypes { switch (tag >>> 3) { case 1: { - if (opts.limits?.number != null && (opts.emitCollections === true ? obj.number.length === opts.limits.number : obj.number === opts.limits.number)) { - throw new MaxLengthError('Decode error - map field "number" had too many elements') + if (opts.limits?.number != null && obj.number === opts.limits.number) { + throw new MaxLengthError('Decode error - repeated field "number" had too many elements') } const value = reader.uint32() + obj.number++ yield { - field: 'number$value', - index: opts.emitCollections === true ? obj.number.length : obj.number, + field: `${prefix != null ? `${prefix}.` : ''}number`, + index: obj.number, value } - if (opts.emitCollections === true) { - obj.number.push(value) - } else { - obj.number++ - } - break } case 2: { - if (opts.limits?.limitedNumber != null && (opts.emitCollections === true ? obj.limitedNumber.length === opts.limits.limitedNumber : obj.limitedNumber === opts.limits.limitedNumber)) { - throw new MaxLengthError('Decode error - map field "limitedNumber" had too many elements') + if (opts.limits?.limitedNumber != null && obj.limitedNumber === opts.limits.limitedNumber) { + throw new MaxLengthError('Decode error - repeated field "limitedNumber" had too many elements') } - if (opts.emitCollections === true ? obj.limitedNumber.length === 1 : obj.limitedNumber === 1) { + if (obj.limitedNumber === 1) { throw new MaxLengthError('Decode error - repeated field "limitedNumber" had too many elements') } const value = reader.uint32() + obj.limitedNumber++ yield { - field: 'limitedNumber$value', - index: opts.emitCollections === true ? obj.limitedNumber.length : obj.limitedNumber, + field: `${prefix != null ? `${prefix}.` : ''}limitedNumber`, + index: obj.limitedNumber, value } - if (opts.emitCollections === true) { - obj.limitedNumber.push(value) - } else { - obj.limitedNumber++ - } - break } case 3: { - if (opts.limits?.messages != null && (opts.emitCollections === true ? obj.messages.length === opts.limits.messages : obj.messages === opts.limits.messages)) { - throw new MaxLengthError('Decode error - map field "messages" had too many elements') + if (opts.limits?.messages != null && obj.messages === opts.limits.messages) { + throw new MaxLengthError('Decode error - repeated field "messages" had too many elements') } const value = SubMessage.codec().decode(reader, reader.uint32(), { limits: opts.limits?.messages$ }) + obj.messages++ yield { - field: 'messages$value', - index: opts.emitCollections === true ? obj.messages.length : obj.messages, + field: `${prefix != null ? `${prefix}.` : ''}messages`, + index: obj.messages, value } - if (opts.emitCollections === true) { - obj.messages.push(value) - } else { - obj.messages++ - } - break } case 4: { yield { - field: 'message', + field: `${prefix != null ? `${prefix}.` : ''}message`, value: SubMessage.codec().decode(reader, reader.uint32(), { limits: opts.limits?.message }) @@ -631,7 +525,7 @@ export namespace RepeatedTypes { } case 5: { yield { - field: 'nonRepeating', + field: `${prefix != null ? `${prefix}.` : ''}nonRepeating`, value: reader.uint32() } break @@ -642,17 +536,6 @@ export namespace RepeatedTypes { } } } - - if (opts.emitCollections === true) { - for (const [key, value] of Object.entries(obj)) { - if (Array.isArray(value) || value instanceof Map) { - yield { - field: key, - value - } - } - } - } }) } @@ -660,41 +543,37 @@ export namespace RepeatedTypes { } export interface RepeatedTypesNumberFieldEvent { - field: 'number' - value: number[] - } - - export interface RepeatedTypesNumberValueEvent { - field: 'number$value' + field: 'number$entry' index: number value: number } export interface RepeatedTypesLimitedNumberFieldEvent { - field: 'limitedNumber' - value: number[] + field: 'limitedNumber$entry' + index: number + value: number } - export interface RepeatedTypesLimitedNumberValueEvent { - field: 'limitedNumber$value' + export interface RepeatedTypesMessageSubMessageFooFieldEvent { + field: 'foo$entry' index: number - value: number + value: string } - export interface RepeatedTypesMessagesFieldEvent { - field: 'messages' - value: SubMessage[] + export interface RepeatedTypesMessageSubMessageNonRepeatingFieldEvent { + field: 'nonRepeating' + value: number } - export interface RepeatedTypesMessagesValueEvent { - field: 'messages$value' + export interface RepeatedTypesMessageSubMessageMessageSubSubMessageFooFieldEvent { + field: 'foo$entry' index: number - value: SubMessage + value: string } - export interface RepeatedTypesMessageFieldEvent { - field: 'message' - value: SubMessage + export interface RepeatedTypesMessageSubMessageMessageSubSubMessageNonRepeatingFieldEvent { + field: 'nonRepeating' + value: number } export interface RepeatedTypesNonRepeatingFieldEvent { @@ -702,9 +581,6 @@ export namespace RepeatedTypes { value: number } - export type RepeatedTypesStreamEvent = RepeatedTypesNumberValueEvent | RepeatedTypesLimitedNumberValueEvent | RepeatedTypesMessagesValueEvent | RepeatedTypesMessageFieldEvent | RepeatedTypesNonRepeatingFieldEvent - export type RepeatedTypesStreamCollectionsEvent = RepeatedTypesNumberFieldEvent | RepeatedTypesLimitedNumberFieldEvent | RepeatedTypesMessagesFieldEvent - export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, RepeatedTypes.codec()) } @@ -713,9 +589,7 @@ export namespace RepeatedTypes { return decodeMessage(buf, RepeatedTypes.codec(), opts) } - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Generator { return streamMessage(buf, RepeatedTypes.codec(), opts) } } diff --git a/packages/protons/test/fixtures/singular.ts b/packages/protons/test/fixtures/singular.ts index 728b05d..40b4deb 100644 --- a/packages/protons/test/fixtures/singular.ts +++ b/packages/protons/test/fixtures/singular.ts @@ -1,8 +1,6 @@ -/* eslint-disable complexity */ - import { decodeMessage, encodeMessage, enumeration, message, streamMessage } from 'protons-runtime' import { alloc as uint8ArrayAlloc } from 'uint8arrays/alloc' -import type { Codec, DecodeOptions, StreamingDecodeOptions, StreamingDecodeWithCollectionsOptions } from 'protons-runtime' +import type { Codec, DecodeOptions } from 'protons-runtime' import type { Uint8ArrayList } from 'uint8arraylist' export enum SingularEnum { @@ -18,7 +16,7 @@ enum __SingularEnumValues { } export namespace SingularEnum { - export const codec = (): Codec => { + export const codec = (): Codec => { return enumeration(__SingularEnumValues) } } @@ -29,11 +27,11 @@ export interface SingularSubMessage { } export namespace SingularSubMessage { - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -79,18 +77,7 @@ export namespace SingularSubMessage { } return obj - }, function * (reader, length, opts = {}) { - let obj: any - - if (opts.emitCollections === true) { - obj = { - foo: '', - bar: 0 - } - } else { - obj = {} - } - + }, function * (reader, length, prefix, opts = {}) { const end = length == null ? reader.len : reader.pos + length while (reader.pos < end) { @@ -99,14 +86,14 @@ export namespace SingularSubMessage { switch (tag >>> 3) { case 1: { yield { - field: 'foo', + field: `${prefix != null ? `${prefix}.` : ''}foo`, value: reader.string() } break } case 2: { yield { - field: 'bar', + field: `${prefix != null ? `${prefix}.` : ''}bar`, value: reader.int32() } break @@ -117,17 +104,6 @@ export namespace SingularSubMessage { } } } - - if (opts.emitCollections === true) { - for (const [key, value] of Object.entries(obj)) { - if (Array.isArray(value) || value instanceof Map) { - yield { - field: key, - value - } - } - } - } }) } @@ -144,9 +120,6 @@ export namespace SingularSubMessage { value: number } - export type SingularSubMessageStreamEvent = SingularSubMessageFooFieldEvent | SingularSubMessageBarFieldEvent - export type SingularSubMessageStreamCollectionsEvent = {} - export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, SingularSubMessage.codec()) } @@ -155,9 +128,7 @@ export namespace SingularSubMessage { return decodeMessage(buf, SingularSubMessage.codec(), opts) } - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Generator { return streamMessage(buf, SingularSubMessage.codec(), opts) } } @@ -183,11 +154,11 @@ export interface Singular { } export namespace Singular { - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -384,32 +355,7 @@ export namespace Singular { } return obj - }, function * (reader, length, opts = {}) { - let obj: any - - if (opts.emitCollections === true) { - obj = { - double: 0, - float: 0, - int32: 0, - int64: 0n, - uint32: 0, - uint64: 0n, - sint32: 0, - sint64: 0n, - fixed32: 0, - fixed64: 0n, - sfixed32: 0, - sfixed64: 0n, - bool: false, - string: '', - bytes: uint8ArrayAlloc(0), - enum: SingularEnum.NO_VALUE - } - } else { - obj = {} - } - + }, function * (reader, length, prefix, opts = {}) { const end = length == null ? reader.len : reader.pos + length while (reader.pos < end) { @@ -418,119 +364,119 @@ export namespace Singular { switch (tag >>> 3) { case 1: { yield { - field: 'double', + field: `${prefix != null ? `${prefix}.` : ''}double`, value: reader.double() } break } case 2: { yield { - field: 'float', + field: `${prefix != null ? `${prefix}.` : ''}float`, value: reader.float() } break } case 3: { yield { - field: 'int32', + field: `${prefix != null ? `${prefix}.` : ''}int32`, value: reader.int32() } break } case 4: { yield { - field: 'int64', + field: `${prefix != null ? `${prefix}.` : ''}int64`, value: reader.int64() } break } case 5: { yield { - field: 'uint32', + field: `${prefix != null ? `${prefix}.` : ''}uint32`, value: reader.uint32() } break } case 6: { yield { - field: 'uint64', + field: `${prefix != null ? `${prefix}.` : ''}uint64`, value: reader.uint64() } break } case 7: { yield { - field: 'sint32', + field: `${prefix != null ? `${prefix}.` : ''}sint32`, value: reader.sint32() } break } case 8: { yield { - field: 'sint64', + field: `${prefix != null ? `${prefix}.` : ''}sint64`, value: reader.sint64() } break } case 9: { yield { - field: 'fixed32', + field: `${prefix != null ? `${prefix}.` : ''}fixed32`, value: reader.fixed32() } break } case 10: { yield { - field: 'fixed64', + field: `${prefix != null ? `${prefix}.` : ''}fixed64`, value: reader.fixed64() } break } case 11: { yield { - field: 'sfixed32', + field: `${prefix != null ? `${prefix}.` : ''}sfixed32`, value: reader.sfixed32() } break } case 12: { yield { - field: 'sfixed64', + field: `${prefix != null ? `${prefix}.` : ''}sfixed64`, value: reader.sfixed64() } break } case 13: { yield { - field: 'bool', + field: `${prefix != null ? `${prefix}.` : ''}bool`, value: reader.bool() } break } case 14: { yield { - field: 'string', + field: `${prefix != null ? `${prefix}.` : ''}string`, value: reader.string() } break } case 15: { yield { - field: 'bytes', + field: `${prefix != null ? `${prefix}.` : ''}bytes`, value: reader.bytes() } break } case 16: { yield { - field: 'enum', + field: `${prefix != null ? `${prefix}.` : ''}enum`, value: SingularEnum.codec().decode(reader) } break } case 17: { yield { - field: 'subMessage', + field: `${prefix != null ? `${prefix}.` : ''}subMessage`, value: SingularSubMessage.codec().decode(reader, reader.uint32(), { limits: opts.limits?.subMessage }) @@ -543,17 +489,6 @@ export namespace Singular { } } } - - if (opts.emitCollections === true) { - for (const [key, value] of Object.entries(obj)) { - if (Array.isArray(value) || value instanceof Map) { - yield { - field: key, - value - } - } - } - } }) } @@ -640,13 +575,15 @@ export namespace Singular { value: SingularEnum } - export interface SingularSubMessageFieldEvent { - field: 'subMessage' - value: SingularSubMessage + export interface SingularSubMessageSingularSubMessageFooFieldEvent { + field: 'foo' + value: string } - export type SingularStreamEvent = SingularDoubleFieldEvent | SingularFloatFieldEvent | SingularInt32FieldEvent | SingularInt64FieldEvent | SingularUint32FieldEvent | SingularUint64FieldEvent | SingularSint32FieldEvent | SingularSint64FieldEvent | SingularFixed32FieldEvent | SingularFixed64FieldEvent | SingularSfixed32FieldEvent | SingularSfixed64FieldEvent | SingularBoolFieldEvent | SingularStringFieldEvent | SingularBytesFieldEvent | SingularEnumFieldEvent | SingularSubMessageFieldEvent - export type SingularStreamCollectionsEvent = {} + export interface SingularSubMessageSingularSubMessageBarFieldEvent { + field: 'bar' + value: number + } export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, Singular.codec()) @@ -656,9 +593,7 @@ export namespace Singular { return decodeMessage(buf, Singular.codec(), opts) } - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Generator { return streamMessage(buf, Singular.codec(), opts) } } diff --git a/packages/protons/test/fixtures/test.ts b/packages/protons/test/fixtures/test.ts index 2fbbcd1..cd6dfb9 100644 --- a/packages/protons/test/fixtures/test.ts +++ b/packages/protons/test/fixtures/test.ts @@ -1,7 +1,5 @@ -/* eslint-disable complexity */ - import { decodeMessage, encodeMessage, enumeration, MaxLengthError, message, streamMessage } from 'protons-runtime' -import type { Codec, DecodeOptions, StreamingDecodeOptions, StreamingDecodeWithCollectionsOptions } from 'protons-runtime' +import type { Codec, DecodeOptions } from 'protons-runtime' import type { Uint8ArrayList } from 'uint8arraylist' export enum AnEnum { @@ -15,7 +13,7 @@ enum __AnEnumValues { } export namespace AnEnum { - export const codec = (): Codec => { + export const codec = (): Codec => { return enumeration(__AnEnumValues) } } @@ -25,11 +23,11 @@ export interface SubMessage { } export namespace SubMessage { - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -65,17 +63,7 @@ export namespace SubMessage { } return obj - }, function * (reader, length, opts = {}) { - let obj: any - - if (opts.emitCollections === true) { - obj = { - foo: '' - } - } else { - obj = {} - } - + }, function * (reader, length, prefix, opts = {}) { const end = length == null ? reader.len : reader.pos + length while (reader.pos < end) { @@ -84,7 +72,7 @@ export namespace SubMessage { switch (tag >>> 3) { case 1: { yield { - field: 'foo', + field: `${prefix != null ? `${prefix}.` : ''}foo`, value: reader.string() } break @@ -95,17 +83,6 @@ export namespace SubMessage { } } } - - if (opts.emitCollections === true) { - for (const [key, value] of Object.entries(obj)) { - if (Array.isArray(value) || value instanceof Map) { - yield { - field: key, - value - } - } - } - } }) } @@ -117,9 +94,6 @@ export namespace SubMessage { value: string } - export type SubMessageStreamEvent = SubMessageFooFieldEvent - export type SubMessageStreamCollectionsEvent = {} - export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, SubMessage.codec()) } @@ -128,9 +102,7 @@ export namespace SubMessage { return decodeMessage(buf, SubMessage.codec(), opts) } - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Generator { return streamMessage(buf, SubMessage.codec(), opts) } } @@ -157,11 +129,11 @@ export interface AllTheTypes { } export namespace AllTheTypes { - let _codec: Codec + let _codec: Codec - export const codec = (): Codec => { + export const codec = (): Codec => { if (_codec == null) { - _codec = message((obj, w, opts = {}) => { + _codec = message((obj, w, opts = {}) => { if (opts.lengthDelimited !== false) { w.fork() } @@ -328,7 +300,7 @@ export namespace AllTheTypes { } case 14: { if (opts.limits?.field14 != null && obj.field14.length === opts.limits.field14) { - throw new MaxLengthError('Decode error - map field "field14" had too many elements') + throw new MaxLengthError('Decode error - repeated field "field14" had too many elements') } obj.field14.push(reader.string()) @@ -358,17 +330,9 @@ export namespace AllTheTypes { } return obj - }, function * (reader, length, opts = {}) { - let obj: any - - if (opts.emitCollections === true) { - obj = { - field14: [] - } - } else { - obj = { - field14: 0 - } + }, function * (reader, length, prefix, opts = {}) { + const obj = { + field14: 0 } const end = length == null ? reader.len : reader.pos + length @@ -379,91 +343,91 @@ export namespace AllTheTypes { switch (tag >>> 3) { case 1: { yield { - field: 'field1', + field: `${prefix != null ? `${prefix}.` : ''}field1`, value: reader.bool() } break } case 2: { yield { - field: 'field2', + field: `${prefix != null ? `${prefix}.` : ''}field2`, value: reader.int32() } break } case 3: { yield { - field: 'field3', + field: `${prefix != null ? `${prefix}.` : ''}field3`, value: reader.int64() } break } case 4: { yield { - field: 'field4', + field: `${prefix != null ? `${prefix}.` : ''}field4`, value: reader.uint32() } break } case 5: { yield { - field: 'field5', + field: `${prefix != null ? `${prefix}.` : ''}field5`, value: reader.uint64() } break } case 6: { yield { - field: 'field6', + field: `${prefix != null ? `${prefix}.` : ''}field6`, value: reader.sint32() } break } case 7: { yield { - field: 'field7', + field: `${prefix != null ? `${prefix}.` : ''}field7`, value: reader.sint64() } break } case 8: { yield { - field: 'field8', + field: `${prefix != null ? `${prefix}.` : ''}field8`, value: reader.double() } break } case 9: { yield { - field: 'field9', + field: `${prefix != null ? `${prefix}.` : ''}field9`, value: reader.float() } break } case 10: { yield { - field: 'field10', + field: `${prefix != null ? `${prefix}.` : ''}field10`, value: reader.string() } break } case 11: { yield { - field: 'field11', + field: `${prefix != null ? `${prefix}.` : ''}field11`, value: reader.bytes() } break } case 12: { yield { - field: 'field12', + field: `${prefix != null ? `${prefix}.` : ''}field12`, value: AnEnum.codec().decode(reader) } break } case 13: { yield { - field: 'field13', + field: `${prefix != null ? `${prefix}.` : ''}field13`, value: SubMessage.codec().decode(reader, reader.uint32(), { limits: opts.limits?.field13 }) @@ -471,50 +435,45 @@ export namespace AllTheTypes { break } case 14: { - if (opts.limits?.field14 != null && (opts.emitCollections === true ? obj.field14.length === opts.limits.field14 : obj.field14 === opts.limits.field14)) { - throw new MaxLengthError('Decode error - map field "field14" had too many elements') + if (opts.limits?.field14 != null && obj.field14 === opts.limits.field14) { + throw new MaxLengthError('Decode error - repeated field "field14" had too many elements') } const value = reader.string() + obj.field14++ yield { - field: 'field14$value', - index: opts.emitCollections === true ? obj.field14.length : obj.field14, + field: `${prefix != null ? `${prefix}.` : ''}field14`, + index: obj.field14, value } - if (opts.emitCollections === true) { - obj.field14.push(value) - } else { - obj.field14++ - } - break } case 15: { yield { - field: 'field15', + field: `${prefix != null ? `${prefix}.` : ''}field15`, value: reader.fixed32() } break } case 16: { yield { - field: 'field16', + field: `${prefix != null ? `${prefix}.` : ''}field16`, value: reader.fixed64() } break } case 17: { yield { - field: 'field17', + field: `${prefix != null ? `${prefix}.` : ''}field17`, value: reader.sfixed32() } break } case 18: { yield { - field: 'field18', + field: `${prefix != null ? `${prefix}.` : ''}field18`, value: reader.sfixed64() } break @@ -525,17 +484,6 @@ export namespace AllTheTypes { } } } - - if (opts.emitCollections === true) { - for (const [key, value] of Object.entries(obj)) { - if (Array.isArray(value) || value instanceof Map) { - yield { - field: key, - value - } - } - } - } }) } @@ -602,18 +550,13 @@ export namespace AllTheTypes { value: AnEnum } - export interface AllTheTypesField13FieldEvent { - field: 'field13' - value: SubMessage + export interface AllTheTypesField13SubMessageFooFieldEvent { + field: 'foo' + value: string } export interface AllTheTypesField14FieldEvent { - field: 'field14' - value: string[] - } - - export interface AllTheTypesField14ValueEvent { - field: 'field14$value' + field: 'field14$entry' index: number value: string } @@ -638,9 +581,6 @@ export namespace AllTheTypes { value: bigint } - export type AllTheTypesStreamEvent = AllTheTypesField1FieldEvent | AllTheTypesField2FieldEvent | AllTheTypesField3FieldEvent | AllTheTypesField4FieldEvent | AllTheTypesField5FieldEvent | AllTheTypesField6FieldEvent | AllTheTypesField7FieldEvent | AllTheTypesField8FieldEvent | AllTheTypesField9FieldEvent | AllTheTypesField10FieldEvent | AllTheTypesField11FieldEvent | AllTheTypesField12FieldEvent | AllTheTypesField13FieldEvent | AllTheTypesField14ValueEvent | AllTheTypesField15FieldEvent | AllTheTypesField16FieldEvent | AllTheTypesField17FieldEvent | AllTheTypesField18FieldEvent - export type AllTheTypesStreamCollectionsEvent = AllTheTypesField14FieldEvent - export function encode (obj: Partial): Uint8Array { return encodeMessage(obj, AllTheTypes.codec()) } @@ -649,9 +589,7 @@ export namespace AllTheTypes { return decodeMessage(buf, AllTheTypes.codec(), opts) } - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: StreamingDecodeWithCollectionsOptions): Generator - export function stream (buf: Uint8Array | Uint8ArrayList, opts?: any): Generator { + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Generator { return streamMessage(buf, AllTheTypes.codec(), opts) } } diff --git a/packages/protons/test/streaming-decode.spec.ts b/packages/protons/test/streaming-decode.spec.ts index bbc390a..74924a0 100644 --- a/packages/protons/test/streaming-decode.spec.ts +++ b/packages/protons/test/streaming-decode.spec.ts @@ -1,48 +1,8 @@ import { expect } from 'aegir/chai' import all from 'it-all' -import { AllTheTypes, AnEnum } from './fixtures/test.ts' - -describe('streaming-decode', () => { - it('should yield collections when asked to', async () => { - const values = { - field1: true, - field2: 2, - field3: 3n, - field4: 4, - field5: 5n, - field6: 6, - field7: 7n, - field8: 8, - field9: 9, - field10: '10', - field11: Uint8Array.from([11]), - field12: AnEnum.DERP, - field13: { - foo: '13' - }, - field14: [ - '14' - ], - field15: 15, - field16: 16n, - field17: 17, - field18: 18n - } - const input = AllTheTypes.encode(values) - - const events = all(AllTheTypes.stream(input, { - emitCollections: false - })) - - expect(events).to.have.lengthOf(Object.entries(values).length) - - const eventsWithCollections = all(AllTheTypes.stream(input, { - emitCollections: true - })) - - expect(eventsWithCollections).to.have.lengthOf(Object.entries(values).length + 1) - }) +import { AllTheTypes } from './fixtures/test.ts' +describe.skip('streaming-decode', () => { it('should include indexes in field values', async () => { const input = AllTheTypes.encode({ field14: [ From 6bf4cab5d3c11d1b06728ed4a23a4c24eaa76852 Mon Sep 17 00:00:00 2001 From: achingbrain Date: Fri, 20 Mar 2026 17:59:11 +0100 Subject: [PATCH 4/4] chore: add more streaming tests --- packages/protons-runtime/src/codecs/enum.ts | 17 +- packages/protons/src/fields/array-field.ts | 13 +- packages/protons/src/fields/map-field.ts | 11 +- packages/protons/src/fields/message-field.ts | 12 +- packages/protons/src/types/enum.ts | 4 + packages/protons/src/types/index.ts | 1 + packages/protons/src/types/message.ts | 29 + packages/protons/src/types/primitive.ts | 15 + packages/protons/test/fixtures/bitswap.ts | 73 +- packages/protons/test/fixtures/circuit.ts | 29 +- packages/protons/test/fixtures/daemon.ts | 268 ++-- packages/protons/test/fixtures/dht.ts | 45 +- packages/protons/test/fixtures/maps.ts | 64 +- packages/protons/test/fixtures/optional.ts | 10 +- packages/protons/test/fixtures/peer.ts | 45 +- .../protons/test/fixtures/protons-options.ts | 20 +- packages/protons/test/fixtures/repeated.ts | 94 +- packages/protons/test/fixtures/singular.ts | 10 +- .../protons/test/fixtures/streaming.proto | 36 + packages/protons/test/fixtures/streaming.ts | 1096 +++++++++++++++++ packages/protons/test/fixtures/test.ts | 19 +- .../protons/test/streaming-decode.spec.ts | 144 ++- 22 files changed, 1630 insertions(+), 425 deletions(-) create mode 100644 packages/protons/test/fixtures/streaming.proto create mode 100644 packages/protons/test/fixtures/streaming.ts diff --git a/packages/protons-runtime/src/codecs/enum.ts b/packages/protons-runtime/src/codecs/enum.ts index fb83643..525091a 100644 --- a/packages/protons-runtime/src/codecs/enum.ts +++ b/packages/protons-runtime/src/codecs/enum.ts @@ -1,8 +1,8 @@ import { createCodec, CODEC_TYPES } from '../codec.ts' -import type { DecodeFunction, EncodeFunction, Codec } from '../codec.ts' +import type { DecodeFunction, EncodeFunction, Codec, StreamFunction } from '../codec.ts' export function enumeration (v: any): Codec { - function findValue (val: string | number): number { + function findValue (val: any): number { // Use the reverse mapping to look up the enum key for the stored value // https://www.typescriptlang.org/docs/handbook/enums.html#reverse-mappings if (v[val.toString()] == null) { @@ -12,18 +12,23 @@ export function enumeration (v: any): Codec { return v[val] } - const encode: EncodeFunction = function enumEncode (val, writer) { + const encode: EncodeFunction = function enumEncode (val, writer) { const enumValue = findValue(val) writer.int32(enumValue) } - const decode: DecodeFunction = function enumDecode (reader) { + const decode: DecodeFunction = function enumDecode (reader) { const val = reader.int32() return findValue(val) } - // @ts-expect-error yeah yeah - return createCodec('enum', CODEC_TYPES.VARINT, encode, decode) + const stream: StreamFunction = function * enumStream (reader) { + const val = reader.int32() + + yield findValue(val) + } + + return createCodec('enum', CODEC_TYPES.VARINT, encode, decode, stream) } diff --git a/packages/protons/src/fields/array-field.ts b/packages/protons/src/fields/array-field.ts index 9d62a34..86ee0a3 100644 --- a/packages/protons/src/fields/array-field.ts +++ b/packages/protons/src/fields/array-field.ts @@ -80,14 +80,14 @@ export class ArrayField extends Field { let limit = ` if (opts.limits?.${this.name} != null && obj.${this.name} === opts.limits.${this.name}) { - throw new MaxLengthError('Decode error - repeated field "${this.name}" had too many elements') + throw new MaxLengthError('Streaming decode error - repeated field "${this.name}" had too many elements') } ` if (this.lengthLimit != null) { limit += ` if (obj.${this.name} === ${this.lengthLimit}) { - throw new MaxLengthError('Decode error - repeated field "${this.name}" had too many elements') + throw new MaxLengthError('Streaming decode error - repeated field "${this.name}" had too many elements') } ` } @@ -95,14 +95,9 @@ export class ArrayField extends Field { const type: Type = parent.findType(this.type) return `case ${this.id}: {${limit} - const value = ${type.getDecoder(this)} - obj.${this.name}++ + ${type.getStreamingDecoder(this, `\`\${prefix != null ? \`\${prefix}.\` : ''}${this.name}\``, ' ')} - yield { - field: \`\${prefix != null ? \`\${prefix}.\` : ''}${this.name}\`, - index: obj.${this.name}, - value - } + obj.${this.name}++ break }` diff --git a/packages/protons/src/fields/map-field.ts b/packages/protons/src/fields/map-field.ts index 7a88c9b..df3243e 100644 --- a/packages/protons/src/fields/map-field.ts +++ b/packages/protons/src/fields/map-field.ts @@ -90,17 +90,12 @@ export class MapField extends Field { ` } - const entryType = parent.findType(this.entryType) + const type = parent.findType(this.entryType) return `case ${this.id}: {${limit} - const entry = ${entryType.getDecoder(this)} - obj.${this.name}++ + ${type.getStreamingDecoder(this, `\`\${prefix != null ? \`\${prefix}.\` : ''}${this.name}\``, ' ')} - yield { - field: \`\${prefix != null ? \`\${prefix}.\` : ''}${this.name}\`, - key: entry.key, - value: entry.value - } + obj.${this.name}++ break }` diff --git a/packages/protons/src/fields/message-field.ts b/packages/protons/src/fields/message-field.ts index f9767db..e77b385 100644 --- a/packages/protons/src/fields/message-field.ts +++ b/packages/protons/src/fields/message-field.ts @@ -1,6 +1,6 @@ import { Message } from '../types/message.ts' import { Field } from './field.ts' -import type { Parent } from '../types/index.ts' +import type { Parent, Type } from '../types/index.ts' export class MessageField extends Field { getInterfaceField (parent: Parent, indent = ''): string { @@ -16,4 +16,14 @@ export class MessageField extends Field { return type } + + getStreamingDecoder (parent: Parent): string { + const type: Type = parent.findType(this.type) + + return `case ${this.id}: { + ${type.getStreamingDecoder(this, `\`\${prefix != null ? \`\${prefix}.\` : ''}${this.name}\``, ' ')} + + break + }` + } } diff --git a/packages/protons/src/types/enum.ts b/packages/protons/src/types/enum.ts index 856c06d..655da44 100644 --- a/packages/protons/src/types/enum.ts +++ b/packages/protons/src/types/enum.ts @@ -53,6 +53,10 @@ export class Enum implements Type { return `${this.jsType}.codec().decode(reader)` } + getStreamingDecoder (field: Field): string { + return `${this.jsType}.codec().stream(reader)` + } + getEncoder (field: Field, accessor: string): string { return `${this.jsType}.codec().encode(${accessor}, w)` } diff --git a/packages/protons/src/types/index.ts b/packages/protons/src/types/index.ts index 439e11c..db02ec2 100644 --- a/packages/protons/src/types/index.ts +++ b/packages/protons/src/types/index.ts @@ -7,6 +7,7 @@ export interface Type { pbType: string init(module: Module): void getDecoder(field: Field, indent?: string): string + getStreamingDecoder(field: Field, prefix: string, indent?: string): string getEncoder(field: Field, accessor: string): string getValueTest(field: Field, accessor: string): string } diff --git a/packages/protons/src/types/message.ts b/packages/protons/src/types/message.ts index 7e49e4a..35cb818 100644 --- a/packages/protons/src/types/message.ts +++ b/packages/protons/src/types/message.ts @@ -180,6 +180,35 @@ ${indent} }` return `${this.jsType}.codec().decode(reader, reader.uint32()${opts})` } + getStreamingDecoder (field: Field, prefix: string, indent = ''): string { + let opts = '' + + if (field instanceof MessageField) { + opts = `, { +${indent} limits: opts.limits?.${field.name} +${indent} }` + } else if (field instanceof ArrayField) { + opts = `, { +${indent} limits: opts.limits?.${field.name}$ +${indent} }` + + return `for (const evt of ${this.jsType}.codec().stream(reader, reader.uint32(), ${prefix}${opts})) { + yield { + ...evt, + index: obj.${field.name} + } + }` + } else if (field instanceof MapField) { + opts = `, { +${indent} limits: { +${indent} value: opts.limits?.${field.name}$value + } +${indent} }` + } + + return `yield * ${this.jsType}.codec().stream(reader, reader.uint32(), ${prefix}${opts})` + } + getEncoder (field: Field, accessor: string): string { if (field instanceof ArrayField) { // message fields are only written if they have values. But if a message diff --git a/packages/protons/src/types/primitive.ts b/packages/protons/src/types/primitive.ts index 6ca0d47..b6cbc8e 100644 --- a/packages/protons/src/types/primitive.ts +++ b/packages/protons/src/types/primitive.ts @@ -1,3 +1,4 @@ +import { ArrayField } from '../fields/array-field.ts' import type { Type } from './index.ts' import type { Field } from '../fields/field.ts' @@ -185,6 +186,20 @@ export class Primitive implements Type { return decoderGenerators[this.pbType](field.jsTypeOverride) } + getStreamingDecoder (field: Field, prefix: string, indent: string): string { + const generator = decoderGenerators[this.pbType](field.jsTypeOverride) + + if (field instanceof ArrayField) { + return `yield { + field: ${prefix}, + index: obj.${field.name}, + value: ${generator} + }` + } + + return generator + } + getValueTest (field: Field, accessor: string): string { // proto3 singular fields should only be written out if they are not the default value if (!field.optional && !field.proto2Required) { diff --git a/packages/protons/test/fixtures/bitswap.ts b/packages/protons/test/fixtures/bitswap.ts index 4489ca8..4241865 100644 --- a/packages/protons/test/fixtures/bitswap.ts +++ b/packages/protons/test/fixtures/bitswap.ts @@ -285,20 +285,20 @@ export namespace Message { switch (tag >>> 3) { case 1: { if (opts.limits?.entries != null && obj.entries === opts.limits.entries) { - throw new MaxLengthError('Decode error - repeated field "entries" had too many elements') + throw new MaxLengthError('Streaming decode error - repeated field "entries" had too many elements') } - const value = Message.Wantlist.Entry.codec().decode(reader, reader.uint32(), { + for (const evt of Message.Wantlist.Entry.codec().stream(reader, reader.uint32(), `${prefix != null ? `${prefix}.` : ''}entries`, { limits: opts.limits?.entries$ - }) - obj.entries++ - - yield { - field: `${prefix != null ? `${prefix}.` : ''}entries`, - index: obj.entries, - value + })) { + yield { + ...evt, + index: obj.entries + } } + obj.entries++ + break } case 2: { @@ -695,64 +695,61 @@ export namespace Message { switch (tag >>> 3) { case 1: { - yield { - field: `${prefix != null ? `${prefix}.` : ''}wantlist`, - value: Message.Wantlist.codec().decode(reader, reader.uint32(), { - limits: opts.limits?.wantlist - }) - } + yield * Message.Wantlist.codec().stream(reader, reader.uint32(), `${prefix != null ? `${prefix}.` : ''}wantlist`, { + limits: opts.limits?.wantlist + }) + break } case 2: { if (opts.limits?.blocks != null && obj.blocks === opts.limits.blocks) { - throw new MaxLengthError('Decode error - repeated field "blocks" had too many elements') + throw new MaxLengthError('Streaming decode error - repeated field "blocks" had too many elements') } - const value = reader.bytes() - obj.blocks++ - yield { field: `${prefix != null ? `${prefix}.` : ''}blocks`, index: obj.blocks, - value + value: reader.bytes() } + obj.blocks++ + break } case 3: { if (opts.limits?.payload != null && obj.payload === opts.limits.payload) { - throw new MaxLengthError('Decode error - repeated field "payload" had too many elements') + throw new MaxLengthError('Streaming decode error - repeated field "payload" had too many elements') } - const value = Message.Block.codec().decode(reader, reader.uint32(), { + for (const evt of Message.Block.codec().stream(reader, reader.uint32(), `${prefix != null ? `${prefix}.` : ''}payload`, { limits: opts.limits?.payload$ - }) - obj.payload++ - - yield { - field: `${prefix != null ? `${prefix}.` : ''}payload`, - index: obj.payload, - value + })) { + yield { + ...evt, + index: obj.payload + } } + obj.payload++ + break } case 4: { if (opts.limits?.blockPresences != null && obj.blockPresences === opts.limits.blockPresences) { - throw new MaxLengthError('Decode error - repeated field "blockPresences" had too many elements') + throw new MaxLengthError('Streaming decode error - repeated field "blockPresences" had too many elements') } - const value = Message.BlockPresence.codec().decode(reader, reader.uint32(), { + for (const evt of Message.BlockPresence.codec().stream(reader, reader.uint32(), `${prefix != null ? `${prefix}.` : ''}blockPresences`, { limits: opts.limits?.blockPresences$ - }) - obj.blockPresences++ - - yield { - field: `${prefix != null ? `${prefix}.` : ''}blockPresences`, - index: obj.blockPresences, - value + })) { + yield { + ...evt, + index: obj.blockPresences + } } + obj.blockPresences++ + break } case 5: { diff --git a/packages/protons/test/fixtures/circuit.ts b/packages/protons/test/fixtures/circuit.ts index 8c69c98..56d3b4e 100644 --- a/packages/protons/test/fixtures/circuit.ts +++ b/packages/protons/test/fixtures/circuit.ts @@ -157,18 +157,17 @@ export namespace CircuitRelay { } case 2: { if (opts.limits?.addrs != null && obj.addrs === opts.limits.addrs) { - throw new MaxLengthError('Decode error - repeated field "addrs" had too many elements') + throw new MaxLengthError('Streaming decode error - repeated field "addrs" had too many elements') } - const value = reader.bytes() - obj.addrs++ - yield { field: `${prefix != null ? `${prefix}.` : ''}addrs`, index: obj.addrs, - value + value: reader.bytes() } + obj.addrs++ + break } default: { @@ -291,21 +290,17 @@ export namespace CircuitRelay { break } case 2: { - yield { - field: `${prefix != null ? `${prefix}.` : ''}srcPeer`, - value: CircuitRelay.Peer.codec().decode(reader, reader.uint32(), { - limits: opts.limits?.srcPeer - }) - } + yield * CircuitRelay.Peer.codec().stream(reader, reader.uint32(), `${prefix != null ? `${prefix}.` : ''}srcPeer`, { + limits: opts.limits?.srcPeer + }) + break } case 3: { - yield { - field: `${prefix != null ? `${prefix}.` : ''}dstPeer`, - value: CircuitRelay.Peer.codec().decode(reader, reader.uint32(), { - limits: opts.limits?.dstPeer - }) - } + yield * CircuitRelay.Peer.codec().stream(reader, reader.uint32(), `${prefix != null ? `${prefix}.` : ''}dstPeer`, { + limits: opts.limits?.dstPeer + }) + break } case 4: { diff --git a/packages/protons/test/fixtures/daemon.ts b/packages/protons/test/fixtures/daemon.ts index 2fbe286..22087e9 100644 --- a/packages/protons/test/fixtures/daemon.ts +++ b/packages/protons/test/fixtures/daemon.ts @@ -191,75 +191,59 @@ export namespace Request { break } case 2: { - yield { - field: `${prefix != null ? `${prefix}.` : ''}connect`, - value: ConnectRequest.codec().decode(reader, reader.uint32(), { - limits: opts.limits?.connect - }) - } + yield * ConnectRequest.codec().stream(reader, reader.uint32(), `${prefix != null ? `${prefix}.` : ''}connect`, { + limits: opts.limits?.connect + }) + break } case 3: { - yield { - field: `${prefix != null ? `${prefix}.` : ''}streamOpen`, - value: StreamOpenRequest.codec().decode(reader, reader.uint32(), { - limits: opts.limits?.streamOpen - }) - } + yield * StreamOpenRequest.codec().stream(reader, reader.uint32(), `${prefix != null ? `${prefix}.` : ''}streamOpen`, { + limits: opts.limits?.streamOpen + }) + break } case 4: { - yield { - field: `${prefix != null ? `${prefix}.` : ''}streamHandler`, - value: StreamHandlerRequest.codec().decode(reader, reader.uint32(), { - limits: opts.limits?.streamHandler - }) - } + yield * StreamHandlerRequest.codec().stream(reader, reader.uint32(), `${prefix != null ? `${prefix}.` : ''}streamHandler`, { + limits: opts.limits?.streamHandler + }) + break } case 5: { - yield { - field: `${prefix != null ? `${prefix}.` : ''}dht`, - value: DHTRequest.codec().decode(reader, reader.uint32(), { - limits: opts.limits?.dht - }) - } + yield * DHTRequest.codec().stream(reader, reader.uint32(), `${prefix != null ? `${prefix}.` : ''}dht`, { + limits: opts.limits?.dht + }) + break } case 6: { - yield { - field: `${prefix != null ? `${prefix}.` : ''}connManager`, - value: ConnManagerRequest.codec().decode(reader, reader.uint32(), { - limits: opts.limits?.connManager - }) - } + yield * ConnManagerRequest.codec().stream(reader, reader.uint32(), `${prefix != null ? `${prefix}.` : ''}connManager`, { + limits: opts.limits?.connManager + }) + break } case 7: { - yield { - field: `${prefix != null ? `${prefix}.` : ''}disconnect`, - value: DisconnectRequest.codec().decode(reader, reader.uint32(), { - limits: opts.limits?.disconnect - }) - } + yield * DisconnectRequest.codec().stream(reader, reader.uint32(), `${prefix != null ? `${prefix}.` : ''}disconnect`, { + limits: opts.limits?.disconnect + }) + break } case 8: { - yield { - field: `${prefix != null ? `${prefix}.` : ''}pubsub`, - value: PSRequest.codec().decode(reader, reader.uint32(), { - limits: opts.limits?.pubsub - }) - } + yield * PSRequest.codec().stream(reader, reader.uint32(), `${prefix != null ? `${prefix}.` : ''}pubsub`, { + limits: opts.limits?.pubsub + }) + break } case 9: { - yield { - field: `${prefix != null ? `${prefix}.` : ''}peerStore`, - value: PeerstoreRequest.codec().decode(reader, reader.uint32(), { - limits: opts.limits?.peerStore - }) - } + yield * PeerstoreRequest.codec().stream(reader, reader.uint32(), `${prefix != null ? `${prefix}.` : ''}peerStore`, { + limits: opts.limits?.peerStore + }) + break } default: { @@ -597,75 +581,63 @@ export namespace Response { break } case 2: { - yield { - field: `${prefix != null ? `${prefix}.` : ''}error`, - value: ErrorResponse.codec().decode(reader, reader.uint32(), { - limits: opts.limits?.error - }) - } + yield * ErrorResponse.codec().stream(reader, reader.uint32(), `${prefix != null ? `${prefix}.` : ''}error`, { + limits: opts.limits?.error + }) + break } case 3: { - yield { - field: `${prefix != null ? `${prefix}.` : ''}streamInfo`, - value: StreamInfo.codec().decode(reader, reader.uint32(), { - limits: opts.limits?.streamInfo - }) - } + yield * StreamInfo.codec().stream(reader, reader.uint32(), `${prefix != null ? `${prefix}.` : ''}streamInfo`, { + limits: opts.limits?.streamInfo + }) + break } case 4: { - yield { - field: `${prefix != null ? `${prefix}.` : ''}identify`, - value: IdentifyResponse.codec().decode(reader, reader.uint32(), { - limits: opts.limits?.identify - }) - } + yield * IdentifyResponse.codec().stream(reader, reader.uint32(), `${prefix != null ? `${prefix}.` : ''}identify`, { + limits: opts.limits?.identify + }) + break } case 5: { - yield { - field: `${prefix != null ? `${prefix}.` : ''}dht`, - value: DHTResponse.codec().decode(reader, reader.uint32(), { - limits: opts.limits?.dht - }) - } + yield * DHTResponse.codec().stream(reader, reader.uint32(), `${prefix != null ? `${prefix}.` : ''}dht`, { + limits: opts.limits?.dht + }) + break } case 6: { if (opts.limits?.peers != null && obj.peers === opts.limits.peers) { - throw new MaxLengthError('Decode error - repeated field "peers" had too many elements') + throw new MaxLengthError('Streaming decode error - repeated field "peers" had too many elements') } - const value = PeerInfo.codec().decode(reader, reader.uint32(), { + for (const evt of PeerInfo.codec().stream(reader, reader.uint32(), `${prefix != null ? `${prefix}.` : ''}peers`, { limits: opts.limits?.peers$ - }) - obj.peers++ - - yield { - field: `${prefix != null ? `${prefix}.` : ''}peers`, - index: obj.peers, - value + })) { + yield { + ...evt, + index: obj.peers + } } + obj.peers++ + break } case 7: { - yield { - field: `${prefix != null ? `${prefix}.` : ''}pubsub`, - value: PSResponse.codec().decode(reader, reader.uint32(), { - limits: opts.limits?.pubsub - }) - } + yield * PSResponse.codec().stream(reader, reader.uint32(), `${prefix != null ? `${prefix}.` : ''}pubsub`, { + limits: opts.limits?.pubsub + }) + break } case 8: { - yield { - field: `${prefix != null ? `${prefix}.` : ''}peerStore`, - value: PeerstoreResponse.codec().decode(reader, reader.uint32(), { - limits: opts.limits?.peerStore - }) - } + yield * PeerstoreResponse.codec().stream(reader, reader.uint32(), `${prefix != null ? `${prefix}.` : ''}peerStore`, { + limits: opts.limits?.peerStore + }) + break } default: { @@ -861,18 +833,17 @@ export namespace IdentifyResponse { } case 2: { if (opts.limits?.addrs != null && obj.addrs === opts.limits.addrs) { - throw new MaxLengthError('Decode error - repeated field "addrs" had too many elements') + throw new MaxLengthError('Streaming decode error - repeated field "addrs" had too many elements') } - const value = reader.bytes() - obj.addrs++ - yield { field: `${prefix != null ? `${prefix}.` : ''}addrs`, index: obj.addrs, - value + value: reader.bytes() } + obj.addrs++ + break } default: { @@ -1003,18 +974,17 @@ export namespace ConnectRequest { } case 2: { if (opts.limits?.addrs != null && obj.addrs === opts.limits.addrs) { - throw new MaxLengthError('Decode error - repeated field "addrs" had too many elements') + throw new MaxLengthError('Streaming decode error - repeated field "addrs" had too many elements') } - const value = reader.bytes() - obj.addrs++ - yield { field: `${prefix != null ? `${prefix}.` : ''}addrs`, index: obj.addrs, - value + value: reader.bytes() } + obj.addrs++ + break } case 3: { @@ -1157,18 +1127,17 @@ export namespace StreamOpenRequest { } case 2: { if (opts.limits?.proto != null && obj.proto === opts.limits.proto) { - throw new MaxLengthError('Decode error - repeated field "proto" had too many elements') + throw new MaxLengthError('Streaming decode error - repeated field "proto" had too many elements') } - const value = reader.string() - obj.proto++ - yield { field: `${prefix != null ? `${prefix}.` : ''}proto`, index: obj.proto, - value + value: reader.string() } + obj.proto++ + break } case 3: { @@ -1301,18 +1270,17 @@ export namespace StreamHandlerRequest { } case 2: { if (opts.limits?.proto != null && obj.proto === opts.limits.proto) { - throw new MaxLengthError('Decode error - repeated field "proto" had too many elements') + throw new MaxLengthError('Streaming decode error - repeated field "proto" had too many elements') } - const value = reader.string() - obj.proto++ - yield { field: `${prefix != null ? `${prefix}.` : ''}proto`, index: obj.proto, - value + value: reader.string() } + obj.proto++ + break } default: { @@ -1926,12 +1894,10 @@ export namespace DHTResponse { break } case 2: { - yield { - field: `${prefix != null ? `${prefix}.` : ''}peer`, - value: PeerInfo.codec().decode(reader, reader.uint32(), { - limits: opts.limits?.peer - }) - } + yield * PeerInfo.codec().stream(reader, reader.uint32(), `${prefix != null ? `${prefix}.` : ''}peer`, { + limits: opts.limits?.peer + }) + break } case 3: { @@ -2069,18 +2035,17 @@ export namespace PeerInfo { } case 2: { if (opts.limits?.addrs != null && obj.addrs === opts.limits.addrs) { - throw new MaxLengthError('Decode error - repeated field "addrs" had too many elements') + throw new MaxLengthError('Streaming decode error - repeated field "addrs" had too many elements') } - const value = reader.bytes() - obj.addrs++ - yield { field: `${prefix != null ? `${prefix}.` : ''}addrs`, index: obj.addrs, - value + value: reader.bytes() } + obj.addrs++ + break } default: { @@ -2669,18 +2634,17 @@ export namespace PSMessage { } case 4: { if (opts.limits?.topicIDs != null && obj.topicIDs === opts.limits.topicIDs) { - throw new MaxLengthError('Decode error - repeated field "topicIDs" had too many elements') + throw new MaxLengthError('Streaming decode error - repeated field "topicIDs" had too many elements') } - const value = reader.string() - obj.topicIDs++ - yield { field: `${prefix != null ? `${prefix}.` : ''}topicIDs`, index: obj.topicIDs, - value + value: reader.string() } + obj.topicIDs++ + break } case 5: { @@ -2835,34 +2799,32 @@ export namespace PSResponse { switch (tag >>> 3) { case 1: { if (opts.limits?.topics != null && obj.topics === opts.limits.topics) { - throw new MaxLengthError('Decode error - repeated field "topics" had too many elements') + throw new MaxLengthError('Streaming decode error - repeated field "topics" had too many elements') } - const value = reader.string() - obj.topics++ - yield { field: `${prefix != null ? `${prefix}.` : ''}topics`, index: obj.topics, - value + value: reader.string() } + obj.topics++ + break } case 2: { if (opts.limits?.peerIDs != null && obj.peerIDs === opts.limits.peerIDs) { - throw new MaxLengthError('Decode error - repeated field "peerIDs" had too many elements') + throw new MaxLengthError('Streaming decode error - repeated field "peerIDs" had too many elements') } - const value = reader.bytes() - obj.peerIDs++ - yield { field: `${prefix != null ? `${prefix}.` : ''}peerIDs`, index: obj.peerIDs, - value + value: reader.bytes() } + obj.peerIDs++ + break } default: { @@ -3019,18 +2981,17 @@ export namespace PeerstoreRequest { } case 3: { if (opts.limits?.protos != null && obj.protos === opts.limits.protos) { - throw new MaxLengthError('Decode error - repeated field "protos" had too many elements') + throw new MaxLengthError('Streaming decode error - repeated field "protos" had too many elements') } - const value = reader.string() - obj.protos++ - yield { field: `${prefix != null ? `${prefix}.` : ''}protos`, index: obj.protos, - value + value: reader.string() } + obj.protos++ + break } default: { @@ -3149,28 +3110,25 @@ export namespace PeerstoreResponse { switch (tag >>> 3) { case 1: { - yield { - field: `${prefix != null ? `${prefix}.` : ''}peer`, - value: PeerInfo.codec().decode(reader, reader.uint32(), { - limits: opts.limits?.peer - }) - } + yield * PeerInfo.codec().stream(reader, reader.uint32(), `${prefix != null ? `${prefix}.` : ''}peer`, { + limits: opts.limits?.peer + }) + break } case 2: { if (opts.limits?.protos != null && obj.protos === opts.limits.protos) { - throw new MaxLengthError('Decode error - repeated field "protos" had too many elements') + throw new MaxLengthError('Streaming decode error - repeated field "protos" had too many elements') } - const value = reader.string() - obj.protos++ - yield { field: `${prefix != null ? `${prefix}.` : ''}protos`, index: obj.protos, - value + value: reader.string() } + obj.protos++ + break } default: { diff --git a/packages/protons/test/fixtures/dht.ts b/packages/protons/test/fixtures/dht.ts index 3174a5e..2799413 100644 --- a/packages/protons/test/fixtures/dht.ts +++ b/packages/protons/test/fixtures/dht.ts @@ -322,18 +322,17 @@ export namespace Message { } case 2: { if (opts.limits?.addrs != null && obj.addrs === opts.limits.addrs) { - throw new MaxLengthError('Decode error - repeated field "addrs" had too many elements') + throw new MaxLengthError('Streaming decode error - repeated field "addrs" had too many elements') } - const value = reader.bytes() - obj.addrs++ - yield { field: `${prefix != null ? `${prefix}.` : ''}addrs`, index: obj.addrs, - value + value: reader.bytes() } + obj.addrs++ + break } case 3: { @@ -528,38 +527,38 @@ export namespace Message { } case 8: { if (opts.limits?.closerPeers != null && obj.closerPeers === opts.limits.closerPeers) { - throw new MaxLengthError('Decode error - repeated field "closerPeers" had too many elements') + throw new MaxLengthError('Streaming decode error - repeated field "closerPeers" had too many elements') } - const value = Message.Peer.codec().decode(reader, reader.uint32(), { + for (const evt of Message.Peer.codec().stream(reader, reader.uint32(), `${prefix != null ? `${prefix}.` : ''}closerPeers`, { limits: opts.limits?.closerPeers$ - }) - obj.closerPeers++ - - yield { - field: `${prefix != null ? `${prefix}.` : ''}closerPeers`, - index: obj.closerPeers, - value + })) { + yield { + ...evt, + index: obj.closerPeers + } } + obj.closerPeers++ + break } case 9: { if (opts.limits?.providerPeers != null && obj.providerPeers === opts.limits.providerPeers) { - throw new MaxLengthError('Decode error - repeated field "providerPeers" had too many elements') + throw new MaxLengthError('Streaming decode error - repeated field "providerPeers" had too many elements') } - const value = Message.Peer.codec().decode(reader, reader.uint32(), { + for (const evt of Message.Peer.codec().stream(reader, reader.uint32(), `${prefix != null ? `${prefix}.` : ''}providerPeers`, { limits: opts.limits?.providerPeers$ - }) - obj.providerPeers++ - - yield { - field: `${prefix != null ? `${prefix}.` : ''}providerPeers`, - index: obj.providerPeers, - value + })) { + yield { + ...evt, + index: obj.providerPeers + } } + obj.providerPeers++ + break } default: { diff --git a/packages/protons/test/fixtures/maps.ts b/packages/protons/test/fixtures/maps.ts index 165e4cc..692e889 100644 --- a/packages/protons/test/fixtures/maps.ts +++ b/packages/protons/test/fixtures/maps.ts @@ -102,18 +102,17 @@ export namespace SubMessage { } case 2: { if (opts.limits?.bar != null && obj.bar === opts.limits.bar) { - throw new MaxLengthError('Decode error - repeated field "bar" had too many elements') + throw new MaxLengthError('Streaming decode error - repeated field "bar" had too many elements') } - const value = reader.uint32() - obj.bar++ - yield { field: `${prefix != null ? `${prefix}.` : ''}bar`, index: obj.bar, - value + value: reader.uint32() } + obj.bar++ + break } default: { @@ -569,12 +568,10 @@ export namespace MapTypes { break } case 2: { - yield { - field: `${prefix != null ? `${prefix}.` : ''}value`, - value: SubMessage.codec().decode(reader, reader.uint32(), { - limits: opts.limits?.value - }) - } + yield * SubMessage.codec().stream(reader, reader.uint32(), `${prefix != null ? `${prefix}.` : ''}value`, { + limits: opts.limits?.value + }) + break } default: { @@ -885,18 +882,13 @@ export namespace MapTypes { throw new MaxLengthError('Decode error - map field "stringMap" had too many elements') } - const entry = MapTypes.MapTypes$stringMapEntry.codec().decode(reader, reader.uint32(), { + yield * MapTypes.MapTypes$stringMapEntry.codec().stream(reader, reader.uint32(), `${prefix != null ? `${prefix}.` : ''}stringMap`, { limits: { value: opts.limits?.stringMap$value } }) - obj.stringMap++ - yield { - field: `${prefix != null ? `${prefix}.` : ''}stringMap`, - key: entry.key, - value: entry.value - } + obj.stringMap++ break } @@ -905,18 +897,13 @@ export namespace MapTypes { throw new MaxLengthError('Decode error - map field "intMap" had too many elements') } - const entry = MapTypes.MapTypes$intMapEntry.codec().decode(reader, reader.uint32(), { + yield * MapTypes.MapTypes$intMapEntry.codec().stream(reader, reader.uint32(), `${prefix != null ? `${prefix}.` : ''}intMap`, { limits: { value: opts.limits?.intMap$value } }) - obj.intMap++ - yield { - field: `${prefix != null ? `${prefix}.` : ''}intMap`, - key: entry.key, - value: entry.value - } + obj.intMap++ break } @@ -925,18 +912,13 @@ export namespace MapTypes { throw new MaxLengthError('Decode error - map field "boolMap" had too many elements') } - const entry = MapTypes.MapTypes$boolMapEntry.codec().decode(reader, reader.uint32(), { + yield * MapTypes.MapTypes$boolMapEntry.codec().stream(reader, reader.uint32(), `${prefix != null ? `${prefix}.` : ''}boolMap`, { limits: { value: opts.limits?.boolMap$value } }) - obj.boolMap++ - yield { - field: `${prefix != null ? `${prefix}.` : ''}boolMap`, - key: entry.key, - value: entry.value - } + obj.boolMap++ break } @@ -945,18 +927,13 @@ export namespace MapTypes { throw new MaxLengthError('Decode error - map field "messageMap" had too many elements') } - const entry = MapTypes.MapTypes$messageMapEntry.codec().decode(reader, reader.uint32(), { + yield * MapTypes.MapTypes$messageMapEntry.codec().stream(reader, reader.uint32(), `${prefix != null ? `${prefix}.` : ''}messageMap`, { limits: { value: opts.limits?.messageMap$value } }) - obj.messageMap++ - yield { - field: `${prefix != null ? `${prefix}.` : ''}messageMap`, - key: entry.key, - value: entry.value - } + obj.messageMap++ break } @@ -965,18 +942,13 @@ export namespace MapTypes { throw new MaxLengthError('Decode error - map field "enumMap" had too many elements') } - const entry = MapTypes.MapTypes$enumMapEntry.codec().decode(reader, reader.uint32(), { + yield * MapTypes.MapTypes$enumMapEntry.codec().stream(reader, reader.uint32(), `${prefix != null ? `${prefix}.` : ''}enumMap`, { limits: { value: opts.limits?.enumMap$value } }) - obj.enumMap++ - yield { - field: `${prefix != null ? `${prefix}.` : ''}enumMap`, - key: entry.key, - value: entry.value - } + obj.enumMap++ break } diff --git a/packages/protons/test/fixtures/optional.ts b/packages/protons/test/fixtures/optional.ts index 05d0985..d00b800 100644 --- a/packages/protons/test/fixtures/optional.ts +++ b/packages/protons/test/fixtures/optional.ts @@ -454,12 +454,10 @@ export namespace Optional { break } case 17: { - yield { - field: `${prefix != null ? `${prefix}.` : ''}subMessage`, - value: OptionalSubMessage.codec().decode(reader, reader.uint32(), { - limits: opts.limits?.subMessage - }) - } + yield * OptionalSubMessage.codec().stream(reader, reader.uint32(), `${prefix != null ? `${prefix}.` : ''}subMessage`, { + limits: opts.limits?.subMessage + }) + break } default: { diff --git a/packages/protons/test/fixtures/peer.ts b/packages/protons/test/fixtures/peer.ts index 4be50bd..271e5e5 100644 --- a/packages/protons/test/fixtures/peer.ts +++ b/packages/protons/test/fixtures/peer.ts @@ -127,54 +127,53 @@ export namespace Peer { switch (tag >>> 3) { case 1: { if (opts.limits?.addresses != null && obj.addresses === opts.limits.addresses) { - throw new MaxLengthError('Decode error - repeated field "addresses" had too many elements') + throw new MaxLengthError('Streaming decode error - repeated field "addresses" had too many elements') } - const value = Address.codec().decode(reader, reader.uint32(), { + for (const evt of Address.codec().stream(reader, reader.uint32(), `${prefix != null ? `${prefix}.` : ''}addresses`, { limits: opts.limits?.addresses$ - }) - obj.addresses++ - - yield { - field: `${prefix != null ? `${prefix}.` : ''}addresses`, - index: obj.addresses, - value + })) { + yield { + ...evt, + index: obj.addresses + } } + obj.addresses++ + break } case 2: { if (opts.limits?.protocols != null && obj.protocols === opts.limits.protocols) { - throw new MaxLengthError('Decode error - repeated field "protocols" had too many elements') + throw new MaxLengthError('Streaming decode error - repeated field "protocols" had too many elements') } - const value = reader.string() - obj.protocols++ - yield { field: `${prefix != null ? `${prefix}.` : ''}protocols`, index: obj.protocols, - value + value: reader.string() } + obj.protocols++ + break } case 3: { if (opts.limits?.metadata != null && obj.metadata === opts.limits.metadata) { - throw new MaxLengthError('Decode error - repeated field "metadata" had too many elements') + throw new MaxLengthError('Streaming decode error - repeated field "metadata" had too many elements') } - const value = Metadata.codec().decode(reader, reader.uint32(), { + for (const evt of Metadata.codec().stream(reader, reader.uint32(), `${prefix != null ? `${prefix}.` : ''}metadata`, { limits: opts.limits?.metadata$ - }) - obj.metadata++ - - yield { - field: `${prefix != null ? `${prefix}.` : ''}metadata`, - index: obj.metadata, - value + })) { + yield { + ...evt, + index: obj.metadata + } } + obj.metadata++ + break } case 4: { diff --git a/packages/protons/test/fixtures/protons-options.ts b/packages/protons/test/fixtures/protons-options.ts index 4a2185e..2ca72ff 100644 --- a/packages/protons/test/fixtures/protons-options.ts +++ b/packages/protons/test/fixtures/protons-options.ts @@ -70,22 +70,21 @@ export namespace MessageWithSizeLimitedRepeatedField { switch (tag >>> 3) { case 1: { if (opts.limits?.repeatedField != null && obj.repeatedField === opts.limits.repeatedField) { - throw new MaxLengthError('Decode error - repeated field "repeatedField" had too many elements') + throw new MaxLengthError('Streaming decode error - repeated field "repeatedField" had too many elements') } if (obj.repeatedField === 1) { - throw new MaxLengthError('Decode error - repeated field "repeatedField" had too many elements') + throw new MaxLengthError('Streaming decode error - repeated field "repeatedField" had too many elements') } - const value = reader.string() - obj.repeatedField++ - yield { field: `${prefix != null ? `${prefix}.` : ''}repeatedField`, index: obj.repeatedField, - value + value: reader.string() } + obj.repeatedField++ + break } default: { @@ -311,18 +310,13 @@ export namespace MessageWithSizeLimitedMap { throw new MaxLengthError('Decode error - repeated field "mapField" had too many elements') } - const entry = MessageWithSizeLimitedMap.MessageWithSizeLimitedMap$mapFieldEntry.codec().decode(reader, reader.uint32(), { + yield * MessageWithSizeLimitedMap.MessageWithSizeLimitedMap$mapFieldEntry.codec().stream(reader, reader.uint32(), `${prefix != null ? `${prefix}.` : ''}mapField`, { limits: { value: opts.limits?.mapField$value } }) - obj.mapField++ - yield { - field: `${prefix != null ? `${prefix}.` : ''}mapField`, - key: entry.key, - value: entry.value - } + obj.mapField++ break } diff --git a/packages/protons/test/fixtures/repeated.ts b/packages/protons/test/fixtures/repeated.ts index b7e3d67..aaf2f35 100644 --- a/packages/protons/test/fixtures/repeated.ts +++ b/packages/protons/test/fixtures/repeated.ts @@ -76,18 +76,17 @@ export namespace SubSubMessage { switch (tag >>> 3) { case 1: { if (opts.limits?.foo != null && obj.foo === opts.limits.foo) { - throw new MaxLengthError('Decode error - repeated field "foo" had too many elements') + throw new MaxLengthError('Streaming decode error - repeated field "foo" had too many elements') } - const value = reader.string() - obj.foo++ - yield { field: `${prefix != null ? `${prefix}.` : ''}foo`, index: obj.foo, - value + value: reader.string() } + obj.foo++ + break } case 2: { @@ -239,18 +238,17 @@ export namespace SubMessage { switch (tag >>> 3) { case 1: { if (opts.limits?.foo != null && obj.foo === opts.limits.foo) { - throw new MaxLengthError('Decode error - repeated field "foo" had too many elements') + throw new MaxLengthError('Streaming decode error - repeated field "foo" had too many elements') } - const value = reader.string() - obj.foo++ - yield { field: `${prefix != null ? `${prefix}.` : ''}foo`, index: obj.foo, - value + value: reader.string() } + obj.foo++ + break } case 2: { @@ -261,30 +259,28 @@ export namespace SubMessage { break } case 3: { - yield { - field: `${prefix != null ? `${prefix}.` : ''}message`, - value: SubSubMessage.codec().decode(reader, reader.uint32(), { - limits: opts.limits?.message - }) - } + yield * SubSubMessage.codec().stream(reader, reader.uint32(), `${prefix != null ? `${prefix}.` : ''}message`, { + limits: opts.limits?.message + }) + break } case 4: { if (opts.limits?.messages != null && obj.messages === opts.limits.messages) { - throw new MaxLengthError('Decode error - repeated field "messages" had too many elements') + throw new MaxLengthError('Streaming decode error - repeated field "messages" had too many elements') } - const value = SubSubMessage.codec().decode(reader, reader.uint32(), { + for (const evt of SubSubMessage.codec().stream(reader, reader.uint32(), `${prefix != null ? `${prefix}.` : ''}messages`, { limits: opts.limits?.messages$ - }) - obj.messages++ - - yield { - field: `${prefix != null ? `${prefix}.` : ''}messages`, - index: obj.messages, - value + })) { + yield { + ...evt, + index: obj.messages + } } + obj.messages++ + break } default: { @@ -462,65 +458,61 @@ export namespace RepeatedTypes { switch (tag >>> 3) { case 1: { if (opts.limits?.number != null && obj.number === opts.limits.number) { - throw new MaxLengthError('Decode error - repeated field "number" had too many elements') + throw new MaxLengthError('Streaming decode error - repeated field "number" had too many elements') } - const value = reader.uint32() - obj.number++ - yield { field: `${prefix != null ? `${prefix}.` : ''}number`, index: obj.number, - value + value: reader.uint32() } + obj.number++ + break } case 2: { if (opts.limits?.limitedNumber != null && obj.limitedNumber === opts.limits.limitedNumber) { - throw new MaxLengthError('Decode error - repeated field "limitedNumber" had too many elements') + throw new MaxLengthError('Streaming decode error - repeated field "limitedNumber" had too many elements') } if (obj.limitedNumber === 1) { - throw new MaxLengthError('Decode error - repeated field "limitedNumber" had too many elements') + throw new MaxLengthError('Streaming decode error - repeated field "limitedNumber" had too many elements') } - const value = reader.uint32() - obj.limitedNumber++ - yield { field: `${prefix != null ? `${prefix}.` : ''}limitedNumber`, index: obj.limitedNumber, - value + value: reader.uint32() } + obj.limitedNumber++ + break } case 3: { if (opts.limits?.messages != null && obj.messages === opts.limits.messages) { - throw new MaxLengthError('Decode error - repeated field "messages" had too many elements') + throw new MaxLengthError('Streaming decode error - repeated field "messages" had too many elements') } - const value = SubMessage.codec().decode(reader, reader.uint32(), { + for (const evt of SubMessage.codec().stream(reader, reader.uint32(), `${prefix != null ? `${prefix}.` : ''}messages`, { limits: opts.limits?.messages$ - }) - obj.messages++ - - yield { - field: `${prefix != null ? `${prefix}.` : ''}messages`, - index: obj.messages, - value + })) { + yield { + ...evt, + index: obj.messages + } } + obj.messages++ + break } case 4: { - yield { - field: `${prefix != null ? `${prefix}.` : ''}message`, - value: SubMessage.codec().decode(reader, reader.uint32(), { - limits: opts.limits?.message - }) - } + yield * SubMessage.codec().stream(reader, reader.uint32(), `${prefix != null ? `${prefix}.` : ''}message`, { + limits: opts.limits?.message + }) + break } case 5: { diff --git a/packages/protons/test/fixtures/singular.ts b/packages/protons/test/fixtures/singular.ts index 40b4deb..84611b2 100644 --- a/packages/protons/test/fixtures/singular.ts +++ b/packages/protons/test/fixtures/singular.ts @@ -475,12 +475,10 @@ export namespace Singular { break } case 17: { - yield { - field: `${prefix != null ? `${prefix}.` : ''}subMessage`, - value: SingularSubMessage.codec().decode(reader, reader.uint32(), { - limits: opts.limits?.subMessage - }) - } + yield * SingularSubMessage.codec().stream(reader, reader.uint32(), `${prefix != null ? `${prefix}.` : ''}subMessage`, { + limits: opts.limits?.subMessage + }) + break } default: { diff --git a/packages/protons/test/fixtures/streaming.proto b/packages/protons/test/fixtures/streaming.proto new file mode 100644 index 0000000..f187c37 --- /dev/null +++ b/packages/protons/test/fixtures/streaming.proto @@ -0,0 +1,36 @@ +syntax = "proto3"; + +message MessageWithArrayField { + optional bool field1 = 1; + optional uint32 field2 = 2; + repeated string arr = 3; +} + +message NestedMessage { + string nestedValue = 1; + } + +message MessageWithNestedMessage { + bool field1 = 1; + NestedMessage nestedMessage = 2; +} + +message MessageWithDeeplyNestedMessage { + bool field1 = 1; + MessageWithNestedMessage nestedMessage = 2; +} + +message MessageWithRepeatedMessage { + bool field1 = 1; + repeated NestedMessage nestedMessages = 2; +} + +message MessageWithMapMessage { + bool field1 = 1; + map nestedMessages = 2; +} + +message MessageWithPrimitiveMap { + bool field1 = 1; + map nestedStrings = 2; +} diff --git a/packages/protons/test/fixtures/streaming.ts b/packages/protons/test/fixtures/streaming.ts new file mode 100644 index 0000000..45d746e --- /dev/null +++ b/packages/protons/test/fixtures/streaming.ts @@ -0,0 +1,1096 @@ +import { decodeMessage, encodeMessage, MaxLengthError, MaxSizeError, message, streamMessage } from 'protons-runtime' +import type { Codec, DecodeOptions } from 'protons-runtime' +import type { Uint8ArrayList } from 'uint8arraylist' + +export interface MessageWithArrayField { + field1?: boolean + field2?: number + arr: string[] +} + +export namespace MessageWithArrayField { + let _codec: Codec + + export const codec = (): Codec => { + if (_codec == null) { + _codec = message((obj, w, opts = {}) => { + if (opts.lengthDelimited !== false) { + w.fork() + } + + if (obj.field1 != null) { + w.uint32(8) + w.bool(obj.field1) + } + + if (obj.field2 != null) { + w.uint32(16) + w.uint32(obj.field2) + } + + if (obj.arr != null) { + for (const value of obj.arr) { + w.uint32(26) + w.string(value) + } + } + + if (opts.lengthDelimited !== false) { + w.ldelim() + } + }, (reader, length, opts = {}) => { + const obj: any = { + arr: [] + } + + const end = length == null ? reader.len : reader.pos + length + + while (reader.pos < end) { + const tag = reader.uint32() + + switch (tag >>> 3) { + case 1: { + obj.field1 = reader.bool() + break + } + case 2: { + obj.field2 = reader.uint32() + break + } + case 3: { + if (opts.limits?.arr != null && obj.arr.length === opts.limits.arr) { + throw new MaxLengthError('Decode error - repeated field "arr" had too many elements') + } + + obj.arr.push(reader.string()) + break + } + default: { + reader.skipType(tag & 7) + break + } + } + } + + return obj + }, function * (reader, length, prefix, opts = {}) { + const obj = { + arr: 0 + } + + const end = length == null ? reader.len : reader.pos + length + + while (reader.pos < end) { + const tag = reader.uint32() + + switch (tag >>> 3) { + case 1: { + yield { + field: `${prefix != null ? `${prefix}.` : ''}field1`, + value: reader.bool() + } + break + } + case 2: { + yield { + field: `${prefix != null ? `${prefix}.` : ''}field2`, + value: reader.uint32() + } + break + } + case 3: { + if (opts.limits?.arr != null && obj.arr === opts.limits.arr) { + throw new MaxLengthError('Streaming decode error - repeated field "arr" had too many elements') + } + + yield { + field: `${prefix != null ? `${prefix}.` : ''}arr`, + index: obj.arr, + value: reader.string() + } + + obj.arr++ + + break + } + default: { + reader.skipType(tag & 7) + break + } + } + } + }) + } + + return _codec + } + + export interface MessageWithArrayFieldField1FieldEvent { + field: 'field1' + value: boolean + } + + export interface MessageWithArrayFieldField2FieldEvent { + field: 'field2' + value: number + } + + export interface MessageWithArrayFieldArrFieldEvent { + field: 'arr$entry' + index: number + value: string + } + + export function encode (obj: Partial): Uint8Array { + return encodeMessage(obj, MessageWithArrayField.codec()) + } + + export function decode (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): MessageWithArrayField { + return decodeMessage(buf, MessageWithArrayField.codec(), opts) + } + + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Generator { + return streamMessage(buf, MessageWithArrayField.codec(), opts) + } +} + +export interface NestedMessage { + nestedValue: string +} + +export namespace NestedMessage { + let _codec: Codec + + export const codec = (): Codec => { + if (_codec == null) { + _codec = message((obj, w, opts = {}) => { + if (opts.lengthDelimited !== false) { + w.fork() + } + + if ((obj.nestedValue != null && obj.nestedValue !== '')) { + w.uint32(10) + w.string(obj.nestedValue) + } + + if (opts.lengthDelimited !== false) { + w.ldelim() + } + }, (reader, length, opts = {}) => { + const obj: any = { + nestedValue: '' + } + + const end = length == null ? reader.len : reader.pos + length + + while (reader.pos < end) { + const tag = reader.uint32() + + switch (tag >>> 3) { + case 1: { + obj.nestedValue = reader.string() + break + } + default: { + reader.skipType(tag & 7) + break + } + } + } + + return obj + }, function * (reader, length, prefix, opts = {}) { + const end = length == null ? reader.len : reader.pos + length + + while (reader.pos < end) { + const tag = reader.uint32() + + switch (tag >>> 3) { + case 1: { + yield { + field: `${prefix != null ? `${prefix}.` : ''}nestedValue`, + value: reader.string() + } + break + } + default: { + reader.skipType(tag & 7) + break + } + } + } + }) + } + + return _codec + } + + export interface NestedMessageNestedValueFieldEvent { + field: 'nestedValue' + value: string + } + + export function encode (obj: Partial): Uint8Array { + return encodeMessage(obj, NestedMessage.codec()) + } + + export function decode (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): NestedMessage { + return decodeMessage(buf, NestedMessage.codec(), opts) + } + + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Generator { + return streamMessage(buf, NestedMessage.codec(), opts) + } +} + +export interface MessageWithNestedMessage { + field1: boolean + nestedMessage?: NestedMessage +} + +export namespace MessageWithNestedMessage { + let _codec: Codec + + export const codec = (): Codec => { + if (_codec == null) { + _codec = message((obj, w, opts = {}) => { + if (opts.lengthDelimited !== false) { + w.fork() + } + + if ((obj.field1 != null && obj.field1 !== false)) { + w.uint32(8) + w.bool(obj.field1) + } + + if (obj.nestedMessage != null) { + w.uint32(18) + NestedMessage.codec().encode(obj.nestedMessage, w) + } + + if (opts.lengthDelimited !== false) { + w.ldelim() + } + }, (reader, length, opts = {}) => { + const obj: any = { + field1: false + } + + const end = length == null ? reader.len : reader.pos + length + + while (reader.pos < end) { + const tag = reader.uint32() + + switch (tag >>> 3) { + case 1: { + obj.field1 = reader.bool() + break + } + case 2: { + obj.nestedMessage = NestedMessage.codec().decode(reader, reader.uint32(), { + limits: opts.limits?.nestedMessage + }) + break + } + default: { + reader.skipType(tag & 7) + break + } + } + } + + return obj + }, function * (reader, length, prefix, opts = {}) { + const end = length == null ? reader.len : reader.pos + length + + while (reader.pos < end) { + const tag = reader.uint32() + + switch (tag >>> 3) { + case 1: { + yield { + field: `${prefix != null ? `${prefix}.` : ''}field1`, + value: reader.bool() + } + break + } + case 2: { + yield * NestedMessage.codec().stream(reader, reader.uint32(), `${prefix != null ? `${prefix}.` : ''}nestedMessage`, { + limits: opts.limits?.nestedMessage + }) + + break + } + default: { + reader.skipType(tag & 7) + break + } + } + } + }) + } + + return _codec + } + + export interface MessageWithNestedMessageField1FieldEvent { + field: 'field1' + value: boolean + } + + export interface MessageWithNestedMessageNestedMessageNestedMessageNestedValueFieldEvent { + field: 'nestedValue' + value: string + } + + export function encode (obj: Partial): Uint8Array { + return encodeMessage(obj, MessageWithNestedMessage.codec()) + } + + export function decode (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): MessageWithNestedMessage { + return decodeMessage(buf, MessageWithNestedMessage.codec(), opts) + } + + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Generator { + return streamMessage(buf, MessageWithNestedMessage.codec(), opts) + } +} + +export interface MessageWithDeeplyNestedMessage { + field1: boolean + nestedMessage?: MessageWithNestedMessage +} + +export namespace MessageWithDeeplyNestedMessage { + let _codec: Codec + + export const codec = (): Codec => { + if (_codec == null) { + _codec = message((obj, w, opts = {}) => { + if (opts.lengthDelimited !== false) { + w.fork() + } + + if ((obj.field1 != null && obj.field1 !== false)) { + w.uint32(8) + w.bool(obj.field1) + } + + if (obj.nestedMessage != null) { + w.uint32(18) + MessageWithNestedMessage.codec().encode(obj.nestedMessage, w) + } + + if (opts.lengthDelimited !== false) { + w.ldelim() + } + }, (reader, length, opts = {}) => { + const obj: any = { + field1: false + } + + const end = length == null ? reader.len : reader.pos + length + + while (reader.pos < end) { + const tag = reader.uint32() + + switch (tag >>> 3) { + case 1: { + obj.field1 = reader.bool() + break + } + case 2: { + obj.nestedMessage = MessageWithNestedMessage.codec().decode(reader, reader.uint32(), { + limits: opts.limits?.nestedMessage + }) + break + } + default: { + reader.skipType(tag & 7) + break + } + } + } + + return obj + }, function * (reader, length, prefix, opts = {}) { + const end = length == null ? reader.len : reader.pos + length + + while (reader.pos < end) { + const tag = reader.uint32() + + switch (tag >>> 3) { + case 1: { + yield { + field: `${prefix != null ? `${prefix}.` : ''}field1`, + value: reader.bool() + } + break + } + case 2: { + yield * MessageWithNestedMessage.codec().stream(reader, reader.uint32(), `${prefix != null ? `${prefix}.` : ''}nestedMessage`, { + limits: opts.limits?.nestedMessage + }) + + break + } + default: { + reader.skipType(tag & 7) + break + } + } + } + }) + } + + return _codec + } + + export interface MessageWithDeeplyNestedMessageField1FieldEvent { + field: 'field1' + value: boolean + } + + export interface MessageWithDeeplyNestedMessageNestedMessageMessageWithNestedMessageField1FieldEvent { + field: 'field1' + value: boolean + } + + export interface MessageWithDeeplyNestedMessageNestedMessageMessageWithNestedMessageNestedMessageNestedMessageNestedValueFieldEvent { + field: 'nestedValue' + value: string + } + + export function encode (obj: Partial): Uint8Array { + return encodeMessage(obj, MessageWithDeeplyNestedMessage.codec()) + } + + export function decode (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): MessageWithDeeplyNestedMessage { + return decodeMessage(buf, MessageWithDeeplyNestedMessage.codec(), opts) + } + + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Generator { + return streamMessage(buf, MessageWithDeeplyNestedMessage.codec(), opts) + } +} + +export interface MessageWithRepeatedMessage { + field1: boolean + nestedMessages: NestedMessage[] +} + +export namespace MessageWithRepeatedMessage { + let _codec: Codec + + export const codec = (): Codec => { + if (_codec == null) { + _codec = message((obj, w, opts = {}) => { + if (opts.lengthDelimited !== false) { + w.fork() + } + + if ((obj.field1 != null && obj.field1 !== false)) { + w.uint32(8) + w.bool(obj.field1) + } + + if (obj.nestedMessages != null) { + for (const value of obj.nestedMessages) { + w.uint32(18) + NestedMessage.codec().encode(value, w) + } + } + + if (opts.lengthDelimited !== false) { + w.ldelim() + } + }, (reader, length, opts = {}) => { + const obj: any = { + field1: false, + nestedMessages: [] + } + + const end = length == null ? reader.len : reader.pos + length + + while (reader.pos < end) { + const tag = reader.uint32() + + switch (tag >>> 3) { + case 1: { + obj.field1 = reader.bool() + break + } + case 2: { + if (opts.limits?.nestedMessages != null && obj.nestedMessages.length === opts.limits.nestedMessages) { + throw new MaxLengthError('Decode error - repeated field "nestedMessages" had too many elements') + } + + obj.nestedMessages.push(NestedMessage.codec().decode(reader, reader.uint32(), { + limits: opts.limits?.nestedMessages$ + })) + break + } + default: { + reader.skipType(tag & 7) + break + } + } + } + + return obj + }, function * (reader, length, prefix, opts = {}) { + const obj = { + nestedMessages: 0 + } + + const end = length == null ? reader.len : reader.pos + length + + while (reader.pos < end) { + const tag = reader.uint32() + + switch (tag >>> 3) { + case 1: { + yield { + field: `${prefix != null ? `${prefix}.` : ''}field1`, + value: reader.bool() + } + break + } + case 2: { + if (opts.limits?.nestedMessages != null && obj.nestedMessages === opts.limits.nestedMessages) { + throw new MaxLengthError('Streaming decode error - repeated field "nestedMessages" had too many elements') + } + + for (const evt of NestedMessage.codec().stream(reader, reader.uint32(), `${prefix != null ? `${prefix}.` : ''}nestedMessages`, { + limits: opts.limits?.nestedMessages$ + })) { + yield { + ...evt, + index: obj.nestedMessages + } + } + + obj.nestedMessages++ + + break + } + default: { + reader.skipType(tag & 7) + break + } + } + } + }) + } + + return _codec + } + + export interface MessageWithRepeatedMessageField1FieldEvent { + field: 'field1' + value: boolean + } + + export function encode (obj: Partial): Uint8Array { + return encodeMessage(obj, MessageWithRepeatedMessage.codec()) + } + + export function decode (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): MessageWithRepeatedMessage { + return decodeMessage(buf, MessageWithRepeatedMessage.codec(), opts) + } + + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Generator { + return streamMessage(buf, MessageWithRepeatedMessage.codec(), opts) + } +} + +export interface MessageWithMapMessage { + field1: boolean + nestedMessages: Map +} + +export namespace MessageWithMapMessage { + export interface MessageWithMapMessage$nestedMessagesEntry { + key: string + value?: NestedMessage + } + + export namespace MessageWithMapMessage$nestedMessagesEntry { + let _codec: Codec + + export const codec = (): Codec => { + if (_codec == null) { + _codec = message((obj, w, opts = {}) => { + if (opts.lengthDelimited !== false) { + w.fork() + } + + if ((obj.key != null && obj.key !== '')) { + w.uint32(10) + w.string(obj.key) + } + + if (obj.value != null) { + w.uint32(18) + NestedMessage.codec().encode(obj.value, w) + } + + if (opts.lengthDelimited !== false) { + w.ldelim() + } + }, (reader, length, opts = {}) => { + const obj: any = { + key: '' + } + + const end = length == null ? reader.len : reader.pos + length + + while (reader.pos < end) { + const tag = reader.uint32() + + switch (tag >>> 3) { + case 1: { + obj.key = reader.string() + break + } + case 2: { + obj.value = NestedMessage.codec().decode(reader, reader.uint32(), { + limits: opts.limits?.value + }) + break + } + default: { + reader.skipType(tag & 7) + break + } + } + } + + return obj + }, function * (reader, length, prefix, opts = {}) { + const end = length == null ? reader.len : reader.pos + length + + while (reader.pos < end) { + const tag = reader.uint32() + + switch (tag >>> 3) { + case 1: { + yield { + field: `${prefix != null ? `${prefix}.` : ''}key`, + value: reader.string() + } + break + } + case 2: { + yield * NestedMessage.codec().stream(reader, reader.uint32(), `${prefix != null ? `${prefix}.` : ''}value`, { + limits: opts.limits?.value + }) + + break + } + default: { + reader.skipType(tag & 7) + break + } + } + } + }) + } + + return _codec + } + + export interface MessageWithMapMessage$nestedMessagesEntryKeyFieldEvent { + field: 'key' + value: string + } + + export interface MessageWithMapMessage$nestedMessagesEntryValueNestedMessageNestedValueFieldEvent { + field: 'nestedValue' + value: string + } + + export function encode (obj: Partial): Uint8Array { + return encodeMessage(obj, MessageWithMapMessage$nestedMessagesEntry.codec()) + } + + export function decode (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): MessageWithMapMessage$nestedMessagesEntry { + return decodeMessage(buf, MessageWithMapMessage$nestedMessagesEntry.codec(), opts) + } + + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Generator { + return streamMessage(buf, MessageWithMapMessage$nestedMessagesEntry.codec(), opts) + } + } + + let _codec: Codec + + export const codec = (): Codec => { + if (_codec == null) { + _codec = message((obj, w, opts = {}) => { + if (opts.lengthDelimited !== false) { + w.fork() + } + + if ((obj.field1 != null && obj.field1 !== false)) { + w.uint32(8) + w.bool(obj.field1) + } + + if (obj.nestedMessages != null) { + for (const [key, value] of obj.nestedMessages.entries()) { + w.uint32(18) + MessageWithMapMessage.MessageWithMapMessage$nestedMessagesEntry.codec().encode({ key, value }, w) + } + } + + if (opts.lengthDelimited !== false) { + w.ldelim() + } + }, (reader, length, opts = {}) => { + const obj: any = { + field1: false, + nestedMessages: new Map() + } + + const end = length == null ? reader.len : reader.pos + length + + while (reader.pos < end) { + const tag = reader.uint32() + + switch (tag >>> 3) { + case 1: { + obj.field1 = reader.bool() + break + } + case 2: { + if (opts.limits?.nestedMessages != null && obj.nestedMessages.size === opts.limits.nestedMessages) { + throw new MaxSizeError('Decode error - map field "nestedMessages" had too many elements') + } + + const entry = MessageWithMapMessage.MessageWithMapMessage$nestedMessagesEntry.codec().decode(reader, reader.uint32(), { + limits: { + value: opts.limits?.nestedMessages$value + } + }) + obj.nestedMessages.set(entry.key, entry.value) + break + } + default: { + reader.skipType(tag & 7) + break + } + } + } + + return obj + }, function * (reader, length, prefix, opts = {}) { + const obj = { + nestedMessages: 0 + } + + const end = length == null ? reader.len : reader.pos + length + + while (reader.pos < end) { + const tag = reader.uint32() + + switch (tag >>> 3) { + case 1: { + yield { + field: `${prefix != null ? `${prefix}.` : ''}field1`, + value: reader.bool() + } + break + } + case 2: { + if (opts.limits?.nestedMessages != null && obj.nestedMessages === opts.limits.nestedMessages) { + throw new MaxLengthError('Decode error - map field "nestedMessages" had too many elements') + } + + yield * MessageWithMapMessage.MessageWithMapMessage$nestedMessagesEntry.codec().stream(reader, reader.uint32(), `${prefix != null ? `${prefix}.` : ''}nestedMessages`, { + limits: { + value: opts.limits?.nestedMessages$value + } + }) + + obj.nestedMessages++ + + break + } + default: { + reader.skipType(tag & 7) + break + } + } + } + }) + } + + return _codec + } + + export interface MessageWithMapMessageField1FieldEvent { + field: 'field1' + value: boolean + } + + export function encode (obj: Partial): Uint8Array { + return encodeMessage(obj, MessageWithMapMessage.codec()) + } + + export function decode (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): MessageWithMapMessage { + return decodeMessage(buf, MessageWithMapMessage.codec(), opts) + } + + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Generator { + return streamMessage(buf, MessageWithMapMessage.codec(), opts) + } +} + +export interface MessageWithPrimitiveMap { + field1: boolean + nestedStrings: Map +} + +export namespace MessageWithPrimitiveMap { + export interface MessageWithPrimitiveMap$nestedStringsEntry { + key: string + value: string + } + + export namespace MessageWithPrimitiveMap$nestedStringsEntry { + let _codec: Codec + + export const codec = (): Codec => { + if (_codec == null) { + _codec = message((obj, w, opts = {}) => { + if (opts.lengthDelimited !== false) { + w.fork() + } + + if ((obj.key != null && obj.key !== '')) { + w.uint32(10) + w.string(obj.key) + } + + if ((obj.value != null && obj.value !== '')) { + w.uint32(18) + w.string(obj.value) + } + + if (opts.lengthDelimited !== false) { + w.ldelim() + } + }, (reader, length, opts = {}) => { + const obj: any = { + key: '', + value: '' + } + + const end = length == null ? reader.len : reader.pos + length + + while (reader.pos < end) { + const tag = reader.uint32() + + switch (tag >>> 3) { + case 1: { + obj.key = reader.string() + break + } + case 2: { + obj.value = reader.string() + break + } + default: { + reader.skipType(tag & 7) + break + } + } + } + + return obj + }, function * (reader, length, prefix, opts = {}) { + const end = length == null ? reader.len : reader.pos + length + + while (reader.pos < end) { + const tag = reader.uint32() + + switch (tag >>> 3) { + case 1: { + yield { + field: `${prefix != null ? `${prefix}.` : ''}key`, + value: reader.string() + } + break + } + case 2: { + yield { + field: `${prefix != null ? `${prefix}.` : ''}value`, + value: reader.string() + } + break + } + default: { + reader.skipType(tag & 7) + break + } + } + } + }) + } + + return _codec + } + + export interface MessageWithPrimitiveMap$nestedStringsEntryKeyFieldEvent { + field: 'key' + value: string + } + + export interface MessageWithPrimitiveMap$nestedStringsEntryValueFieldEvent { + field: 'value' + value: string + } + + export function encode (obj: Partial): Uint8Array { + return encodeMessage(obj, MessageWithPrimitiveMap$nestedStringsEntry.codec()) + } + + export function decode (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): MessageWithPrimitiveMap$nestedStringsEntry { + return decodeMessage(buf, MessageWithPrimitiveMap$nestedStringsEntry.codec(), opts) + } + + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Generator { + return streamMessage(buf, MessageWithPrimitiveMap$nestedStringsEntry.codec(), opts) + } + } + + let _codec: Codec + + export const codec = (): Codec => { + if (_codec == null) { + _codec = message((obj, w, opts = {}) => { + if (opts.lengthDelimited !== false) { + w.fork() + } + + if ((obj.field1 != null && obj.field1 !== false)) { + w.uint32(8) + w.bool(obj.field1) + } + + if (obj.nestedStrings != null) { + for (const [key, value] of obj.nestedStrings.entries()) { + w.uint32(18) + MessageWithPrimitiveMap.MessageWithPrimitiveMap$nestedStringsEntry.codec().encode({ key, value }, w) + } + } + + if (opts.lengthDelimited !== false) { + w.ldelim() + } + }, (reader, length, opts = {}) => { + const obj: any = { + field1: false, + nestedStrings: new Map() + } + + const end = length == null ? reader.len : reader.pos + length + + while (reader.pos < end) { + const tag = reader.uint32() + + switch (tag >>> 3) { + case 1: { + obj.field1 = reader.bool() + break + } + case 2: { + if (opts.limits?.nestedStrings != null && obj.nestedStrings.size === opts.limits.nestedStrings) { + throw new MaxSizeError('Decode error - map field "nestedStrings" had too many elements') + } + + const entry = MessageWithPrimitiveMap.MessageWithPrimitiveMap$nestedStringsEntry.codec().decode(reader, reader.uint32(), { + limits: { + value: opts.limits?.nestedStrings$value + } + }) + obj.nestedStrings.set(entry.key, entry.value) + break + } + default: { + reader.skipType(tag & 7) + break + } + } + } + + return obj + }, function * (reader, length, prefix, opts = {}) { + const obj = { + nestedStrings: 0 + } + + const end = length == null ? reader.len : reader.pos + length + + while (reader.pos < end) { + const tag = reader.uint32() + + switch (tag >>> 3) { + case 1: { + yield { + field: `${prefix != null ? `${prefix}.` : ''}field1`, + value: reader.bool() + } + break + } + case 2: { + if (opts.limits?.nestedStrings != null && obj.nestedStrings === opts.limits.nestedStrings) { + throw new MaxLengthError('Decode error - map field "nestedStrings" had too many elements') + } + + yield * MessageWithPrimitiveMap.MessageWithPrimitiveMap$nestedStringsEntry.codec().stream(reader, reader.uint32(), `${prefix != null ? `${prefix}.` : ''}nestedStrings`, { + limits: { + value: opts.limits?.nestedStrings$value + } + }) + + obj.nestedStrings++ + + break + } + default: { + reader.skipType(tag & 7) + break + } + } + } + }) + } + + return _codec + } + + export interface MessageWithPrimitiveMapField1FieldEvent { + field: 'field1' + value: boolean + } + + export interface MessageWithPrimitiveMapNestedStringsFieldEvent { + field: 'nestedStrings$entry' + key: string + value: string + } + + export function encode (obj: Partial): Uint8Array { + return encodeMessage(obj, MessageWithPrimitiveMap.codec()) + } + + export function decode (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): MessageWithPrimitiveMap { + return decodeMessage(buf, MessageWithPrimitiveMap.codec(), opts) + } + + export function stream (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions): Generator { + return streamMessage(buf, MessageWithPrimitiveMap.codec(), opts) + } +} diff --git a/packages/protons/test/fixtures/test.ts b/packages/protons/test/fixtures/test.ts index cd6dfb9..3276a37 100644 --- a/packages/protons/test/fixtures/test.ts +++ b/packages/protons/test/fixtures/test.ts @@ -426,28 +426,25 @@ export namespace AllTheTypes { break } case 13: { - yield { - field: `${prefix != null ? `${prefix}.` : ''}field13`, - value: SubMessage.codec().decode(reader, reader.uint32(), { - limits: opts.limits?.field13 - }) - } + yield * SubMessage.codec().stream(reader, reader.uint32(), `${prefix != null ? `${prefix}.` : ''}field13`, { + limits: opts.limits?.field13 + }) + break } case 14: { if (opts.limits?.field14 != null && obj.field14 === opts.limits.field14) { - throw new MaxLengthError('Decode error - repeated field "field14" had too many elements') + throw new MaxLengthError('Streaming decode error - repeated field "field14" had too many elements') } - const value = reader.string() - obj.field14++ - yield { field: `${prefix != null ? `${prefix}.` : ''}field14`, index: obj.field14, - value + value: reader.string() } + obj.field14++ + break } case 15: { diff --git a/packages/protons/test/streaming-decode.spec.ts b/packages/protons/test/streaming-decode.spec.ts index 74924a0..fa4519d 100644 --- a/packages/protons/test/streaming-decode.spec.ts +++ b/packages/protons/test/streaming-decode.spec.ts @@ -1,37 +1,37 @@ import { expect } from 'aegir/chai' import all from 'it-all' -import { AllTheTypes } from './fixtures/test.ts' +import { MessageWithArrayField, MessageWithNestedMessage, MessageWithRepeatedMessage, MessageWithMapMessage, MessageWithPrimitiveMap, MessageWithDeeplyNestedMessage } from './fixtures/streaming.ts' -describe.skip('streaming-decode', () => { +describe('streaming-decode', () => { it('should include indexes in field values', async () => { - const input = AllTheTypes.encode({ - field14: [ + const input = MessageWithArrayField.encode({ + arr: [ '1', '2', '3' ] }) - const output = all(AllTheTypes.stream(input)) + const output = all(MessageWithArrayField.stream(input)) expect(output).to.deep.equal([{ - field: 'field14$value', + field: 'arr', index: 0, value: '1' }, { - field: 'field14$value', + field: 'arr', index: 1, value: '2' }, { - field: 'field14$value', + field: 'arr', index: 2, value: '3' }]) }) it('should not parse input after exiting loop', () => { - const input = AllTheTypes.encode({ + const input = MessageWithArrayField.encode({ field1: true, field2: 5, - field14: [ + arr: [ '1', '2', '3' ] }) @@ -46,11 +46,11 @@ describe.skip('streaming-decode', () => { // cannot read input to completion expect(() => { - all(AllTheTypes.stream(input)) + all(MessageWithArrayField.stream(input)) }).to.throw().with.property('name', 'RangeError') // can read first couple of values - for (const evt of AllTheTypes.stream(input)) { + for (const evt of MessageWithArrayField.stream(input)) { output.push(evt) if (evt.field === 'field2') { @@ -60,4 +60,124 @@ describe.skip('streaming-decode', () => { expect(output).to.have.lengthOf(2) }) + + it('should stream nested message fields', () => { + const input = MessageWithNestedMessage.encode({ + field1: true, + nestedMessage: { + nestedValue: 'hello' + } + }) + + const output = all(MessageWithNestedMessage.stream(input)) + + expect(output).to.deep.equal([{ + field: 'field1', + value: true + }, { + field: 'nestedMessage.nestedValue', + value: 'hello' + }]) + }) + + it('should stream deeply nested message fields', () => { + const input = MessageWithDeeplyNestedMessage.encode({ + field1: true, + nestedMessage: { + field1: true, + nestedMessage: { + nestedValue: 'hello' + } + } + }) + + const output = all(MessageWithDeeplyNestedMessage.stream(input)) + + expect(output).to.deep.equal([{ + field: 'field1', + value: true + }, { + field: 'nestedMessage.field1', + value: true + }, { + field: 'nestedMessage.nestedMessage.nestedValue', + value: 'hello' + }]) + }) + + it('should stream message fields in lists', () => { + const input = MessageWithRepeatedMessage.encode({ + field1: true, + nestedMessages: [{ + nestedValue: 'hello' + }] + }) + + const output = all(MessageWithRepeatedMessage.stream(input)) + + expect(output).to.deep.equal([{ + field: 'field1', + value: true + }, { + field: 'nestedMessages.nestedValue', + index: 0, + value: 'hello' + }]) + }) + + it('should stream message fields in maps', () => { + const input = MessageWithMapMessage.encode({ + field1: true, + nestedMessages: new Map([['this-is-a-key', { + nestedValue: 'hello' + }], ['this-is-another-key', { + nestedValue: 'world' + }]]) + }) + + const output = all(MessageWithMapMessage.stream(input)) + + expect(output).to.deep.equal([{ + field: 'field1', + value: true + }, { + field: 'nestedMessages.key', + value: 'this-is-a-key' + }, { + field: 'nestedMessages.value.nestedValue', + value: 'hello' + }, { + field: 'nestedMessages.key', + value: 'this-is-another-key' + }, { + field: 'nestedMessages.value.nestedValue', + value: 'world' + }]) + }) + + it('should stream primitive fields in maps', () => { + const input = MessageWithPrimitiveMap.encode({ + field1: true, + nestedStrings: new Map([['this-is-a-key', 'this-is-a-value'], ['this-is-another-key', 'this-is-another-value']]) + }) + + const output = all(MessageWithPrimitiveMap.stream(input)) + + expect(output).to.deep.equal([{ + field: 'field1', + value: true + }, { + field: 'nestedStrings.key', + value: 'this-is-a-key' + }, { + field: 'nestedStrings.value', + value: 'this-is-a-value' + }, { + field: 'nestedStrings.key', + value: 'this-is-another-key' + }, { + field: 'nestedStrings.value', + value: 'this-is-another-value' + }]) + }) })