import { ExtData } from "./ExtData.ts";import { timestampExtension } from "./timestamp.ts";
export type ExtensionDecoderType<ContextType> = ( data: Uint8Array, extensionType: number, context: ContextType,) => unknown;
export type ExtensionEncoderType<ContextType> = ( input: unknown, context: ContextType,) => Uint8Array | null;
export type ExtensionCodecType<ContextType> = { __brand?: ContextType; tryToEncode(object: unknown, context: ContextType): ExtData | null; decode(data: Uint8Array, extType: number, context: ContextType): unknown;};
export class ExtensionCodec<ContextType = undefined> implements ExtensionCodecType<ContextType> { public static readonly defaultCodec: ExtensionCodecType<undefined> = new ExtensionCodec();
__brand?: ContextType;
private readonly builtInEncoders: Array< ExtensionEncoderType<ContextType> | undefined | null > = []; private readonly builtInDecoders: Array< ExtensionDecoderType<ContextType> | undefined | null > = [];
private readonly encoders: Array< ExtensionEncoderType<ContextType> | undefined | null > = []; private readonly decoders: Array< ExtensionDecoderType<ContextType> | undefined | null > = [];
public constructor() { this.register(timestampExtension); }
public register({ type, encode, decode, }: { type: number; encode: ExtensionEncoderType<ContextType>; decode: ExtensionDecoderType<ContextType>; }): void { if (type >= 0) { this.encoders[type] = encode; this.decoders[type] = decode; } else { const index = 1 + type; this.builtInEncoders[index] = encode; this.builtInDecoders[index] = decode; } }
public tryToEncode(object: unknown, context: ContextType): ExtData | null { for (let i = 0; i < this.builtInEncoders.length; i++) { const encoder = this.builtInEncoders[i]; if (encoder != null) { const data = encoder(object, context); if (data != null) { const type = -1 - i; return new ExtData(type, data); } } }
for (let i = 0; i < this.encoders.length; i++) { const encoder = this.encoders[i]; if (encoder != null) { const data = encoder(object, context); if (data != null) { const type = i; return new ExtData(type, data); } } }
if (object instanceof ExtData) { return object; } return null; }
public decode(data: Uint8Array, type: number, context: ContextType): unknown { const decoder = type < 0 ? this.builtInDecoders[-1 - type] : this.decoders[type]; if (decoder) { return decoder(data, type, context); } else { return new ExtData(type, data); } }}