({
decoderExtensions = [],
}: DecoderOptions<ExtensionType> = {})
| 16 | }; |
| 17 | |
| 18 | export function makeMessagePackDecoder<ExtensionType extends object = object>({ |
| 19 | decoderExtensions = [], |
| 20 | }: DecoderOptions<ExtensionType> = {}): { |
| 21 | decode: DecodeFn<ExtensionType>, |
| 22 | } { |
| 23 | let textDecoder = new TextDecoder(); |
| 24 | |
| 25 | const decodeArrayItems = (input: Uint8Array, len: number) => { |
| 26 | let acc = 0; |
| 27 | let array: Array<Input<ExtensionType>> = Array(len); |
| 28 | for (let i = 0; i < len; i++) { |
| 29 | let [item, readBytes] = decode(input.slice(acc), acc); |
| 30 | array[i] = item; |
| 31 | acc += readBytes; |
| 32 | } |
| 33 | return [array, acc] as const; |
| 34 | }; |
| 35 | |
| 36 | const decodeObjectEntries = (input: Uint8Array, size: number, pos = 0) => { |
| 37 | let acc = 0; |
| 38 | let entries: Array<[key: string, value: Input<ExtensionType>]> = Array(size); |
| 39 | for (let i = 0; i < size; i++) { |
| 40 | let [key, keySize] = decode(input.slice(acc), pos + acc); |
| 41 | if (typeof key !== 'string') { |
| 42 | throw new Error(`expected string at ${pos}, but got ${typeof key}`); |
| 43 | } |
| 44 | acc += keySize; |
| 45 | |
| 46 | let [value, valueSize] = decode(input.slice(acc), pos + acc); |
| 47 | acc += valueSize; |
| 48 | |
| 49 | entries[i] = [key, value]; |
| 50 | } |
| 51 | |
| 52 | return [Object.fromEntries(entries), acc] as const; |
| 53 | }; |
| 54 | |
| 55 | const decode: DecodeProcessFn<ExtensionType> = (input: Uint8Array, pos = 0) => { |
| 56 | let acc = 0; |
| 57 | let header = input[acc++]; |
| 58 | |
| 59 | if (header < 0x80) { |
| 60 | return [header, acc]; |
| 61 | } else if (header < 0x90) { |
| 62 | let len = header & 15; |
| 63 | let [data, readBytes] = decodeObjectEntries(input.slice(acc), len, pos + acc); |
| 64 | return [data, acc + readBytes]; |
| 65 | } else if (header < 0xa0) { |
| 66 | let len = header & 15; |
| 67 | let [data, readBytes] = decodeArrayItems(input.slice(acc), len); |
| 68 | return [data, acc + readBytes]; |
| 69 | } else if (header < 0xc0) { |
| 70 | let len = 0x1f & header; |
| 71 | let str = textDecoder.decode(input.slice(acc, acc + len)); |
| 72 | return [str, acc + len]; |
| 73 | } else if (header === 0xc0) { |
| 74 | return [null, acc]; |
| 75 | } else if (header === 0xc1) { |
no test coverage detected