UNPKG

lnp

Version:

A compact and deterministic length-prefixed serialization format with a minimal, unambiguous grammar.

1 lines 7.6 kB
{"version":3,"sources":["../packages/index.ts"],"sourcesContent":["\r\nconst td = new TextEncoder();\r\n\r\nexport interface EncodeOptions {\r\n compressed?: boolean;\r\n blnp?: boolean;\r\n signature?: {\r\n key: string;\r\n algorithm?: string;\r\n }\r\n}\r\n\r\nexport class LNPEncoder {\r\n encode(value: any): Buffer {\r\n let output = this.encodeLNP(value);\r\n\r\n return output;\r\n }\r\n\r\n private pack(type: string, payload: Uint8Array): Buffer {\r\n return Buffer.concat([\r\n Buffer.from(type),\r\n Buffer.from(String(payload.length)),\r\n Buffer.from(\":\"),\r\n Buffer.from(payload)\r\n ]);\r\n }\r\n\r\n\r\n private encodeLNP(value: any): Buffer {\r\n if (value === null) { // Null -> N0:\r\n return this.pack(\"N\", Buffer.alloc(0));\r\n }\r\n\r\n switch(typeof value) {\r\n case \"string\":\r\n return this.pack(\"s\", td.encode(value));\r\n \r\n case \"number\":\r\n return this.pack(\"n\", Buffer.from(String(value)));\r\n \r\n case \"boolean\":\r\n return this.pack(\"b\", Buffer.from(value ? \"t\" : \"f\"));\r\n \r\n case \"object\":\r\n if (Array.isArray(value)) // Array\r\n return this.pack(\"a\", this.encodeLNPArray(value));\r\n return this.pack(\"o\", this.encodeLNPObject(value));\r\n\r\n default:\r\n throw new Error(\"Unsupported type in LNP\");\r\n }\r\n }\r\n\r\n private encodeLNPArray(arr: any[]) {\r\n return Buffer.concat(arr.map((v) => this.encodeLNP(v)));\r\n }\r\n\r\n private encodeLNPObject(obj: Record<string, any>) {\r\n const chunks: Buffer[] = [];\r\n\r\n for (const [k, v] of Object.entries(obj)) {\r\n const kb = td.encode(k);\r\n\r\n chunks.push(Buffer.from(String(kb.length) + \":\"));\r\n chunks.push(Buffer.from(kb));\r\n chunks.push(this.encodeLNP(v));\r\n }\r\n\r\n return Buffer.concat(chunks);\r\n }\r\n}\r\n\r\n\r\nexport class LNPParser {\r\n parse(value: Buffer): object {\r\n let [output, _]: any = this.parseValue(value);\r\n\r\n return output;\r\n }\r\n\r\n\r\n private parseValue(buf: Buffer, offset: number = 0) {\r\n const type = String.fromCharCode(buf[offset] as number);\r\n offset++;\r\n\r\n let lenStr = \"\";\r\n while (buf[offset] !== 58) { // :\r\n lenStr += String.fromCharCode(buf[offset] as number);\r\n offset++;\r\n }\r\n offset++; // Skip :\r\n\r\n const length: number = parseInt(lenStr, 10);\r\n const end: number = offset + length;\r\n const payload: Buffer = buf.subarray(offset, end);\r\n\r\n switch (type) {\r\n case \"s\":\r\n return [new TextDecoder().decode(payload), end];\r\n case \"n\":\r\n return [Number(new TextDecoder().decode(payload)), end];\r\n case \"b\":\r\n return [payload[0] === 116, end];\r\n case \"N\":\r\n return [null, end];\r\n case \"B\":\r\n return [Buffer.from(payload.toString(), \"base64\"), end];\r\n case \"a\":\r\n return [this.parseArray(payload), end];\r\n case \"o\":\r\n return [this.parseObject(payload), end];\r\n default:\r\n throw new Error(\"Unknown type: \" + type);\r\n }\r\n }\r\n\r\n private parseArray(payload: Buffer) {\r\n let offset: number = 0;\r\n const arr: any[] = [];\r\n\r\n while (offset < payload.length) {\r\n const [value, next]: any = this.parseValue(payload, offset);\r\n arr.push(value);\r\n offset = next;\r\n }\r\n\r\n return arr;\r\n }\r\n\r\n private parseObject(payload: Buffer) {\r\n let offset: number = 0;\r\n const obj: Record<string, any> = {};\r\n\r\n while (offset < payload.length) {\r\n let klenStr = \"\";\r\n\r\n while (payload[offset] !== 58) { // :\r\n klenStr += String.fromCharCode(payload[offset] as number);\r\n offset++;\r\n }\r\n offset++; // Skip :\r\n\r\n const klen: number = parseInt(klenStr, 10);\r\n const key: string = new TextDecoder().decode(payload.subarray(offset, offset + klen));\r\n offset += klen;\r\n\r\n const [value, next]: any = this.parseValue(payload, offset);\r\n obj[key] = value;\r\n offset = next;\r\n }\r\n\r\n return obj;\r\n }\r\n}\r\n\r\n"],"mappings":"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","names":["td","LNPEncoder","value","type","payload","arr","v","obj","chunks","k","kb","LNPParser","output","_","buf","offset","lenStr","length","end","next","klenStr","klen","key"]}