UNPKG

@andrew_l/tl-pack

Version:

![license](https://img.shields.io/npm/l/%40andrew_l%2Ftl-pack) <!-- omit in toc --> ![npm version](https://img.shields.io/npm/v/%40andrew_l%2Ftl-pack) <!-- omit in toc --> ![npm bundle size](https://img.shields.io/bundlephobia/minzip/%40andrew_l%2Ftl-pack

1 lines 77.9 kB
{"version":3,"file":"tl-pack.DfL54MjP.cjs","sources":["../../src/constants.ts","../../src/dictionary.ts","../../src/helpers.ts","../../src/BinaryReader.ts","../../src/BinaryWriter.ts"],"sourcesContent":["export enum CORE_TYPES {\n None = 0,\n Binary = 1,\n BoolFalse = 2,\n BoolTrue = 3,\n Null = 4,\n Date = 5,\n Vector = 6,\n VectorDynamic = 7,\n Int32 = 8,\n Int16 = 9,\n Int8 = 10,\n UInt32 = 11,\n UInt16 = 12,\n UInt8 = 13,\n Float = 14,\n Double = 15,\n Map = 16,\n DictValue = 17,\n DictIndex = 18,\n String = 19,\n Repeat = 20,\n Checksum = 21,\n GZIP = 25,\n}\n\nexport const MAX_BUFFER_SIZE = 0x7fd00000;\n","export function createDictionary(values?: string[]): Dictionary {\n return new Dictionary(values);\n}\n\nexport class Dictionary {\n private _count = 0;\n private _wordToIndex: Map<string, number>;\n private _words: string[];\n private _offset: number;\n\n constructor(values?: string[], offset = 0) {\n this._words = [];\n this._wordToIndex = new Map();\n this._offset = offset;\n\n if (Array.isArray(values) && values.length) {\n values.forEach(word => {\n if (this._wordToIndex!.has(word)) return;\n\n this._wordToIndex.set(word, this._count++);\n this._words.push(word);\n });\n }\n }\n\n get size(): number {\n return this._count;\n }\n\n /**\n * Returns inserted index or nothing\n */\n maybeInsert(word: string): number | null {\n if (this._wordToIndex.has(word)) return null;\n\n this._wordToIndex.set(word, this._count++);\n this._words.push(word);\n\n return this._count + this._offset;\n }\n\n getValue(index: number): string | null {\n return this._words[index - this._offset] ?? null;\n }\n\n getIndex(value: string): number | null {\n const idx = this._wordToIndex.get(value);\n\n if (idx === undefined) {\n return null;\n }\n\n return idx + this._offset;\n }\n\n hasValue(value: string): boolean {\n return this._wordToIndex.has(value);\n }\n\n hasIndex(index: number): boolean {\n return this._words[index - this._offset] !== undefined;\n }\n}\n","import { isPlainObject } from '@andrew_l/toolkit';\nimport { CORE_TYPES } from './constants';\n\nconst encoder = new TextEncoder();\nconst decoder = new TextDecoder();\n\nconst fromCharCode = String.fromCharCode;\n\nexport const int32 = new Int32Array(2);\nexport const float32 = new Float32Array(int32.buffer);\nexport const float64 = new Float64Array(int32.buffer);\n\nexport function byteArrayAllocate(length: number): Uint8Array {\n return new Uint8Array(length);\n}\n\nexport function coreType(value: any): CORE_TYPES {\n switch (typeof value) {\n case 'string': {\n return CORE_TYPES.String;\n }\n\n case 'boolean': {\n return value ? CORE_TYPES.BoolTrue : CORE_TYPES.BoolFalse;\n }\n\n case 'number': {\n if (Math.trunc(value) === value) {\n if (value >= 0 && value <= 0xff) {\n return CORE_TYPES.UInt8;\n } else if (value >= 0 && value <= 0xffff) {\n return CORE_TYPES.UInt16;\n } else if (value >= 0 && value <= 0xffffffff) {\n return CORE_TYPES.UInt32;\n } else if (value >= -0x80 && value <= 0x7f) {\n return CORE_TYPES.Int8;\n } else if (value >= -0x8000 && value <= 0x7fff) {\n return CORE_TYPES.Int16;\n } else if (value >= -0x80000000 && value <= 0x7fffffff) {\n return CORE_TYPES.Int32;\n }\n }\n\n return CORE_TYPES.Double;\n }\n\n case 'object': {\n if (value === null) return CORE_TYPES.Null;\n\n if (value instanceof Date) {\n return CORE_TYPES.Date;\n }\n\n if (Array.isArray(value)) {\n return CORE_TYPES.Vector;\n }\n\n if (isPlainObject(value)) {\n return CORE_TYPES.Map;\n }\n }\n }\n\n return CORE_TYPES.None;\n}\n\nexport function utf8Read(target: Uint8Array, length: number, offset: number) {\n let result;\n if (length < 16) {\n if ((result = utf8ReadShort(target, length, offset))) return result;\n }\n if (length > 64 && decoder)\n return decoder.decode(target.subarray(offset, (offset += length)));\n const end = offset + length;\n const units = [];\n result = '';\n while (offset < end) {\n const byte1 = target[offset++];\n if ((byte1 & 0x80) === 0) {\n // 1 byte\n units.push(byte1);\n } else if ((byte1 & 0xe0) === 0xc0) {\n // 2 bytes\n const byte2 = target[offset++] & 0x3f;\n units.push(((byte1 & 0x1f) << 6) | byte2);\n } else if ((byte1 & 0xf0) === 0xe0) {\n // 3 bytes\n const byte2 = target[offset++] & 0x3f;\n const byte3 = target[offset++] & 0x3f;\n units.push(((byte1 & 0x1f) << 12) | (byte2 << 6) | byte3);\n } else if ((byte1 & 0xf8) === 0xf0) {\n // 4 bytes\n const byte2 = target[offset++] & 0x3f;\n const byte3 = target[offset++] & 0x3f;\n const byte4 = target[offset++] & 0x3f;\n let unit =\n ((byte1 & 0x07) << 0x12) | (byte2 << 0x0c) | (byte3 << 0x06) | byte4;\n if (unit > 0xffff) {\n unit -= 0x10000;\n units.push(((unit >>> 10) & 0x3ff) | 0xd800);\n unit = 0xdc00 | (unit & 0x3ff);\n }\n units.push(unit);\n } else {\n units.push(byte1);\n }\n\n if (units.length >= 0x1000) {\n result += fromCharCode.apply(String, units);\n units.length = 0;\n }\n }\n\n if (units.length > 0) {\n result += fromCharCode.apply(String, units);\n }\n\n return result;\n}\n\nexport function utf8ReadShort(\n target: Uint8Array,\n length: number,\n offset: number,\n) {\n if (length < 4) {\n if (length < 2) {\n if (length === 0) return '';\n else {\n let a = target[offset++];\n if ((a & 0x80) > 1) {\n offset -= 1;\n return;\n }\n return fromCharCode(a);\n }\n } else {\n let a = target[offset++];\n let b = target[offset++];\n if ((a & 0x80) > 0 || (b & 0x80) > 0) {\n offset -= 2;\n return;\n }\n if (length < 3) return fromCharCode(a, b);\n let c = target[offset++];\n if ((c & 0x80) > 0) {\n offset -= 3;\n return;\n }\n return fromCharCode(a, b, c);\n }\n } else {\n let a = target[offset++];\n let b = target[offset++];\n let c = target[offset++];\n let d = target[offset++];\n if ((a & 0x80) > 0 || (b & 0x80) > 0 || (c & 0x80) > 0 || (d & 0x80) > 0) {\n offset -= 4;\n return;\n }\n if (length < 6) {\n if (length === 4) return fromCharCode(a, b, c, d);\n else {\n let e = target[offset++];\n if ((e & 0x80) > 0) {\n offset -= 5;\n return;\n }\n return fromCharCode(a, b, c, d, e);\n }\n } else if (length < 8) {\n let e = target[offset++];\n let f = target[offset++];\n if ((e & 0x80) > 0 || (f & 0x80) > 0) {\n offset -= 6;\n return;\n }\n if (length < 7) return fromCharCode(a, b, c, d, e, f);\n let g = target[offset++];\n if ((g & 0x80) > 0) {\n offset -= 7;\n return;\n }\n return fromCharCode(a, b, c, d, e, f, g);\n } else {\n let e = target[offset++];\n let f = target[offset++];\n let g = target[offset++];\n let h = target[offset++];\n if (\n (e & 0x80) > 0 ||\n (f & 0x80) > 0 ||\n (g & 0x80) > 0 ||\n (h & 0x80) > 0\n ) {\n offset -= 8;\n return;\n }\n if (length < 10) {\n if (length === 8) return fromCharCode(a, b, c, d, e, f, g, h);\n else {\n let i = target[offset++];\n if ((i & 0x80) > 0) {\n offset -= 9;\n return;\n }\n return fromCharCode(a, b, c, d, e, f, g, h, i);\n }\n } else if (length < 12) {\n let i = target[offset++];\n let j = target[offset++];\n if ((i & 0x80) > 0 || (j & 0x80) > 0) {\n offset -= 10;\n return;\n }\n if (length < 11) return fromCharCode(a, b, c, d, e, f, g, h, i, j);\n let k = target[offset++];\n if ((k & 0x80) > 0) {\n offset -= 11;\n return;\n }\n return fromCharCode(a, b, c, d, e, f, g, h, i, j, k);\n } else {\n let i = target[offset++];\n let j = target[offset++];\n let k = target[offset++];\n let l = target[offset++];\n if (\n (i & 0x80) > 0 ||\n (j & 0x80) > 0 ||\n (k & 0x80) > 0 ||\n (l & 0x80) > 0\n ) {\n offset -= 12;\n return;\n }\n if (length < 14) {\n if (length === 12)\n return fromCharCode(a, b, c, d, e, f, g, h, i, j, k, l);\n else {\n let m = target[offset++];\n if ((m & 0x80) > 0) {\n offset -= 13;\n return;\n }\n return fromCharCode(a, b, c, d, e, f, g, h, i, j, k, l, m);\n }\n } else {\n let m = target[offset++];\n let n = target[offset++];\n if ((m & 0x80) > 0 || (n & 0x80) > 0) {\n offset -= 14;\n return;\n }\n if (length < 15)\n return fromCharCode(a, b, c, d, e, f, g, h, i, j, k, l, m, n);\n let o = target[offset++];\n if ((o & 0x80) > 0) {\n offset -= 15;\n return;\n }\n return fromCharCode(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o);\n }\n }\n }\n }\n}\n\nexport const utf8Write = function (target: any, value: string, offset: number) {\n return value.length < 0x40\n ? utf8WriteShort(target, value, offset)\n : encoder.encodeInto(value, target.subarray(offset)).written;\n};\n\nexport const utf8WriteShort = (target: any, value: string, offset: number) => {\n let i,\n c1,\n c2,\n strPosition = offset;\n\n const strLength = value.length;\n\n for (i = 0; i < strLength; i++) {\n c1 = value.charCodeAt(i);\n if (c1 < 0x80) {\n target[strPosition++] = c1;\n } else if (c1 < 0x800) {\n target[strPosition++] = (c1 >> 6) | 0xc0;\n target[strPosition++] = (c1 & 0x3f) | 0x80;\n } else if (\n (c1 & 0xfc00) === 0xd800 &&\n ((c2 = value.charCodeAt(i + 1)) & 0xfc00) === 0xdc00\n ) {\n c1 = 0x10000 + ((c1 & 0x03ff) << 10) + (c2 & 0x03ff);\n i++;\n target[strPosition++] = (c1 >> 18) | 0xf0;\n target[strPosition++] = ((c1 >> 12) & 0x3f) | 0x80;\n target[strPosition++] = ((c1 >> 6) & 0x3f) | 0x80;\n target[strPosition++] = (c1 & 0x3f) | 0x80;\n } else {\n target[strPosition++] = (c1 >> 12) | 0xe0;\n target[strPosition++] = ((c1 >> 6) & 0x3f) | 0x80;\n target[strPosition++] = (c1 & 0x3f) | 0x80;\n }\n }\n\n return strPosition - offset;\n};\n","import pako from 'pako';\nimport { CORE_TYPES } from './constants';\nimport { Dictionary } from './dictionary';\nimport type { TLExtension } from './extension';\nimport { float32, float64, int32, utf8Read } from './helpers';\n\nexport interface BinaryReaderOptions {\n dictionary?: string[] | Dictionary;\n extensions?: TLExtension[];\n}\n\nexport class BinaryReader {\n private target: Uint8Array;\n private _last?: any;\n private _lastObject?: any;\n private dictionary?: Dictionary;\n private dictionaryExtended: Dictionary;\n private extensions: Map<number, TLExtension>;\n private _repeat?: { pool: number; value: any };\n private _checksumOffset: number;\n offset: number;\n length: number;\n\n /**\n * Small utility class to read binary data.\n */\n constructor(data: Uint8Array, options?: BinaryReaderOptions) {\n this.target = data;\n this.offset = 0;\n this._checksumOffset = 0;\n this.length = data.length;\n this.extensions = new Map();\n\n if (options && options.extensions) {\n options.extensions.forEach(ext => {\n this.extensions.set(ext.token, ext);\n });\n }\n\n if (!options) {\n this.dictionary = new Dictionary();\n } else if (options.dictionary instanceof Dictionary) {\n this.dictionary = options.dictionary;\n } else if (Array.isArray(options.dictionary)) {\n this.dictionary = new Dictionary(options.dictionary);\n } else {\n this.dictionary = new Dictionary();\n }\n\n this.dictionaryExtended = new Dictionary(undefined, this.dictionary.size);\n }\n\n readByte() {\n this.assertRead(1);\n this._last = this.target[this.offset++];\n\n return this._last as number;\n }\n\n readInt32(signed = true) {\n this.assertRead(4);\n\n this._last =\n this.target[this.offset++] |\n (this.target[this.offset++] << 8) |\n (this.target[this.offset++] << 16) |\n (this.target[this.offset++] << 24);\n\n if (!signed) {\n this._last = this._last >>> 0;\n }\n\n return this._last as number;\n }\n\n readInt16(signed = true) {\n this.assertRead(2);\n\n this._last = this.target[this.offset++] | (this.target[this.offset++] << 8);\n\n if (signed) {\n this._last = (this._last << 16) >> 16;\n }\n\n return this._last as number;\n }\n\n readInt8(signed = true) {\n this.assertRead(1);\n\n this._last = this.target[this.offset++];\n\n if (signed) {\n this._last = (this._last << 24) >> 24;\n }\n\n return this._last as number;\n }\n\n /**\n * Reads a real floating point (4 bytes) value.\n * @returns {number}\n */\n readFloat() {\n this.assertRead(4);\n\n int32[0] = this.readInt32();\n this._last = float32[0];\n\n return this._last as number;\n }\n\n /**\n * Reads a real floating point (8 bytes) value.\n * @returns {BigInteger}\n */\n readDouble() {\n this.assertRead(8);\n\n int32[0] = this.readInt32();\n int32[1] = this.readInt32();\n this._last = float64[0];\n\n return this._last as number;\n }\n\n /**\n * Read the given amount of bytes, or -1 to read all remaining.\n * @param length {number}\n */\n assertRead(length: number) {\n if (this.length < this.offset + +length) {\n const left = this.target.length - this.offset;\n const result = this.target.subarray(this.offset, this.offset + left);\n\n const err = new Error(\n `No more data left to read (need ${length}, got ${left}: ${result}); last read ${this._last}`,\n );\n\n (err as any).incomplete = true;\n\n Error.captureStackTrace(err, this.assertRead);\n\n throw err;\n }\n }\n\n assertConstructor(constructorId: CORE_TYPES) {\n const byte = this.readByte();\n\n if (byte !== constructorId) {\n throw new Error(\n `Invalid constructor code, expected = ${CORE_TYPES[constructorId]}, got = ${\n CORE_TYPES[byte] || byte\n }, offset = ${this.offset - 1}`,\n );\n }\n }\n\n /**\n * Gets the byte array representing the current buffer as a whole.\n */\n getBuffer(): Uint8Array {\n return this.target;\n }\n\n readNull() {\n const value = this.readByte();\n\n if (value === CORE_TYPES.Null) {\n return null;\n }\n\n throw new Error(`Invalid boolean code ${value.toString(16)}`);\n }\n\n readLength() {\n const firstByte = this.readByte();\n\n if (firstByte === 254) {\n return this.readByte() | (this.readByte() << 8) | (this.readByte() << 16);\n }\n\n return firstByte;\n }\n\n readAll() {\n const result: any[] = [];\n\n while (this.length > this.offset) {\n result.push(this.readObject());\n }\n\n return result;\n }\n\n readBytes(): Uint8Array {\n const length = this.readLength();\n\n this.assertRead(length);\n\n const bytes = this.target.subarray(this.offset, this.offset + length);\n\n this.offset += bytes.length;\n\n this._last = bytes;\n\n return bytes;\n }\n\n /**\n * Reads encoded string.\n */\n readString(): string {\n const length = this.readLength();\n\n this.assertRead(length);\n\n const result = utf8Read(this.target, length, this.offset);\n\n this.offset += length;\n\n this._last = result;\n\n return result;\n }\n\n /**\n * Reads a boolean value.\n */\n readBool(): boolean {\n const value = this.readByte();\n\n if (value === CORE_TYPES.BoolTrue) {\n return true;\n } else if (value === CORE_TYPES.BoolFalse) {\n return false;\n } else {\n throw new Error(`Invalid boolean code ${value.toString(16)}`);\n }\n }\n\n /**\n * Reads and converts Unix time\n * into a Javascript {Date} object.\n */\n readDate(): Date {\n const value = this.readDouble();\n\n return new Date(value);\n }\n\n /**\n * Reads a object.\n */\n readObject(): any {\n if (this._repeat) {\n if (this._repeat.pool > 0) {\n --this._repeat.pool;\n return this._repeat.value;\n } else {\n this._repeat = undefined;\n }\n }\n\n const constructorId = this.readByte();\n const ext = this.extensions.get(constructorId);\n\n let value: any;\n\n if (ext) {\n value = ext.decode.call(this);\n } else {\n value = this._lastObject = this.readCore(constructorId);\n }\n\n return value;\n }\n\n readObjectGzip(): any {\n const bytes = this.readGzip();\n const reader = new BinaryReader(bytes);\n\n reader.extensions = this.extensions;\n reader.dictionary = this.dictionary;\n reader.dictionaryExtended = this.dictionaryExtended;\n\n return reader.readObject();\n }\n\n readGzip(): any {\n return pako.inflateRaw(this.readBytes());\n }\n\n private readCore(constructorId: CORE_TYPES): any {\n switch (constructorId) {\n case CORE_TYPES.None:\n return this.readObject();\n case CORE_TYPES.GZIP:\n return this.readObjectGzip();\n case CORE_TYPES.BoolTrue:\n return true;\n case CORE_TYPES.BoolFalse:\n return false;\n case CORE_TYPES.Vector:\n return this.readVector(false);\n case CORE_TYPES.VectorDynamic:\n return this.readVectorDynamic(false);\n case CORE_TYPES.Null:\n return null;\n case CORE_TYPES.Binary:\n return this.readBytes();\n case CORE_TYPES.String:\n return this.readString();\n case CORE_TYPES.Date:\n return this.readDate();\n case CORE_TYPES.Int32:\n return this.readInt32();\n case CORE_TYPES.Int16:\n return this.readInt16();\n case CORE_TYPES.Int8:\n return this.readInt8();\n case CORE_TYPES.UInt32:\n return this.readInt32(false);\n case CORE_TYPES.UInt16:\n return this.readInt16(false);\n case CORE_TYPES.UInt8:\n return this.readInt8(false);\n case CORE_TYPES.Float:\n return this.readFloat();\n case CORE_TYPES.Double:\n return this.readDouble();\n case CORE_TYPES.Map:\n return this.readMap(false);\n case CORE_TYPES.Checksum:\n return void this.readChecksum(false);\n case CORE_TYPES.DictIndex: {\n const idx = this.readLength();\n return this.getDictionaryValue(idx)!;\n }\n case CORE_TYPES.DictValue: {\n const value = this.readString();\n this.dictionaryExtended.maybeInsert(value);\n return value;\n }\n case CORE_TYPES.Repeat: {\n const size = this.readLength();\n this._repeat = { pool: size - 1, value: this._lastObject };\n return this._lastObject;\n }\n }\n\n throw new Error(\n `Invalid constructor = ${CORE_TYPES[constructorId] || constructorId}, offset = ${\n this.offset - 1\n }`,\n );\n }\n\n getDictionaryValue(index: number): string | null {\n let value: string | null = null;\n\n if (this.dictionary) {\n value = this.dictionary.getValue(index);\n }\n\n if (value === null) {\n value = this.dictionaryExtended.getValue(index);\n }\n\n return value;\n }\n\n readDictionary(): null | string {\n const constructorId = this.readByte();\n\n let key: string | null = null;\n\n switch (constructorId) {\n case CORE_TYPES.DictIndex: {\n const idx = this.readLength();\n key = this.getDictionaryValue(idx)!;\n break;\n }\n case CORE_TYPES.DictValue: {\n key = this.readString();\n this.dictionaryExtended.maybeInsert(key);\n break;\n }\n case CORE_TYPES.None: {\n key = null;\n break;\n }\n default: {\n this.seek(-1);\n }\n }\n\n return key;\n }\n\n readMap(checkConstructor = true): Record<string, any> {\n if (checkConstructor) {\n this.assertConstructor(CORE_TYPES.Map);\n }\n\n const temp: Record<string, any> = {};\n\n let key = this.readDictionary();\n\n while (key !== null) {\n temp[key] = this.readObject();\n key = this.readDictionary();\n }\n\n return temp;\n }\n\n decode<T = any>(value: Uint8Array): T {\n this.target = value;\n this._last = undefined;\n this._lastObject = undefined;\n this._repeat = undefined;\n this.offset = 0;\n this._checksumOffset = 0;\n this.length = value.length;\n\n return this.readObject();\n }\n\n /**\n * Reads a vector (a list) of objects.\n */\n readVector<T = any>(checkConstructor = true): T[] {\n if (checkConstructor) {\n this.assertConstructor(CORE_TYPES.Vector);\n }\n\n const count = this.readLength();\n const temp = [];\n\n for (let i = 0; i < count; i++) {\n temp.push(this.readObject());\n }\n\n return temp;\n }\n\n /**\n * Reads a vector (a list) of objects.\n */\n readVectorDynamic<T>(checkConstructor = true): T[] {\n if (checkConstructor) {\n this.assertConstructor(CORE_TYPES.VectorDynamic);\n }\n\n const temp = [];\n\n let complete = false;\n\n while (this.length > this.offset) {\n const constructorId = this.readByte();\n\n if (constructorId === CORE_TYPES.None) {\n complete = true;\n break;\n }\n\n const ext = this.extensions.get(constructorId);\n\n let value: any;\n\n if (ext) {\n value = ext.decode.call(this);\n } else {\n value = this.readCore(constructorId);\n }\n\n temp.push(value);\n }\n\n if (!complete) {\n const err = new Error(`DynamicVector incomplete.`);\n (err as any).incomplete = true;\n Error.captureStackTrace(err, this.readDictionary);\n\n throw err;\n }\n\n this._last = temp;\n\n return temp;\n }\n\n readChecksum(checkConstructor: boolean = true): void {\n const offset = this.offset;\n\n if (checkConstructor) {\n this.assertConstructor(CORE_TYPES.Checksum);\n }\n\n const bytes = this.target.slice(this._checksumOffset, offset);\n const checksum = this.readLength();\n let sum = 0;\n\n for (const val of bytes) {\n sum += val;\n }\n\n if (checksum - sum !== 0) {\n throw new Error(\n `Invalid checksum = ${checksum - sum}, offset = ${offset}`,\n );\n }\n\n this._checksumOffset = this.offset;\n }\n\n /**\n * Tells the current position on the stream.\n */\n tellPosition(): number {\n return this.offset;\n }\n\n /**\n * Sets the current position on the stream.\n */\n setPosition(position: number): void {\n this.offset = position;\n }\n\n /**\n * Seeks the stream position given an offset from the current position.\n * The offset may be negative.\n */\n seek(offset: number): void {\n this.offset += offset;\n }\n}\n","import pako from 'pako';\nimport { CORE_TYPES, MAX_BUFFER_SIZE } from './constants';\nimport { Dictionary } from './dictionary';\nimport type { TLExtension } from './extension';\nimport {\n byteArrayAllocate,\n coreType,\n float32,\n float64,\n int32,\n utf8Write,\n} from './helpers.js';\n\nconst noop = Symbol();\n\nexport interface BinaryWriterOptions {\n gzip?: boolean;\n dictionary?: string[] | Dictionary;\n extensions?: TLExtension[];\n}\n\nconst NO_CONSTRUCTOR = new Set([\n CORE_TYPES.BoolFalse,\n CORE_TYPES.BoolTrue,\n CORE_TYPES.Null,\n]);\n\nconst SUPPORT_COMPRESSION = new Set([CORE_TYPES.String]);\n\nexport class BinaryWriter {\n private withGzip: boolean;\n private target: Uint8Array;\n private dictionary?: Dictionary;\n private dictionaryExtended: Dictionary;\n private extensions: Map<number, TLExtension>;\n private _last: any = noop;\n private _checksumOffset: number;\n private _repeat?: { offset: number; count: number };\n offset: number;\n\n constructor(options?: BinaryWriterOptions) {\n this.offset = 0;\n this._checksumOffset = 0;\n this.extensions = new Map();\n this.withGzip = !!options && !!options.gzip;\n\n this.target = byteArrayAllocate(8192);\n\n if (options && options.extensions) {\n options.extensions.forEach(ext => {\n this.extensions.set(ext.token, ext);\n });\n }\n\n if (!options) {\n this.dictionary = new Dictionary();\n } else if (options.dictionary instanceof Dictionary) {\n this.dictionary = options.dictionary;\n } else if (Array.isArray(options.dictionary)) {\n this.dictionary = new Dictionary(options.dictionary);\n } else {\n this.dictionary = new Dictionary();\n }\n\n this.dictionaryExtended = new Dictionary(undefined, this.dictionary.size);\n }\n\n allocate(size: number): this {\n const position = this.offset + size;\n\n if (this.safeEnd < position) {\n this.makeRoom(position);\n }\n\n return this;\n }\n\n private makeRoom(end: number): void {\n let start = 0;\n let newSize = 0;\n let target = this.target;\n\n if (end > 0x1000000) {\n // special handling for really large buffers\n if (end - start > MAX_BUFFER_SIZE)\n throw new Error(\n 'Packed buffer would be larger than maximum buffer size',\n );\n newSize = Math.min(\n MAX_BUFFER_SIZE,\n Math.round(\n Math.max((end - start) * (end > 0x4000000 ? 1.25 : 2), 0x400000) /\n 0x1000,\n ) * 0x1000,\n );\n } else {\n // faster handling for smaller buffers\n newSize =\n ((Math.max((end - start) << 2, target.length - 1) >> 12) + 1) << 12;\n }\n\n const newBuffer = byteArrayAllocate(newSize);\n\n end = Math.min(end, target.length);\n\n newBuffer.set(target.slice(start, end));\n\n this.target = newBuffer;\n }\n\n get safeEnd(): number {\n return this.target.length - 10;\n }\n\n getBuffer(): Uint8Array {\n return this.target.subarray(0, this.offset);\n }\n\n writeByte(value: number): this {\n this.allocate(1);\n this.target[this.offset++] = value;\n return this;\n }\n\n writeBool(value: boolean): this {\n if (value) {\n this.writeByte(CORE_TYPES.BoolTrue);\n } else {\n this.writeByte(CORE_TYPES.BoolFalse);\n }\n\n return this;\n }\n\n writeNull(): this {\n this.writeByte(CORE_TYPES.Null);\n return this;\n }\n\n writeInt32(value: number, signed = true): this {\n this.allocate(4);\n\n if (signed) {\n this.target[this.offset++] = value;\n this.target[this.offset++] = value >> 8;\n this.target[this.offset++] = value >> 16;\n this.target[this.offset++] = value >> 24;\n } else {\n this.target[this.offset++] = value;\n this.target[this.offset++] = value >> 8;\n this.target[this.offset++] = value >> 16;\n this.target[this.offset++] = value >> 24;\n }\n\n return this;\n }\n\n writeInt16(value: number, signed = true): this {\n this.allocate(2);\n\n if (signed) {\n this.target[this.offset++] = value;\n this.target[this.offset++] = value >> 8;\n } else {\n this.target[this.offset++] = value;\n this.target[this.offset++] = value >> 8;\n }\n\n return this;\n }\n\n writeInt8(value: number, signed = true): this {\n this.allocate(1);\n this.target[this.offset++] = value;\n return this;\n }\n\n writeFloat(value: number): this {\n this.allocate(4);\n float32[0] = value;\n this.writeInt32(int32[0]);\n return this;\n }\n\n writeDouble(value: number): this {\n this.allocate(8);\n\n float64[0] = value;\n this.writeInt32(int32[0], false);\n this.writeInt32(int32[1], false);\n\n return this;\n }\n\n writeDate(value: number | Date): this {\n let timestamp = 0;\n\n if (value instanceof Date) {\n timestamp = value.getTime();\n } else if (typeof value === 'number') {\n timestamp = value;\n }\n\n this.writeDouble(timestamp);\n return this;\n }\n\n writeString(value: string): this {\n const strLength = value.length;\n\n let start = this.offset;\n let require = strLength << 2;\n\n if (require < 254) {\n require += 1;\n this.offset += 1;\n } else {\n require += 4;\n this.offset += 4;\n }\n\n this.allocate(require);\n\n const bytes = utf8Write(this.target, value, this.offset);\n\n if (require < 254) {\n this.target[start++] = bytes;\n } else {\n this.target[start++] = 254;\n this.target[start++] = bytes % 256;\n this.target[start++] = (bytes >> 8) % 256;\n this.target[start++] = (bytes >> 16) % 256;\n }\n\n this.offset += bytes;\n\n return this;\n }\n\n writeChecksum(withConstructor: boolean = true): this {\n const bytes = this.target.slice(this._checksumOffset, this.offset);\n let sum = 0;\n\n for (const val of bytes) {\n sum += val;\n }\n\n if (withConstructor) {\n this.writeByte(CORE_TYPES.Checksum);\n }\n\n this.writeLength(sum);\n this._checksumOffset = this.offset;\n\n return this;\n }\n\n writeBytes(value: Uint8Array): this {\n const length = value.length;\n\n this.writeLength(length);\n this.allocate(length);\n this.target.set(value, this.offset);\n\n this.offset += length;\n\n return this;\n }\n\n writeLength(value: number): this {\n if (value < 254) {\n this.allocate(1);\n this.target[this.offset++] = value;\n } else {\n this.allocate(4);\n this.target[this.offset++] = 254;\n this.target[this.offset++] = value % 256;\n this.target[this.offset++] = (value >> 8) % 256;\n this.target[this.offset++] = (value >> 16) % 256;\n }\n\n return this;\n }\n\n writeVector(value: Array<any>): this {\n const length = value.length;\n this.writeLength(length);\n\n for (let i = 0; i < length; i++) {\n if (value[i] === undefined) {\n this.writeNull();\n } else {\n this.writeObject(value[i]);\n }\n }\n\n return this;\n }\n\n writeMap(object: Record<string, any>): this {\n for (const key in object) {\n if (object[key] === undefined) continue;\n\n this._last = noop;\n this.wireDictionary(key);\n this.writeObject(object[key]);\n }\n\n this.writeByte(CORE_TYPES.None);\n\n return this;\n }\n\n wireDictionary(value: string): this {\n let idx: number | null = null;\n\n if (this.dictionary) {\n idx = this.dictionary.getIndex(value);\n }\n\n if (idx === null) {\n idx = this.dictionaryExtended.getIndex(value);\n }\n\n if (idx === null) {\n this.dictionaryExtended.maybeInsert(value);\n this.writeCore(CORE_TYPES.DictValue, value);\n } else {\n this.writeCore(CORE_TYPES.DictIndex, idx);\n }\n\n return this;\n }\n\n writeGzip(value: Uint8Array | ArrayBuffer): this {\n const compressed = pako.deflateRaw(value, { level: 9 });\n this.writeBytes(compressed);\n return this;\n }\n\n encode(value: any): Uint8Array {\n this.offset = 0;\n this._checksumOffset = 0;\n this._last = noop;\n this._repeat = undefined;\n this.target = byteArrayAllocate(256);\n\n this.writeObject(value);\n\n return this.getBuffer();\n }\n\n startDynamicVector(): this {\n this.writeByte(CORE_TYPES.VectorDynamic);\n return this;\n }\n\n endDynamicVector(): this {\n this.writeByte(CORE_TYPES.None);\n return this;\n }\n\n private _writeCustom(value: any): boolean {\n const start = this.offset;\n\n this.allocate(1);\n\n this.offset++;\n\n let edgeExt;\n\n for (const ext of this.extensions.values()) {\n if (ext.token === -1) {\n edgeExt = ext;\n continue;\n }\n\n ext.encode.call(this, value);\n\n const processed = start + 1 < this.offset;\n\n if (processed) {\n const end = this.offset;\n this.offset = start;\n this.writeByte(ext.token);\n this.offset = end;\n\n return true;\n }\n }\n\n this.offset = start;\n\n if (edgeExt) {\n edgeExt.encode.call(this, value);\n return start < this.offset;\n }\n\n return false;\n }\n\n writeObject(value: any): this {\n if (value === undefined) return this;\n\n const constructorId = coreType(value);\n\n // console.log('write', {\n // \toffset: this.offset,\n // \tconstructorId: CORE_TYPES[constructorId],\n // \tvalue: String(value),\n // });\n\n if (constructorId === CORE_TYPES.None) {\n if (this._writeCustom(value)) {\n return this;\n }\n\n throw new TypeError(`Invalid core type of ${value}`);\n }\n\n if (this._last === value) {\n this.writeRepeat();\n } else {\n this._last = value;\n this._repeat = undefined;\n this.writeCore(constructorId, value);\n }\n\n return this;\n }\n\n writeObjectGzip(value: any): this {\n const writer = new BinaryWriter();\n\n writer.extensions = this.extensions;\n writer.dictionary = this.dictionary;\n writer.dictionaryExtended = this.dictionaryExtended;\n\n writer.writeObject(value);\n this.writeCore(CORE_TYPES.GZIP, writer.getBuffer());\n\n return this;\n }\n\n private writeCore(constructorId: CORE_TYPES, value: any): this {\n if (this.withGzip && SUPPORT_COMPRESSION.has(constructorId)) {\n this.writeObjectGzip(value);\n return this;\n } else if (!NO_CONSTRUCTOR.has(constructorId)) {\n this.writeByte(constructorId);\n }\n\n switch (constructorId) {\n case CORE_TYPES.GZIP: {\n return this.writeGzip(value);\n }\n\n case CORE_TYPES.DictIndex: {\n return this.writeLength(value);\n }\n\n case CORE_TYPES.DictValue: {\n return this.writeString(value);\n }\n\n case CORE_TYPES.BoolFalse: {\n return this.writeBool(value);\n }\n\n case CORE_TYPES.BoolTrue: {\n return this.writeBool(value);\n }\n\n case CORE_TYPES.Date: {\n return this.writeDate(value);\n }\n\n case CORE_TYPES.Int32: {\n return this.writeInt32(value);\n }\n\n case CORE_TYPES.Int16: {\n return this.writeInt16(value);\n }\n\n case CORE_TYPES.Int8: {\n return this.writeInt8(value);\n }\n\n case CORE_TYPES.UInt32: {\n return this.writeInt32(value, false);\n }\n\n case CORE_TYPES.UInt16: {\n return this.writeInt16(value, false);\n }\n\n case CORE_TYPES.UInt8: {\n return this.writeInt8(value, false);\n }\n\n case CORE_TYPES.Double: {\n return this.writeDouble(value);\n }\n\n case CORE_TYPES.Float: {\n return this.writeFloat(value);\n }\n\n case CORE_TYPES.Null: {\n return this.writeNull();\n }\n\n case CORE_TYPES.String: {\n // write short strings into dictionary\n if (value.length <= 0x10) {\n this.offset--;\n return this.wireDictionary(value);\n }\n\n return this.writeString(value);\n }\n\n case CORE_TYPES.Vector: {\n return this.writeVector(value);\n }\n\n case CORE_TYPES.Map: {\n return this.writeMap(value);\n }\n }\n\n return this;\n }\n\n private writeRepeat(): this {\n if (!this._repeat) {\n this.writeByte(CORE_TYPES.Repeat);\n this._repeat = { count: 0, offset: this.offset };\n }\n\n this.offset = this._repeat.offset;\n this._repeat.count++;\n\n this.writeLength(this._repeat.count);\n return this;\n }\n}\n"],"names":["CORE_TYPES","isPlainObject","pako"],"mappings":"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