// @ts-nocheck import { MessageType, PartialMessage, RepeatType, ScalarType } from '@protobuf-ts/runtime'; import { PartialFieldInfo } from '@protobuf-ts/runtime/build/types/reflection-info'; type LowerCamelCase = CamelCaseHelper; type CamelCaseHelper< S extends string, CapNext extends boolean, IsFirstChar extends boolean > = S extends `${infer F}${infer R}` ? F extends '_' ? CamelCaseHelper : F extends `${number}` ? `${F}${CamelCaseHelper}` : CapNext extends true ? `${Uppercase}${CamelCaseHelper}` : IsFirstChar extends true ? `${Lowercase}${CamelCaseHelper}` : `${F}${CamelCaseHelper}` : ''; type ScalarTypeToTsType = T extends | ScalarType.DOUBLE | ScalarType.FLOAT | ScalarType.INT32 | ScalarType.FIXED32 | ScalarType.UINT32 | ScalarType.SFIXED32 | ScalarType.SINT32 ? number : T extends ScalarType.INT64 | ScalarType.UINT64 | ScalarType.FIXED64 | ScalarType.SFIXED64 | ScalarType.SINT64 ? bigint : T extends ScalarType.BOOL ? boolean : T extends ScalarType.STRING ? string : T extends ScalarType.BYTES ? Uint8Array : never; interface BaseProtoFieldType { kind: 'scalar' | 'message'; no: number; type: T; optional: O; repeat: R; } export interface ScalarProtoFieldType extends BaseProtoFieldType { kind: 'scalar'; } export interface MessageProtoFieldType< T extends () => ProtoMessageType, O extends boolean, R extends O extends true ? false : boolean > extends BaseProtoFieldType { kind: 'message'; } type ProtoFieldType = | ScalarProtoFieldType | MessageProtoFieldType<() => ProtoMessageType, boolean, boolean>; type ProtoMessageType = { [key: string]: ProtoFieldType; }; export function ProtoField< T extends ScalarType, O extends boolean = false, R extends O extends true ? false : boolean = false > (no: number, type: T, optional?: O, repeat?: R): ScalarProtoFieldType; export function ProtoField< T extends () => ProtoMessageType, O extends boolean = false, R extends O extends true ? false : boolean = false > (no: number, type: T, optional?: O, repeat?: R): MessageProtoFieldType; export function ProtoField ( no: number, type: ScalarType | (() => ProtoMessageType), optional?: boolean, repeat?: boolean ): ProtoFieldType { if (typeof type === 'function') { return { kind: 'message', no, type, optional: optional ?? false, repeat: repeat ?? false }; } else { return { kind: 'scalar', no, type, optional: optional ?? false, repeat: repeat ?? false }; } } type ProtoFieldReturnType = NonNullable extends ScalarProtoFieldType ? ScalarTypeToTsType : T extends NonNullable> ? NonNullable, E>> : never; type RequiredFieldsBaseType = { [K in keyof T as T[K] extends { optional: true } ? never : LowerCamelCase]: T[K] extends { repeat: true; } ? ProtoFieldReturnType[] : ProtoFieldReturnType; }; type OptionalFieldsBaseType = { [K in keyof T as T[K] extends { optional: true } ? LowerCamelCase : never]?: T[K] extends { repeat: true; } ? ProtoFieldReturnType[] : ProtoFieldReturnType; }; type RequiredFieldsType = E extends true ? Partial> : RequiredFieldsBaseType; type OptionalFieldsType = E extends true ? Partial> : OptionalFieldsBaseType; type NapProtoStructType = RequiredFieldsType & OptionalFieldsType; export type NapProtoEncodeStructType = NapProtoStructType; export type NapProtoDecodeStructType = NapProtoStructType; class NapProtoRealMsg { private readonly _field: PartialFieldInfo[]; private readonly _proto_msg: MessageType>; private static cache = new WeakMap>(); private constructor (fields: T) { this._field = Object.keys(fields).map((key) => { const field = fields[key]; if (field.kind === 'scalar') { const repeatType = field.repeat ? [ScalarType.STRING, ScalarType.BYTES].includes(field.type) ? RepeatType.UNPACKED : RepeatType.PACKED : RepeatType.NO; return { no: field.no, name: key, kind: 'scalar', T: field.type, opt: field.optional, repeat: repeatType, }; } else if (field.kind === 'message') { return { no: field.no, name: key, kind: 'message', repeat: field.repeat ? RepeatType.PACKED : RepeatType.NO, T: () => NapProtoRealMsg.getInstance(field.type())._proto_msg, }; } else { throw new Error(`Unknown field kind: ${field.kind}`); } }) as PartialFieldInfo[]; this._proto_msg = new MessageType>('nya', this._field); } static getInstance(fields: T): NapProtoRealMsg { let instance = this.cache.get(fields); if (!instance) { instance = new NapProtoRealMsg(fields); this.cache.set(fields, instance); } return instance; } encode (data: NapProtoEncodeStructType): Uint8Array { return this._proto_msg.toBinary(this._proto_msg.create(data as PartialMessage>)); } decode (data: Uint8Array): NapProtoDecodeStructType { return this._proto_msg.fromBinary(data) as NapProtoDecodeStructType; } } export class NapProtoMsg { private realMsg: NapProtoRealMsg; constructor (fields: T) { this.realMsg = NapProtoRealMsg.getInstance(fields); } encode (data: NapProtoEncodeStructType): Uint8Array { return this.realMsg.encode(data); } decode (data: Uint8Array): NapProtoDecodeStructType { return this.realMsg.decode(data); } } export { ScalarType } from '@protobuf-ts/runtime';