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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 45 additions & 21 deletions packages/protons-benchmark/src/implementations/protons/bench.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,16 @@ export interface Foo {
baz?: number
}

export interface FooInput {
baz?: number
}

export namespace Foo {
let _codec: Codec<Foo>
let _codec: Codec<Foo, FooInput>

export const codec = (): Codec<Foo> => {
export const codec = (): Codec<Foo, FooInput> => {
if (_codec == null) {
_codec = message<Foo>((obj, w, opts = {}) => {
_codec = message<Foo, FooInput>((obj, w, opts = {}) => {
if (opts.lengthDelimited !== false) {
w.fork()
}
Expand Down Expand Up @@ -92,7 +96,7 @@ export namespace Foo {
value: number
}

export function encode (obj: Partial<Foo>): Uint8Array<ArrayBuffer> {
export function encode (obj: FooInput): Uint8Array<ArrayBuffer> {
return encodeMessage(obj, Foo.codec())
}

Expand All @@ -109,12 +113,16 @@ export interface Bar {
tmp?: Foo
}

export interface BarInput {
tmp?: FooInput
}

export namespace Bar {
let _codec: Codec<Bar>
let _codec: Codec<Bar, BarInput>

export const codec = (): Codec<Bar> => {
export const codec = (): Codec<Bar, BarInput> => {
if (_codec == null) {
_codec = message<Bar>((obj, w, opts = {}) => {
_codec = message<Bar, BarInput>((obj, w, opts = {}) => {
if (opts.lengthDelimited !== false) {
w.fork()
}
Expand Down Expand Up @@ -207,7 +215,7 @@ export namespace Bar {
value: number
}

export function encode (obj: Partial<Bar>): Uint8Array<ArrayBuffer> {
export function encode (obj: BarInput): Uint8Array<ArrayBuffer> {
return encodeMessage(obj, Bar.codec())
}

Expand All @@ -233,7 +241,7 @@ enum __FOOValues {
}

export namespace FOO {
export const codec = (): Codec<FOO> => {
export const codec = (): Codec<FOO, FOO> => {
return enumeration<FOO>(__FOOValues)
}
}
Expand All @@ -242,12 +250,16 @@ export interface Yo {
lol: FOO[]
}

export interface YoInput {
lol?: FOO[]
}

export namespace Yo {
let _codec: Codec<Yo>
let _codec: Codec<Yo, YoInput>

export const codec = (): Codec<Yo> => {
export const codec = (): Codec<Yo, YoInput> => {
if (_codec == null) {
_codec = message<Yo>((obj, w, opts = {}) => {
_codec = message<Yo, YoInput>((obj, w, opts = {}) => {
if (opts.lengthDelimited !== false) {
w.fork()
}
Expand Down Expand Up @@ -349,7 +361,7 @@ export namespace Yo {
value: FOO
}

export function encode (obj: Partial<Yo>): Uint8Array<ArrayBuffer> {
export function encode (obj: YoInput): Uint8Array<ArrayBuffer> {
return encodeMessage(obj, Yo.codec())
}

Expand All @@ -367,12 +379,17 @@ export interface Lol {
b?: Bar
}

export interface LolInput {
lol?: string
b?: BarInput
}

export namespace Lol {
let _codec: Codec<Lol>
let _codec: Codec<Lol, LolInput>

export const codec = (): Codec<Lol> => {
export const codec = (): Codec<Lol, LolInput> => {
if (_codec == null) {
_codec = message<Lol>((obj, w, opts = {}) => {
_codec = message<Lol, LolInput>((obj, w, opts = {}) => {
if (opts.lengthDelimited !== false) {
w.fork()
}
Expand Down Expand Up @@ -496,7 +513,7 @@ export namespace Lol {
value: number
}

export function encode (obj: Partial<Lol>): Uint8Array<ArrayBuffer> {
export function encode (obj: LolInput): Uint8Array<ArrayBuffer> {
return encodeMessage(obj, Lol.codec())
}

Expand All @@ -516,12 +533,19 @@ export interface Test {
payload?: Uint8Array<ArrayBuffer>
}

export interface TestInput {
meh?: LolInput
hello?: number
foo?: string
payload?: Uint8Array
}

export namespace Test {
let _codec: Codec<Test>
let _codec: Codec<Test, TestInput>

export const codec = (): Codec<Test> => {
export const codec = (): Codec<Test, TestInput> => {
if (_codec == null) {
_codec = message<Test>((obj, w, opts = {}) => {
_codec = message<Test, TestInput>((obj, w, opts = {}) => {
if (opts.lengthDelimited !== false) {
w.fork()
}
Expand Down Expand Up @@ -702,7 +726,7 @@ export namespace Test {
value: Uint8Array<ArrayBuffer>
}

export function encode (obj: Partial<Test>): Uint8Array<ArrayBuffer> {
export function encode (obj: TestInput): Uint8Array<ArrayBuffer> {
return encodeMessage(obj, Test.codec())
}

Expand Down
12 changes: 6 additions & 6 deletions packages/protons-runtime/src/codec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export interface EncodeOptions {
}

export interface EncodeFunction<T> {
(value: Partial<T>, writer: Writer, opts?: EncodeOptions): void
(value: T, writer: Writer, opts?: EncodeOptions): void
}

// protobuf types that contain multiple values
Expand Down Expand Up @@ -63,15 +63,15 @@ export interface StreamFunction<T> {
(reader: Reader, length: number | undefined, prefix: string, opts?: DecodeOptions<T>): Generator<any>
}

export interface Codec<T> {
export interface Codec<D, E> {
name: string
type: number
encode: EncodeFunction<T>
decode: DecodeFunction<T>
stream: StreamFunction<T>
encode: EncodeFunction<E>
decode: DecodeFunction<D>
stream: StreamFunction<D>
}

export function createCodec <T> (name: string, type: number, encode: EncodeFunction<T>, decode: DecodeFunction<T>, stream: StreamFunction<T>): Codec<T> {
export function createCodec <D, E> (name: string, type: number, encode: EncodeFunction<E>, decode: DecodeFunction<D>, stream: StreamFunction<D>): Codec<D, E> {
return {
name,
type,
Expand Down
4 changes: 2 additions & 2 deletions packages/protons-runtime/src/codecs/enum.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { createCodec, CODEC_TYPES } from '../codec.ts'
import type { DecodeFunction, EncodeFunction, Codec, StreamFunction } from '../codec.ts'

export function enumeration <T> (v: any): Codec<T> {
export function enumeration <T> (v: any): Codec<T, T> {
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
Expand All @@ -28,5 +28,5 @@ export function enumeration <T> (v: any): Codec<T> {
// enums are simple values that are decoded inline so this is a no-op
}

return createCodec<T>('enum', CODEC_TYPES.VARINT, encode, decode, stream)
return createCodec<T, T>('enum', CODEC_TYPES.VARINT, encode, decode, stream)
}
2 changes: 1 addition & 1 deletion packages/protons-runtime/src/codecs/message.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@ export interface Factory<A, T> {
new (obj: A): T
}

export function message <T> (encode: EncodeFunction<T>, decode: DecodeFunction<T>, stream: StreamFunction<T>): Codec<T> {
export function message <D, E> (encode: EncodeFunction<E>, decode: DecodeFunction<D>, stream: StreamFunction<D>): Codec<D, E> {
return createCodec('message', CODEC_TYPES.LENGTH_DELIMITED, encode, decode, stream)
}
2 changes: 1 addition & 1 deletion packages/protons-runtime/src/decode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 <T> (buf: Uint8Array | Uint8ArrayList, codec: Pick<Codec<T>, 'decode'>, opts?: DecodeOptions<T>): T {
export function decodeMessage <D, E> (buf: Uint8Array | Uint8ArrayList, codec: Pick<Codec<D, E>, 'decode'>, opts?: DecodeOptions<D>): D {
const reader = createReader(buf)

return codec.decode(reader, undefined, opts)
Expand Down
2 changes: 1 addition & 1 deletion packages/protons-runtime/src/encode.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { createWriter } from './utils/writer.ts'
import type { Codec } from './codec.ts'

export function encodeMessage <T> (message: Partial<T>, codec: Pick<Codec<T>, 'encode'>): Uint8Array<ArrayBuffer> {
export function encodeMessage <D, E> (message: E, codec: Pick<Codec<D, E>, 'encode'>): Uint8Array<ArrayBuffer> {
const w = createWriter()

codec.encode(message, w, {
Expand Down
2 changes: 1 addition & 1 deletion packages/protons-runtime/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import type { Codec } from './codec.ts'

export interface FieldDef {
name: string
codec: Codec<any>
codec: Codec<any, any>
optional?: true
repeats?: true
packed?: true
Expand Down
2 changes: 1 addition & 1 deletion packages/protons-runtime/src/stream.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { createReader } from './utils/reader.ts'
import type { Codec } from './codec.ts'
import type { Uint8ArrayList } from 'uint8arraylist'

export function * streamMessage <T> (buf: Uint8Array | Uint8ArrayList, codec: Pick<Codec<T>, 'stream'>, opts?: any): Generator<any> {
export function * streamMessage <D, E> (buf: Uint8Array | Uint8ArrayList, codec: Pick<Codec<D, E>, 'stream'>, opts?: any): Generator<any> {
const reader = createReader(buf)

yield * codec.stream(reader, undefined, '.', opts)
Expand Down
8 changes: 6 additions & 2 deletions packages/protons/src/fields/array-field.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,12 @@ export class ArrayField extends Field {
this.lengthLimit = def.options?.['(protons.options).limit']
}

getInterfaceField (parent: Parent, indent = ''): string {
return `${super.getInterfaceField(parent, indent)}[]`
getDecoderInterfaceField (parent: Parent, indent = ''): string {
return `${super.getDecoderInterfaceField(parent, indent)}[]`
}

getEncoderInterfaceField (parent: Parent, indent = ''): string {
return `${indent}${this.name}?: ${this.jsTypeOverride ?? parent.findType(this.type).jsType.encode}[]`
}

getDefaultField (parent: Parent): string {
Expand Down
21 changes: 18 additions & 3 deletions packages/protons/src/fields/field.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,12 @@ export interface MessageField {
/**
* Return a string that can be used in a typescript interface for this field
*/
getInterfaceField (parent: Parent, indent?: string): string
getDecoderInterfaceField (parent: Parent, indent?: string): string

/**
* Return a string that can be used in a typescript interface for this field
*/
getEncoderInterfaceField (parent: Parent, indent?: string): string
}

export class Field implements MessageField {
Expand Down Expand Up @@ -127,8 +132,12 @@ export class Field implements MessageField {
}
}

getInterfaceField (parent: Parent, indent = ''): string {
return `${indent}${this.name}${this.optional ? '?' : ''}: ${this.jsTypeOverride ?? parent.findType(this.type).jsType}`
getDecoderInterfaceField (parent: Parent, indent = ''): string {
return `${indent}${this.name}${this.optional ? '?' : ''}: ${this.jsTypeOverride ?? parent.findType(this.type).jsType.decode}`
}

getEncoderInterfaceField (parent: Parent, indent = ''): string {
return `${indent}${this.name}${this.proto2Required ? '' : '?'}: ${this.jsTypeOverride ?? parent.findType(this.type).jsType.encode}`
}

getDefaultField (parent: Parent): string {
Expand Down Expand Up @@ -188,6 +197,12 @@ export class Field implements MessageField {
id = (this.id << 3) | codecTypes.enum
}

if (this.proto2Required) {
return `
w.uint32(${id})
${type.getEncoder(this, `obj.${this.name}`)}`
}

return `
if (${type.getValueTest(this, `obj.${this.name}`)}) {
w.uint32(${id})
Expand Down
17 changes: 12 additions & 5 deletions packages/protons/src/fields/map-field.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,16 +37,23 @@ export class MapField extends Field {
}
}

getInterfaceField (parent: Parent): string {
const keyType = this.jsKeyTypeOverride ?? parent.findType(this.keyType).jsType
const valueType = this.jsValueTypeOverride ?? parent.findType(this.valueType).jsType
getDecoderInterfaceField (parent: Parent): string {
const keyType = this.jsKeyTypeOverride ?? parent.findType(this.keyType).jsType.decode
const valueType = this.jsValueTypeOverride ?? parent.findType(this.valueType).jsType.decode

return `${this.name}: Map<${keyType}, ${valueType}>`
}

getEncoderInterfaceField (parent: Parent): string {
const keyType = this.jsKeyTypeOverride ?? parent.findType(this.keyType).jsType.encode
const valueType = this.jsValueTypeOverride ?? parent.findType(this.valueType).jsType.encode

return `${this.name}?: Map<${keyType}, ${valueType}>`
}

getDefaultField (parent: Parent): string {
const keyType = this.jsKeyTypeOverride ?? parent.findType(this.keyType).jsType
const valueType = this.jsValueTypeOverride ?? parent.findType(this.valueType).jsType
const keyType = this.jsKeyTypeOverride ?? parent.findType(this.keyType).jsType.decode
const valueType = this.jsValueTypeOverride ?? parent.findType(this.valueType).jsType.decode

return `${this.name}: new Map<${keyType}, ${valueType}>()`
}
Expand Down
8 changes: 6 additions & 2 deletions packages/protons/src/fields/message-field.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,12 @@ import { Field } from './field.ts'
import type { Parent, Type } from '../types/index.ts'

export class MessageField extends Field {
getInterfaceField (parent: Parent, indent = ''): string {
return `${indent}${this.name}?: ${parent.findType(this.type).jsType}`
getDecoderInterfaceField (parent: Parent, indent = ''): string {
return `${indent}${this.name}?: ${parent.findType(this.type).jsType.decode}`
}

getEncoderInterfaceField (parent: Parent, indent = ''): string {
return `${indent}${this.name}?: ${parent.findType(this.type).jsType.encode}`
}

getMessage (parent: Parent): Message {
Expand Down
Loading
Loading