import ISerializer, { InputOf, OutputOf, JSONOutputOf } from "./ISerializer"; type SerializersMap = { [key: string]: ISerializer }; type TInput = { [key in keyof T]: InputOf }; type TOutput = { [key in keyof T]: OutputOf }; type TJSONOutput = { [key in keyof T]: JSONOutputOf }; export class StructSerializer extends ISerializer, TOutput, TJSONOutput> { public readonly serializers: Readonly; public get keys(): (keyof T)[] { return Object.keys(this.serializers); } constructor(serializers: T) { super(); this.serializers = (Object.keys(serializers) as (keyof T)[]).reduce((acc, key) => { acc[key] = serializers[key]; return acc; }, {} as Partial) as Readonly; } toJSON(value: TInput): TJSONOutput { return this.keys.reduce((acc, key) => { acc[key] = this.serializers[key].toJSON(value[key]); return acc; }, {} as Partial>) as TJSONOutput } fromJSON(value: TJSONOutput): TOutput { return this.keys.reduce((acc, key) => { acc[key] = this.serializers[key].fromJSON(value[key]); return acc; }, {} as Partial>) as TOutput; } toBuffer(value: TInput): Buffer { return Buffer.concat(this.keys.map((key) => this.serializers[key].toBuffer(value[key]))); } readFromBuffer(buffer: Buffer, offset: number = 0): { res: TOutput, newOffset: number } { const result: Partial> = {}; for (const key of this.keys) { const { res: value, newOffset: nextOffset } = this.serializers[key].readFromBuffer(buffer, offset); result[key] = value; offset = nextOffset; } return { res: result as TOutput, newOffset: offset }; } } export default function struct(serializers: T) { return new StructSerializer(serializers); }