Created
November 27, 2025 00:00
-
-
Save themichaelyang/ca5969a6a37598b697056a7909eca61a to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| interface CodecFieldType<D> { | |
| encode(decoded: D): string | |
| decode(encoded: string): readonly [D, rest: string] | |
| } | |
| type CodecFieldDef<R extends true | false, D> = { | |
| required: R, | |
| type: CodecFieldType<D> | |
| } | |
| type CodecLiteral<B extends true | false> = { | |
| [key: string]: CodecFieldDef<B, any> | |
| } | |
| type CodecToObject<C> = { | |
| -readonly [K in keyof C]: C[K] extends CodecFieldDef<infer R, infer D> ? | |
| (R extends true ? D : D | null) | |
| : never | |
| } | |
| function encoder_from_literal<T extends CodecLiteral<any>>(defn: T) { | |
| return (params: CodecToObject<T>): string => { | |
| let out = [] | |
| for (let k of Object.keys(params)) { | |
| let field = defn[k] | |
| out.push(field.type.encode(params[k])) | |
| } | |
| return out.join('') | |
| } | |
| } | |
| function decoder_from_literal<T extends CodecLiteral<any>>(defn: T) { | |
| return (encoded: string): CodecToObject<T> => { | |
| let out: any = {} | |
| for (let k of Object.keys(defn)) { | |
| let field = defn[k] | |
| let parsed | |
| [parsed, encoded] = field.type.decode(encoded) | |
| out[k] = parsed | |
| } | |
| return out as CodecToObject<T> | |
| } | |
| } | |
| function codec_from_literal<const T extends CodecLiteral<any>>(defn: T) { | |
| return { | |
| literal: defn, | |
| encode: encoder_from_literal(defn), | |
| decode: decoder_from_literal(defn) | |
| } | |
| } | |
| class Version implements CodecFieldType<number> { | |
| encode(decoded: number) { | |
| return decoded.toString().padStart(2, '0') | |
| } | |
| decode(encoded: string) { | |
| return [parseInt(encoded.slice(0, 2)), encoded.slice(2)] as const | |
| } | |
| } | |
| class Body implements CodecFieldType<string[]> { | |
| encode(decoded: string[]) { | |
| return decoded.join(',') | |
| } | |
| decode(encoded: string) { | |
| return [encoded.split(','), ''] as const | |
| } | |
| } | |
| let example_codec = codec_from_literal({ | |
| version: { | |
| required: false, | |
| type: new Version() | |
| }, | |
| body: { | |
| required: true, | |
| type: new Body() | |
| } | |
| }) | |
| type _type_check = CodecToObject<typeof example_codec['literal']> | |
| let encoded = example_codec.encode({ | |
| version: 12, | |
| body: ['hello', 'world'] | |
| }) | |
| let decoded = example_codec.decode(encoded) | |
| console.log(encoded) | |
| console.log(decoded) |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
one problem:
requiredisn't used by the decoder; needs a way to check for presence