From 57824da8ed029eb1237395c8bf84a9faefc3fb41 Mon Sep 17 00:00:00 2001 From: Zetazzz Date: Mon, 13 Nov 2023 09:57:45 +0800 Subject: [PATCH] add registry helper --- .../misc/output-impl-interfaces/registry.ts | 4 +- packages/telescope/src/helpers/index.ts | 1 + .../telescope/src/helpers/registry-helper.ts | 167 ++++++++++++++++++ 3 files changed, 170 insertions(+), 2 deletions(-) create mode 100644 packages/telescope/src/helpers/registry-helper.ts diff --git a/__fixtures__/misc/output-impl-interfaces/registry.ts b/__fixtures__/misc/output-impl-interfaces/registry.ts index 75e66a1b34..ea3e7b6742 100644 --- a/__fixtures__/misc/output-impl-interfaces/registry.ts +++ b/__fixtures__/misc/output-impl-interfaces/registry.ts @@ -22,8 +22,8 @@ export interface TelescopeGeneratedDecoder< is(o: unknown): o is T; isSDK?(o: unknown): o is SDK; isAmino?(o: unknown): o is Amino; - encode: (message: T, writer?: BinaryWriter) => BinaryWriter; - decode: (input: BinaryReader | Uint8Array, length?: number) => T; + encode: (message: T, writer?: BinaryWriter | any) => BinaryWriter | any; + decode: (input: BinaryReader | Uint8Array | any, length?: number) => T; fromPartial: (object: any) => T; fromJSON?: (object: unknown) => T; toJSON?: (message: T) => unknown; diff --git a/packages/telescope/src/helpers/index.ts b/packages/telescope/src/helpers/index.ts index a37b89c000..a79cbcc738 100644 --- a/packages/telescope/src/helpers/index.ts +++ b/packages/telescope/src/helpers/index.ts @@ -10,3 +10,4 @@ export * from './varint'; export * from './utf8-helper'; export * from './binary-coder'; export * from './types-helper'; +export * from './registry-helper'; diff --git a/packages/telescope/src/helpers/registry-helper.ts b/packages/telescope/src/helpers/registry-helper.ts new file mode 100644 index 0000000000..7beac2efc6 --- /dev/null +++ b/packages/telescope/src/helpers/registry-helper.ts @@ -0,0 +1,167 @@ +export const registryHelper = `import { BinaryReader, BinaryWriter } from "./binary"; +import { Any } from "./google/protobuf/any"; + +export type ProtoMsg = Omit & { typeUrl: any }; + +export interface IAminoMsg { + type: any; + value: Amino; +} + +export interface IProtoType { + $typeUrl?: any; +} + +export interface TelescopeGeneratedDecoder< + T = unknown, + SDK = unknown, + Amino = unknown +> { + readonly typeUrl: string; + readonly aminoType?: string; + is(o: unknown): o is T; + isSDK?(o: unknown): o is SDK; + isAmino?(o: unknown): o is Amino; + encode: (message: T, writer?: BinaryWriter | any) => BinaryWriter | any; + decode: (input: BinaryReader | Uint8Array | any, length?: number) => T; + fromPartial: (object: any) => T; + fromJSON?: (object: unknown) => T; + toJSON?: (message: T) => unknown; + fromSDK?: (sdk: SDK) => T; + fromSDKJSON?: (object: any) => SDK; + toSDK?: (message: T) => SDK; + fromAmino?: (amino: Amino) => T; + toAmino?: (message: T) => Amino; + fromAminoMsg?: (aminoMsg: IAminoMsg) => T; + toAminoMsg?: (message: T) => IAminoMsg; + toProto?: (message: T) => Uint8Array; + fromProtoMsg?: (message: ProtoMsg) => T; + toProtoMsg?: (message: T) => Any; +} + +export class GlobalDecoderRegistry { + static registry: { + [key: string]: TelescopeGeneratedDecoder; + } = {}; + static register( + key: string, + decoder: TelescopeGeneratedDecoder + ) { + GlobalDecoderRegistry.registry[key] = decoder; + } + static getDecoder( + key: string + ): TelescopeGeneratedDecoder { + return GlobalDecoderRegistry.registry[key]; + } + static getDecoderByInstance( + obj: unknown + ): TelescopeGeneratedDecoder | null { + if (obj === undefined || obj === null) { + return null; + } + const protoType = obj as IProtoType; + + if (protoType.$typeUrl) { + return this.getDecoder(protoType.$typeUrl); + } + + for (const key in GlobalDecoderRegistry.registry) { + if ( + Object.prototype.hasOwnProperty.call( + GlobalDecoderRegistry.registry, + key + ) + ) { + const element = GlobalDecoderRegistry.registry[key]; + + if (element.is(obj)) { + return element; + } + + if (element.isSDK && element.isSDK(obj)) { + return element; + } + + if (element.isAmino && element.isAmino(obj)) { + return element; + } + } + } + + return null; + } + static wrapAny(obj: unknown): Any { + const decoder = getDecoderByInstance(obj); + + return { + typeUrl: decoder.typeUrl, + value: decoder.encode(obj).finish(), + }; + } + static unwrapAny(input: BinaryReader | Uint8Array) { + const reader = + input instanceof BinaryReader ? input : new BinaryReader(input); + + const data = Any.decode(reader, reader.uint32()); + + const decoder = GlobalDecoderRegistry.getDecoder( + data.typeUrl + ); + + if (!decoder) { + return data; + } + + return decoder.decode(data.value); + } + static fromJSON(object: any): T { + const decoder = getDecoderByInstance(object); + return decoder.fromJSON!(object); + } + static toJSON(message: T): any { + const decoder = getDecoderByInstance(message); + return decoder.toJSON!(message); + } + static fromPartial(object: unknown): T { + const decoder = getDecoderByInstance(object); + return decoder ? decoder.fromPartial(object) : (object as T); + } + static fromSDK(object: SDK): T { + const decoder = getDecoderByInstance(object); + return decoder.fromSDK!(object); + } + static fromSDKJSON(object: any): SDK { + const decoder = getDecoderByInstance(object); + return decoder.fromSDKJSON!(object); + } + static toSDK(object: T): SDK { + const decoder = getDecoderByInstance(object); + return decoder.toSDK!(object); + } + static fromAmino(object: Amino): T { + const decoder = getDecoderByInstance(object); + return decoder.fromAmino!(object); + } + static toAmino(object: T): Amino { + const decoder = getDecoderByInstance(object); + return decoder.toAmino!(object); + } +} + +function getDecoderByInstance( + obj: unknown +): TelescopeGeneratedDecoder { + const decoder = GlobalDecoderRegistry.getDecoderByInstance( + obj + ); + + if (!decoder) { + throw new Error( + \`There's no decoder for the instance \${JSON.stringify(obj)}\` + ); + } + + return decoder; +} +`; \ No newline at end of file