@andrew_l/tl-pack 0.2.15 → 0.2.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -31,6 +31,7 @@ var CORE_TYPES = /* @__PURE__ */ ((CORE_TYPES2) => {
31
31
  CORE_TYPES2[CORE_TYPES2["Repeat"] = 20] = "Repeat";
32
32
  CORE_TYPES2[CORE_TYPES2["Checksum"] = 21] = "Checksum";
33
33
  CORE_TYPES2[CORE_TYPES2["GZIP"] = 25] = "GZIP";
34
+ CORE_TYPES2[CORE_TYPES2["Structure"] = 26] = "Structure";
34
35
  return CORE_TYPES2;
35
36
  })(CORE_TYPES || {});
36
37
  const MAX_BUFFER_SIZE = 2144337920;
@@ -85,1072 +86,1499 @@ class Dictionary {
85
86
  }
86
87
  }
87
88
 
88
- const encoder = new TextEncoder();
89
- const decoder = new TextDecoder();
90
- const fromCharCode = String.fromCharCode;
91
- const int32 = new Int32Array(2);
92
- const float32 = new Float32Array(int32.buffer);
93
- const float64 = new Float64Array(int32.buffer);
94
- function byteArrayAllocate(length) {
95
- return new Uint8Array(length);
96
- }
97
- function coreType(value) {
98
- switch (typeof value) {
99
- case "string": {
100
- return CORE_TYPES.String;
101
- }
102
- case "boolean": {
103
- return value ? CORE_TYPES.BoolTrue : CORE_TYPES.BoolFalse;
104
- }
105
- case "number": {
106
- if (Math.trunc(value) === value) {
107
- if (value >= 0 && value <= 255) {
108
- return CORE_TYPES.UInt8;
109
- } else if (value >= 0 && value <= 65535) {
110
- return CORE_TYPES.UInt16;
111
- } else if (value >= 0 && value <= 4294967295) {
112
- return CORE_TYPES.UInt32;
113
- } else if (value >= -128 && value <= 127) {
114
- return CORE_TYPES.Int8;
115
- } else if (value >= -32768 && value <= 32767) {
116
- return CORE_TYPES.Int16;
117
- } else if (value >= -2147483648 && value <= 2147483647) {
118
- return CORE_TYPES.Int32;
119
- }
89
+ const noop = Symbol();
90
+ const NO_CONSTRUCTOR = /* @__PURE__ */ new Set([
91
+ CORE_TYPES.BoolFalse,
92
+ CORE_TYPES.BoolTrue,
93
+ CORE_TYPES.Null
94
+ ]);
95
+ const SUPPORT_COMPRESSION = /* @__PURE__ */ new Set([CORE_TYPES.String]);
96
+ const NOOP_DICTIONARY$1 = new Dictionary();
97
+ class BinaryWriter {
98
+ withGzip;
99
+ target;
100
+ dictionary;
101
+ dictionaryExtended;
102
+ extensions;
103
+ structures;
104
+ _last;
105
+ offsetChecksum;
106
+ _repeat;
107
+ offset;
108
+ constructor({
109
+ gzip = false,
110
+ dictionary = NOOP_DICTIONARY$1,
111
+ extensions,
112
+ structures
113
+ } = {}) {
114
+ this.offset = 0;
115
+ this.offsetChecksum = 0;
116
+ this.extensions = /* @__PURE__ */ new Map();
117
+ this.structures = /* @__PURE__ */ new Map();
118
+ this.withGzip = gzip;
119
+ this.target = byteArrayAllocate(8192);
120
+ this._last = noop;
121
+ if (extensions) {
122
+ for (const ext of extensions) {
123
+ this.extensions.set(ext.token, ext);
120
124
  }
121
- return CORE_TYPES.Double;
122
125
  }
123
- case "object": {
124
- if (value === null) return CORE_TYPES.Null;
125
- if (value instanceof Date) {
126
- return CORE_TYPES.Date;
127
- }
128
- if (Array.isArray(value)) {
129
- return CORE_TYPES.Vector;
130
- }
131
- if (toolkit.isPlainObject(value)) {
132
- return CORE_TYPES.Map;
126
+ if (structures) {
127
+ for (const struct of structures) {
128
+ this.structures.set(struct.extension.token, struct);
133
129
  }
134
130
  }
131
+ if (Array.isArray(dictionary)) {
132
+ this.dictionary = new Dictionary(dictionary);
133
+ } else {
134
+ this.dictionary = dictionary;
135
+ }
136
+ this.dictionaryExtended = new Dictionary(void 0, this.dictionary.size);
135
137
  }
136
- return CORE_TYPES.None;
137
- }
138
- function utf8Read(target, length, offset) {
139
- let result;
140
- if (length < 16) {
141
- if (result = utf8ReadShort(target, length, offset)) return result;
138
+ /**
139
+ * Reset internal state
140
+ */
141
+ reset() {
142
+ this.offset = 0;
143
+ this.offsetChecksum = 0;
144
+ this._last = noop;
145
+ this._repeat = void 0;
146
+ this.dictionaryExtended = new Dictionary(void 0, this.dictionary.size);
147
+ return this;
142
148
  }
143
- if (length > 64 && decoder)
144
- return decoder.decode(target.subarray(offset, offset += length));
145
- const end = offset + length;
146
- const units = [];
147
- result = "";
148
- while (offset < end) {
149
- const byte1 = target[offset++];
150
- if ((byte1 & 128) === 0) {
151
- units.push(byte1);
152
- } else if ((byte1 & 224) === 192) {
153
- const byte2 = target[offset++] & 63;
154
- units.push((byte1 & 31) << 6 | byte2);
155
- } else if ((byte1 & 240) === 224) {
156
- const byte2 = target[offset++] & 63;
157
- const byte3 = target[offset++] & 63;
158
- units.push((byte1 & 31) << 12 | byte2 << 6 | byte3);
159
- } else if ((byte1 & 248) === 240) {
160
- const byte2 = target[offset++] & 63;
161
- const byte3 = target[offset++] & 63;
162
- const byte4 = target[offset++] & 63;
163
- let unit = (byte1 & 7) << 18 | byte2 << 12 | byte3 << 6 | byte4;
164
- if (unit > 65535) {
165
- unit -= 65536;
166
- units.push(unit >>> 10 & 1023 | 55296);
167
- unit = 56320 | unit & 1023;
168
- }
169
- units.push(unit);
170
- } else {
171
- units.push(byte1);
149
+ allocate(size) {
150
+ const position = this.offset + size;
151
+ if (this.safeEnd < position) {
152
+ this.makeRoom(position);
172
153
  }
173
- if (units.length >= 4096) {
174
- result += fromCharCode.apply(String, units);
175
- units.length = 0;
154
+ return this;
155
+ }
156
+ makeRoom(end) {
157
+ let start = 0;
158
+ let newSize = 0;
159
+ let target = this.target;
160
+ if (end > 16777216) {
161
+ if (end - start > MAX_BUFFER_SIZE)
162
+ throw new Error(
163
+ "Packed buffer would be larger than maximum buffer size"
164
+ );
165
+ newSize = Math.min(
166
+ MAX_BUFFER_SIZE,
167
+ Math.round(
168
+ Math.max((end - start) * (end > 67108864 ? 1.25 : 2), 4194304) / 4096
169
+ ) * 4096
170
+ );
171
+ } else {
172
+ newSize = (Math.max(end - start << 2, target.length - 1) >> 12) + 1 << 12;
176
173
  }
174
+ const newBuffer = byteArrayAllocate(newSize);
175
+ end = Math.min(end, target.length);
176
+ newBuffer.set(target.slice(start, end));
177
+ this.target = newBuffer;
177
178
  }
178
- if (units.length > 0) {
179
- result += fromCharCode.apply(String, units);
179
+ get safeEnd() {
180
+ return this.target.length - 10;
180
181
  }
181
- return result;
182
- }
183
- function utf8ReadShort(target, length, offset) {
184
- if (length < 4) {
185
- if (length < 2) {
186
- if (length === 0) return "";
187
- else {
188
- let a = target[offset++];
189
- if ((a & 128) > 1) {
190
- offset -= 1;
191
- return;
192
- }
193
- return fromCharCode(a);
194
- }
182
+ getBuffer() {
183
+ return this.target.subarray(0, this.offset);
184
+ }
185
+ writeByte(value) {
186
+ this.allocate(1);
187
+ this.target[this.offset++] = value;
188
+ return this;
189
+ }
190
+ writeBool(value) {
191
+ if (value) {
192
+ this.writeByte(CORE_TYPES.BoolTrue);
195
193
  } else {
196
- let a = target[offset++];
197
- let b = target[offset++];
198
- if ((a & 128) > 0 || (b & 128) > 0) {
199
- offset -= 2;
200
- return;
201
- }
202
- if (length < 3) return fromCharCode(a, b);
203
- let c = target[offset++];
204
- if ((c & 128) > 0) {
205
- offset -= 3;
206
- return;
207
- }
208
- return fromCharCode(a, b, c);
194
+ this.writeByte(CORE_TYPES.BoolFalse);
209
195
  }
210
- } else {
211
- let a = target[offset++];
212
- let b = target[offset++];
213
- let c = target[offset++];
214
- let d = target[offset++];
215
- if ((a & 128) > 0 || (b & 128) > 0 || (c & 128) > 0 || (d & 128) > 0) {
216
- offset -= 4;
217
- return;
196
+ return this;
197
+ }
198
+ writeNull() {
199
+ this.writeByte(CORE_TYPES.Null);
200
+ return this;
201
+ }
202
+ writeInt32(value, signed = true) {
203
+ this.allocate(4);
204
+ if (signed) {
205
+ this.target[this.offset++] = value;
206
+ this.target[this.offset++] = value >> 8;
207
+ this.target[this.offset++] = value >> 16;
208
+ this.target[this.offset++] = value >> 24;
209
+ } else {
210
+ this.target[this.offset++] = value;
211
+ this.target[this.offset++] = value >> 8;
212
+ this.target[this.offset++] = value >> 16;
213
+ this.target[this.offset++] = value >> 24;
218
214
  }
219
- if (length < 6) {
220
- if (length === 4) return fromCharCode(a, b, c, d);
221
- else {
222
- let e = target[offset++];
223
- if ((e & 128) > 0) {
224
- offset -= 5;
225
- return;
226
- }
227
- return fromCharCode(a, b, c, d, e);
228
- }
229
- } else if (length < 8) {
230
- let e = target[offset++];
231
- let f = target[offset++];
232
- if ((e & 128) > 0 || (f & 128) > 0) {
233
- offset -= 6;
234
- return;
235
- }
236
- if (length < 7) return fromCharCode(a, b, c, d, e, f);
237
- let g = target[offset++];
238
- if ((g & 128) > 0) {
239
- offset -= 7;
240
- return;
241
- }
242
- return fromCharCode(a, b, c, d, e, f, g);
215
+ return this;
216
+ }
217
+ writeInt16(value, signed = true) {
218
+ this.allocate(2);
219
+ if (signed) {
220
+ this.target[this.offset++] = value;
221
+ this.target[this.offset++] = value >> 8;
243
222
  } else {
244
- let e = target[offset++];
245
- let f = target[offset++];
246
- let g = target[offset++];
247
- let h = target[offset++];
248
- if ((e & 128) > 0 || (f & 128) > 0 || (g & 128) > 0 || (h & 128) > 0) {
249
- offset -= 8;
250
- return;
251
- }
252
- if (length < 10) {
253
- if (length === 8) return fromCharCode(a, b, c, d, e, f, g, h);
254
- else {
255
- let i = target[offset++];
256
- if ((i & 128) > 0) {
257
- offset -= 9;
258
- return;
259
- }
260
- return fromCharCode(a, b, c, d, e, f, g, h, i);
261
- }
262
- } else if (length < 12) {
263
- let i = target[offset++];
264
- let j = target[offset++];
265
- if ((i & 128) > 0 || (j & 128) > 0) {
266
- offset -= 10;
267
- return;
268
- }
269
- if (length < 11) return fromCharCode(a, b, c, d, e, f, g, h, i, j);
270
- let k = target[offset++];
271
- if ((k & 128) > 0) {
272
- offset -= 11;
273
- return;
274
- }
275
- return fromCharCode(a, b, c, d, e, f, g, h, i, j, k);
276
- } else {
277
- let i = target[offset++];
278
- let j = target[offset++];
279
- let k = target[offset++];
280
- let l = target[offset++];
281
- if ((i & 128) > 0 || (j & 128) > 0 || (k & 128) > 0 || (l & 128) > 0) {
282
- offset -= 12;
283
- return;
284
- }
285
- if (length < 14) {
286
- if (length === 12)
287
- return fromCharCode(a, b, c, d, e, f, g, h, i, j, k, l);
288
- else {
289
- let m = target[offset++];
290
- if ((m & 128) > 0) {
291
- offset -= 13;
292
- return;
293
- }
294
- return fromCharCode(a, b, c, d, e, f, g, h, i, j, k, l, m);
295
- }
296
- } else {
297
- let m = target[offset++];
298
- let n = target[offset++];
299
- if ((m & 128) > 0 || (n & 128) > 0) {
300
- offset -= 14;
301
- return;
302
- }
303
- if (length < 15)
304
- return fromCharCode(a, b, c, d, e, f, g, h, i, j, k, l, m, n);
305
- let o = target[offset++];
306
- if ((o & 128) > 0) {
307
- offset -= 15;
308
- return;
309
- }
310
- return fromCharCode(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o);
311
- }
312
- }
223
+ this.target[this.offset++] = value;
224
+ this.target[this.offset++] = value >> 8;
225
+ }
226
+ return this;
227
+ }
228
+ writeInt8(value, signed = true) {
229
+ this.allocate(1);
230
+ this.target[this.offset++] = value;
231
+ return this;
232
+ }
233
+ writeFloat(value) {
234
+ this.allocate(4);
235
+ float32[0] = value;
236
+ this.writeInt32(int32[0]);
237
+ return this;
238
+ }
239
+ writeDouble(value) {
240
+ this.allocate(8);
241
+ float64[0] = value;
242
+ this.writeInt32(int32[0], false);
243
+ this.writeInt32(int32[1], false);
244
+ return this;
245
+ }
246
+ writeDate(value) {
247
+ let timestamp = 0;
248
+ if (value instanceof Date) {
249
+ timestamp = value.getTime();
250
+ } else if (typeof value === "number") {
251
+ timestamp = value;
313
252
  }
253
+ this.writeDouble(timestamp);
254
+ return this;
314
255
  }
315
- }
316
- const utf8Write = function(target, value, offset) {
317
- return value.length < 64 ? utf8WriteShort(target, value, offset) : encoder.encodeInto(value, target.subarray(offset)).written;
318
- };
319
- const utf8WriteShort = (target, value, offset) => {
320
- let i, c1, c2, strPosition = offset;
321
- const strLength = value.length;
322
- for (i = 0; i < strLength; i++) {
323
- c1 = value.charCodeAt(i);
324
- if (c1 < 128) {
325
- target[strPosition++] = c1;
326
- } else if (c1 < 2048) {
327
- target[strPosition++] = c1 >> 6 | 192;
328
- target[strPosition++] = c1 & 63 | 128;
329
- } else if ((c1 & 64512) === 55296 && ((c2 = value.charCodeAt(i + 1)) & 64512) === 56320) {
330
- c1 = 65536 + ((c1 & 1023) << 10) + (c2 & 1023);
331
- i++;
332
- target[strPosition++] = c1 >> 18 | 240;
333
- target[strPosition++] = c1 >> 12 & 63 | 128;
334
- target[strPosition++] = c1 >> 6 & 63 | 128;
335
- target[strPosition++] = c1 & 63 | 128;
256
+ writeString(value) {
257
+ const strLength = value.length;
258
+ let start = this.offset;
259
+ let require = strLength << 2;
260
+ if (require < 254) {
261
+ require += 1;
262
+ this.offset += 1;
336
263
  } else {
337
- target[strPosition++] = c1 >> 12 | 224;
338
- target[strPosition++] = c1 >> 6 & 63 | 128;
339
- target[strPosition++] = c1 & 63 | 128;
264
+ require += 4;
265
+ this.offset += 4;
266
+ }
267
+ this.allocate(require);
268
+ const bytes = utf8Write(this.target, value, this.offset);
269
+ if (require < 254) {
270
+ this.target[start++] = bytes;
271
+ } else {
272
+ this.target[start++] = 254;
273
+ this.target[start++] = bytes % 256;
274
+ this.target[start++] = (bytes >> 8) % 256;
275
+ this.target[start++] = (bytes >> 16) % 256;
340
276
  }
277
+ this.offset += bytes;
278
+ return this;
341
279
  }
342
- return strPosition - offset;
343
- };
344
-
345
- class BinaryReader {
346
- target;
347
- _last;
348
- _lastObject;
349
- dictionary;
350
- dictionaryExtended;
351
- extensions;
352
- _repeat;
353
- _checksumOffset;
354
- offset;
355
- length;
356
- /**
357
- * Small utility class to read binary data.
358
- */
359
- constructor(data, options) {
360
- this.target = data;
361
- this.offset = 0;
362
- this._checksumOffset = 0;
363
- this.length = data.length;
364
- this.extensions = /* @__PURE__ */ new Map();
365
- if (options && options.extensions) {
366
- options.extensions.forEach((ext) => {
367
- this.extensions.set(ext.token, ext);
368
- });
280
+ writeChecksum(withConstructor = true) {
281
+ const bytes = this.target.subarray(this.offsetChecksum, this.offset);
282
+ let sum = 0;
283
+ for (const val of bytes) {
284
+ sum += val;
369
285
  }
370
- if (!options) {
371
- this.dictionary = new Dictionary();
372
- } else if (options.dictionary instanceof Dictionary) {
373
- this.dictionary = options.dictionary;
374
- } else if (Array.isArray(options.dictionary)) {
375
- this.dictionary = new Dictionary(options.dictionary);
376
- } else {
377
- this.dictionary = new Dictionary();
286
+ if (withConstructor) {
287
+ this.writeByte(CORE_TYPES.Checksum);
378
288
  }
379
- this.dictionaryExtended = new Dictionary(void 0, this.dictionary.size);
289
+ this.writeInt32(sum);
290
+ this.offsetChecksum = this.offset;
291
+ return this;
380
292
  }
381
- readByte() {
382
- this.assertRead(1);
383
- this._last = this.target[this.offset++];
384
- return this._last;
293
+ writeBytes(value) {
294
+ const length = value.length;
295
+ this.writeLength(length);
296
+ this.allocate(length);
297
+ this.target.set(value, this.offset);
298
+ this.offset += length;
299
+ return this;
385
300
  }
386
- readInt32(signed = true) {
387
- this.assertRead(4);
388
- this._last = this.target[this.offset++] | this.target[this.offset++] << 8 | this.target[this.offset++] << 16 | this.target[this.offset++] << 24;
389
- if (!signed) {
390
- this._last = this._last >>> 0;
301
+ writeLength(value) {
302
+ if (value < 254) {
303
+ this.allocate(1);
304
+ this.target[this.offset++] = value;
305
+ } else {
306
+ this.allocate(4);
307
+ this.target[this.offset++] = 254;
308
+ this.target[this.offset++] = value % 256;
309
+ this.target[this.offset++] = (value >> 8) % 256;
310
+ this.target[this.offset++] = (value >> 16) % 256;
391
311
  }
392
- return this._last;
312
+ return this;
393
313
  }
394
- readInt16(signed = true) {
395
- this.assertRead(2);
396
- this._last = this.target[this.offset++] | this.target[this.offset++] << 8;
397
- if (signed) {
398
- this._last = this._last << 16 >> 16;
314
+ writeVector(value) {
315
+ const length = value.length;
316
+ this.writeLength(length);
317
+ for (let i = 0; i < length; i++) {
318
+ if (value[i] === void 0) {
319
+ this.writeNull();
320
+ } else {
321
+ this.writeObject(value[i]);
322
+ }
399
323
  }
400
- return this._last;
324
+ return this;
401
325
  }
402
- readInt8(signed = true) {
403
- this.assertRead(1);
404
- this._last = this.target[this.offset++];
405
- if (signed) {
406
- this._last = this._last << 24 >> 24;
326
+ writeMap(object) {
327
+ for (const key in object) {
328
+ if (object[key] === void 0) continue;
329
+ this._last = noop;
330
+ this.wireDictionary(key);
331
+ this.writeObject(object[key]);
407
332
  }
408
- return this._last;
333
+ this.writeByte(CORE_TYPES.None);
334
+ return this;
409
335
  }
410
- /**
411
- * Reads a real floating point (4 bytes) value.
412
- * @returns {number}
413
- */
414
- readFloat() {
415
- this.assertRead(4);
416
- int32[0] = this.readInt32();
417
- this._last = float32[0];
418
- return this._last;
336
+ wireDictionary(value) {
337
+ let idx = null;
338
+ idx = this.dictionary.getIndex(value);
339
+ if (idx === null) {
340
+ idx = this.dictionaryExtended.getIndex(value);
341
+ }
342
+ if (idx === null) {
343
+ this.dictionaryExtended.maybeInsert(value);
344
+ this.writeCore(CORE_TYPES.DictValue, value);
345
+ } else {
346
+ this.writeCore(CORE_TYPES.DictIndex, idx);
347
+ }
348
+ return this;
419
349
  }
420
- /**
421
- * Reads a real floating point (8 bytes) value.
422
- * @returns {BigInteger}
423
- */
424
- readDouble() {
425
- this.assertRead(8);
426
- int32[0] = this.readInt32();
427
- int32[1] = this.readInt32();
428
- this._last = float64[0];
429
- return this._last;
350
+ writeStructure(value) {
351
+ const ctor = value.constructor;
352
+ this.writeInt32(ctor.extension.token, false);
353
+ ctor.extension.encode.call(this, value.value);
354
+ return this;
430
355
  }
431
- /**
432
- * Read the given amount of bytes, or -1 to read all remaining.
433
- * @param length {number}
434
- */
435
- assertRead(length) {
436
- if (this.length < this.offset + +length) {
437
- const left = this.target.length - this.offset;
438
- const result = this.target.subarray(this.offset, this.offset + left);
439
- const err = new Error(
440
- `No more data left to read (need ${length}, got ${left}: ${result}); last read ${this._last}`
441
- );
442
- err.incomplete = true;
443
- Error.captureStackTrace(err, this.assertRead);
444
- throw err;
356
+ writeGzip(value) {
357
+ const compressed = pako__default.deflateRaw(value, { level: 9 });
358
+ this.writeBytes(compressed);
359
+ return this;
360
+ }
361
+ encode(value) {
362
+ this.offset = 0;
363
+ this.offsetChecksum = 0;
364
+ this._last = noop;
365
+ this._repeat = void 0;
366
+ this.target = byteArrayAllocate(256);
367
+ this.writeObject(value);
368
+ return this.getBuffer();
369
+ }
370
+ startDynamicVector() {
371
+ this.writeByte(CORE_TYPES.VectorDynamic);
372
+ return this;
373
+ }
374
+ endDynamicVector() {
375
+ this.writeByte(CORE_TYPES.None);
376
+ return this;
377
+ }
378
+ _writeCustom(value) {
379
+ const start = this.offset;
380
+ this.allocate(1);
381
+ this.offset++;
382
+ let edgeExt;
383
+ for (const ext of this.extensions.values()) {
384
+ if (ext.token === -1) {
385
+ edgeExt = ext;
386
+ continue;
387
+ }
388
+ ext.encode.call(this, value);
389
+ const processed = start + 1 < this.offset;
390
+ if (processed) {
391
+ const end = this.offset;
392
+ this.offset = start;
393
+ this.writeByte(ext.token);
394
+ this.offset = end;
395
+ return true;
396
+ }
397
+ }
398
+ this.offset = start;
399
+ if (edgeExt) {
400
+ edgeExt.encode.call(this, value);
401
+ return start < this.offset;
445
402
  }
403
+ return false;
446
404
  }
447
- assertConstructor(constructorId) {
448
- const byte = this.readByte();
449
- if (byte !== constructorId) {
450
- throw new Error(
451
- `Invalid constructor code, expected = ${CORE_TYPES[constructorId]}, got = ${CORE_TYPES[byte] || byte}, offset = ${this.offset - 1}`
452
- );
405
+ writeObject(value) {
406
+ if (value === void 0) return this;
407
+ const constructorId = coreType(value);
408
+ if (constructorId === CORE_TYPES.None) {
409
+ if (this._writeCustom(value)) {
410
+ return this;
411
+ }
412
+ throw new TypeError(`Invalid core type of ${value}`);
413
+ }
414
+ if (this._last === value) {
415
+ this.writeRepeat();
416
+ } else {
417
+ this._last = value;
418
+ this._repeat = void 0;
419
+ this.writeCore(constructorId, value);
453
420
  }
421
+ return this;
454
422
  }
455
- /**
456
- * Gets the byte array representing the current buffer as a whole.
457
- */
458
- getBuffer() {
459
- return this.target;
423
+ writeObjectGzip(value) {
424
+ const writer = new BinaryWriter();
425
+ writer.extensions = this.extensions;
426
+ writer.dictionary = this.dictionary;
427
+ writer.structures = this.structures;
428
+ writer.dictionaryExtended = this.dictionaryExtended;
429
+ writer.writeObject(value);
430
+ this.writeCore(CORE_TYPES.GZIP, writer.getBuffer());
431
+ return this;
460
432
  }
461
- readNull() {
462
- const value = this.readByte();
463
- if (value === CORE_TYPES.Null) {
464
- return null;
433
+ writeCore(constructorId, value) {
434
+ if (this.withGzip && SUPPORT_COMPRESSION.has(constructorId)) {
435
+ this.writeObjectGzip(value);
436
+ return this;
437
+ } else if (!NO_CONSTRUCTOR.has(constructorId)) {
438
+ this.writeByte(constructorId);
465
439
  }
466
- throw new Error(`Invalid boolean code ${value.toString(16)}`);
467
- }
468
- readLength() {
469
- const firstByte = this.readByte();
470
- if (firstByte === 254) {
471
- return this.readByte() | this.readByte() << 8 | this.readByte() << 16;
440
+ switch (constructorId) {
441
+ case CORE_TYPES.Structure: {
442
+ return this.writeStructure(value);
443
+ }
444
+ case CORE_TYPES.Binary: {
445
+ return this.writeBytes(value);
446
+ }
447
+ case CORE_TYPES.GZIP: {
448
+ return this.writeGzip(value);
449
+ }
450
+ case CORE_TYPES.DictIndex: {
451
+ return this.writeLength(value);
452
+ }
453
+ case CORE_TYPES.DictValue: {
454
+ return this.writeString(value);
455
+ }
456
+ case CORE_TYPES.BoolFalse: {
457
+ return this.writeBool(value);
458
+ }
459
+ case CORE_TYPES.BoolTrue: {
460
+ return this.writeBool(value);
461
+ }
462
+ case CORE_TYPES.Date: {
463
+ return this.writeDate(value);
464
+ }
465
+ case CORE_TYPES.Int32: {
466
+ return this.writeInt32(value);
467
+ }
468
+ case CORE_TYPES.Int16: {
469
+ return this.writeInt16(value);
470
+ }
471
+ case CORE_TYPES.Int8: {
472
+ return this.writeInt8(value);
473
+ }
474
+ case CORE_TYPES.UInt32: {
475
+ return this.writeInt32(value, false);
476
+ }
477
+ case CORE_TYPES.UInt16: {
478
+ return this.writeInt16(value, false);
479
+ }
480
+ case CORE_TYPES.UInt8: {
481
+ return this.writeInt8(value, false);
482
+ }
483
+ case CORE_TYPES.Double: {
484
+ return this.writeDouble(value);
485
+ }
486
+ case CORE_TYPES.Float: {
487
+ return this.writeFloat(value);
488
+ }
489
+ case CORE_TYPES.Null: {
490
+ return this.writeNull();
491
+ }
492
+ case CORE_TYPES.String: {
493
+ if (value.length <= 16) {
494
+ this.offset--;
495
+ return this.wireDictionary(value);
496
+ }
497
+ return this.writeString(value);
498
+ }
499
+ case CORE_TYPES.Vector: {
500
+ return this.writeVector(value);
501
+ }
502
+ case CORE_TYPES.Map: {
503
+ return this.writeMap(value);
504
+ }
472
505
  }
473
- return firstByte;
506
+ return this;
474
507
  }
475
- readAll() {
476
- const result = [];
477
- while (this.length > this.offset) {
478
- result.push(this.readObject());
508
+ writeRepeat() {
509
+ if (!this._repeat) {
510
+ this.writeByte(CORE_TYPES.Repeat);
511
+ this._repeat = { count: 0, offset: this.offset };
479
512
  }
480
- return result;
481
- }
482
- readBytes() {
483
- const length = this.readLength();
484
- this.assertRead(length);
485
- const bytes = this.target.subarray(this.offset, this.offset + length);
486
- this.offset += bytes.length;
487
- this._last = bytes;
488
- return bytes;
513
+ this.offset = this._repeat.offset;
514
+ this._repeat.count++;
515
+ this.writeLength(this._repeat.count);
516
+ return this;
489
517
  }
490
- /**
491
- * Reads encoded string.
492
- */
493
- readString() {
494
- const length = this.readLength();
495
- this.assertRead(length);
496
- const result = utf8Read(this.target, length, this.offset);
497
- this.offset += length;
498
- this._last = result;
499
- return result;
518
+ }
519
+
520
+ const CONSTRUCTOR_OPTIONAL = 1644261036;
521
+ const CONSTRUCTOR_OPTIONAL_NULL = 570519212;
522
+ const TYPE_HANDLERS = {
523
+ ["unknown"]: {
524
+ encode: function(value, key) {
525
+ this.writeObject(value[key]);
526
+ },
527
+ decode: function(result, key) {
528
+ result[key] = this.readObject();
529
+ },
530
+ estimatedSizeBytes: 0
531
+ },
532
+ [CORE_TYPES.Map]: {
533
+ encode: function(value, key) {
534
+ this.writeMap(value[key]);
535
+ },
536
+ decode: function(result, key) {
537
+ result[key] = this.readMap(false);
538
+ },
539
+ estimatedSizeBytes: 0
540
+ },
541
+ [CORE_TYPES.Binary]: {
542
+ encode: function(value, key) {
543
+ this.writeBytes(value[key]);
544
+ },
545
+ decode: function(result, key) {
546
+ result[key] = this.readBytes();
547
+ },
548
+ estimatedSizeBytes: 0
549
+ },
550
+ [CORE_TYPES.Vector]: {
551
+ encode: function(value, key) {
552
+ this.writeVector(value[key]);
553
+ },
554
+ decode: function(result, key) {
555
+ result[key] = this.readVector(false);
556
+ },
557
+ estimatedSizeBytes: 0
558
+ },
559
+ [Boolean.name]: {
560
+ encode: function(value, key) {
561
+ this.writeBool(value[key]);
562
+ },
563
+ decode: function(result, key) {
564
+ result[key] = this.readBool();
565
+ },
566
+ estimatedSizeBytes: 1
567
+ },
568
+ [CORE_TYPES.Int8]: {
569
+ encode: function(value, key) {
570
+ this.writeInt8(value[key], true);
571
+ },
572
+ decode: function(result, key) {
573
+ result[key] = this.readInt8(true);
574
+ },
575
+ estimatedSizeBytes: 1
576
+ },
577
+ [CORE_TYPES.Int16]: {
578
+ encode: function(value, key) {
579
+ this.writeInt16(value[key], true);
580
+ },
581
+ decode: function(result, key) {
582
+ result[key] = this.readInt16(true);
583
+ },
584
+ estimatedSizeBytes: 2
585
+ },
586
+ [CORE_TYPES.Int32]: {
587
+ encode: function(value, key) {
588
+ this.writeInt32(value[key], true);
589
+ },
590
+ decode: function(result, key) {
591
+ result[key] = this.readInt32(true);
592
+ },
593
+ estimatedSizeBytes: 4
594
+ },
595
+ [CORE_TYPES.UInt8]: {
596
+ encode: function(value, key) {
597
+ this.writeInt8(value[key], false);
598
+ },
599
+ decode: function(result, key) {
600
+ result[key] = this.readInt8(false);
601
+ },
602
+ estimatedSizeBytes: 1
603
+ },
604
+ [CORE_TYPES.UInt16]: {
605
+ encode: function(value, key) {
606
+ this.writeInt16(value[key], false);
607
+ },
608
+ decode: function(result, key) {
609
+ result[key] = this.readInt16(false);
610
+ },
611
+ estimatedSizeBytes: 2
612
+ },
613
+ [CORE_TYPES.UInt32]: {
614
+ encode: function(value, key) {
615
+ this.writeInt32(value[key], false);
616
+ },
617
+ decode: function(result, key) {
618
+ result[key] = this.readInt32(false);
619
+ },
620
+ estimatedSizeBytes: 4
621
+ },
622
+ [CORE_TYPES.Double]: {
623
+ encode: function(value, key) {
624
+ this.writeDouble(value[key]);
625
+ },
626
+ decode: function(result, key) {
627
+ result[key] = this.readDouble();
628
+ },
629
+ estimatedSizeBytes: 8
630
+ },
631
+ [CORE_TYPES.Date]: {
632
+ encode: function(value, key) {
633
+ this.writeDate(value[key]);
634
+ },
635
+ decode: function(result, key) {
636
+ result[key] = this.readDate();
637
+ },
638
+ estimatedSizeBytes: 8
639
+ },
640
+ [CORE_TYPES.String]: {
641
+ encode: function(value, key) {
642
+ this.writeString(value[key]);
643
+ },
644
+ decode: function(result, key) {
645
+ result[key] = this.readString();
646
+ },
647
+ estimatedSizeBytes: 0
500
648
  }
501
- /**
502
- * Reads a boolean value.
503
- */
504
- readBool() {
505
- const value = this.readByte();
506
- if (value === CORE_TYPES.BoolTrue) {
507
- return true;
508
- } else if (value === CORE_TYPES.BoolFalse) {
509
- return false;
649
+ };
650
+ TYPE_HANDLERS[Number.name] = TYPE_HANDLERS[CORE_TYPES.Double];
651
+ TYPE_HANDLERS[String.name] = TYPE_HANDLERS[CORE_TYPES.String];
652
+ TYPE_HANDLERS[Object.name] = TYPE_HANDLERS[CORE_TYPES.Map];
653
+ TYPE_HANDLERS[Uint8Array.name] = TYPE_HANDLERS[CORE_TYPES.Binary];
654
+ TYPE_HANDLERS[Array.name] = TYPE_HANDLERS[CORE_TYPES.Vector];
655
+ TYPE_HANDLERS[Date.name] = TYPE_HANDLERS[CORE_TYPES.Date];
656
+ function compileStructure(name, version, properties, checksum) {
657
+ const encodeFns = [];
658
+ const decodeFns = [];
659
+ const structures = [];
660
+ const structureId = toolkit.crc32(name) >>> 0;
661
+ let estimatedSizeBytes = 1;
662
+ encodeFns.push(function() {
663
+ this.writeByte(version);
664
+ });
665
+ decodeFns.push(function() {
666
+ const ver = this.readByte();
667
+ toolkit.assert.ok(
668
+ version === ver,
669
+ `Structure ${structureId} version mismatch: expected ${version}, got ${ver}`
670
+ );
671
+ });
672
+ const entries = Object.entries(properties);
673
+ const entriesLength = entries.length;
674
+ for (let i = 0; i < entriesLength; i++) {
675
+ const [key, prop] = entries[i];
676
+ const isRequired = prop.required === true;
677
+ const isArray = Array.isArray(prop.type);
678
+ const propType = Array.isArray(prop.type) ? prop.type[0] : prop.type;
679
+ if (isStructureType(propType)) {
680
+ encodeFns.push(
681
+ createStructureEncoder(key, propType, isRequired, isArray)
682
+ );
683
+ decodeFns.push(createStructureDecoder(key, isRequired, isArray));
684
+ estimatedSizeBytes += propType.estimatedSizeBytes;
685
+ structures.push(propType);
686
+ continue;
687
+ }
688
+ const typeName = propType?.name || (propType === null ? "unknown" : propType);
689
+ const handler = TYPE_HANDLERS[typeName];
690
+ if (handler) {
691
+ encodeFns.push(
692
+ createBoundEncoder(handler.encode, key, isRequired, isArray)
693
+ );
694
+ decodeFns.push(
695
+ createBoundDecoder(handler.decode, key, isRequired, isArray)
696
+ );
697
+ estimatedSizeBytes += handler.estimatedSizeBytes;
510
698
  } else {
511
- throw new Error(`Invalid boolean code ${value.toString(16)}`);
699
+ throw new Error(`Unsupported property type: ${typeName || "unknown"}`);
700
+ }
701
+ }
702
+ if (checksum) {
703
+ estimatedSizeBytes += 4;
704
+ encodeFns.push(function() {
705
+ this.writeChecksum(false);
706
+ });
707
+ decodeFns.push(function() {
708
+ this.readChecksum(false);
709
+ });
710
+ }
711
+ const compiled = {
712
+ id: structureId,
713
+ encodeFns,
714
+ decodeFns,
715
+ structures,
716
+ estimatedSizeBytes
717
+ };
718
+ return compiled;
719
+ }
720
+ function isStructureType(type) {
721
+ return type?.prototype && Structure.prototype.isPrototypeOf(type.prototype);
722
+ }
723
+ function createStructureEncoder(key, StructureCtor, isRequired, isArray) {
724
+ return function(value) {
725
+ const hasValue = value[key] !== void 0 && value[key] !== null;
726
+ if (!hasValue) {
727
+ toolkit.assert.ok(!isRequired, `Required property "${key}" is missing or null`);
728
+ if (value[key] === null) {
729
+ this.writeInt32(CONSTRUCTOR_OPTIONAL_NULL);
730
+ } else {
731
+ this.writeInt32(CONSTRUCTOR_OPTIONAL);
732
+ }
733
+ } else if (isArray) {
734
+ const arr = value[key];
735
+ toolkit.assert.array(arr, `Expected property "${key}" to be array.`);
736
+ this.writeLength(arr.length);
737
+ for (let idx = 0; idx < arr.length; idx++) {
738
+ this.writeStructure(
739
+ arr[idx] instanceof Structure ? arr[idx] : new StructureCtor(arr[idx])
740
+ );
741
+ }
742
+ } else {
743
+ this.writeStructure(
744
+ value[key] instanceof Structure ? value[key] : new StructureCtor(value[key])
745
+ );
512
746
  }
513
- }
514
- /**
515
- * Reads and converts Unix time
516
- * into a Javascript {Date} object.
517
- */
518
- readDate() {
519
- const value = this.readDouble();
520
- return new Date(value);
521
- }
522
- /**
523
- * Reads a object.
524
- */
525
- readObject() {
526
- if (this._repeat) {
527
- if (this._repeat.pool > 0) {
528
- --this._repeat.pool;
529
- return this._repeat.value;
747
+ };
748
+ }
749
+ function createStructureDecoder(key, isRequired, isArray) {
750
+ return function(result) {
751
+ let shouldRead = true;
752
+ if (!isRequired) {
753
+ shouldRead = !readMaybeInt32(this, CONSTRUCTOR_OPTIONAL);
754
+ if (shouldRead && readMaybeInt32(this, CONSTRUCTOR_OPTIONAL_NULL)) {
755
+ result[key] = null;
756
+ return;
757
+ }
758
+ }
759
+ if (shouldRead) {
760
+ if (isArray) {
761
+ const length = this.readLength();
762
+ const arrResult = Array.from({ length });
763
+ for (let idx = 0; idx < length; idx++) {
764
+ arrResult[idx] = this.readStructure(false);
765
+ }
766
+ result[key] = arrResult;
530
767
  } else {
531
- this._repeat = void 0;
768
+ result[key] = this.readStructure(false);
532
769
  }
533
770
  }
534
- const constructorId = this.readByte();
535
- const ext = this.extensions.get(constructorId);
536
- let value;
537
- if (ext) {
538
- value = ext.decode.call(this);
539
- } else {
540
- value = this._lastObject = this.readCore(constructorId);
771
+ };
772
+ }
773
+ function readMaybeInt32(reader, expectedValue) {
774
+ let result = false;
775
+ if (reader.length >= reader.offset + 4) {
776
+ result = reader.readInt32() === expectedValue;
777
+ if (!result) {
778
+ reader.offset -= 4;
541
779
  }
542
- return value;
543
- }
544
- readObjectGzip() {
545
- const bytes = this.readGzip();
546
- const reader = new BinaryReader(bytes);
547
- reader.extensions = this.extensions;
548
- reader.dictionary = this.dictionary;
549
- reader.dictionaryExtended = this.dictionaryExtended;
550
- return reader.readObject();
551
- }
552
- readGzip() {
553
- return pako__default.inflateRaw(this.readBytes());
554
780
  }
555
- readCore(constructorId) {
556
- switch (constructorId) {
557
- case CORE_TYPES.None:
558
- return this.readObject();
559
- case CORE_TYPES.GZIP:
560
- return this.readObjectGzip();
561
- case CORE_TYPES.BoolTrue:
562
- return true;
563
- case CORE_TYPES.BoolFalse:
564
- return false;
565
- case CORE_TYPES.Vector:
566
- return this.readVector(false);
567
- case CORE_TYPES.VectorDynamic:
568
- return this.readVectorDynamic(false);
569
- case CORE_TYPES.Null:
570
- return null;
571
- case CORE_TYPES.Binary:
572
- return this.readBytes();
573
- case CORE_TYPES.String:
574
- return this.readString();
575
- case CORE_TYPES.Date:
576
- return this.readDate();
577
- case CORE_TYPES.Int32:
578
- return this.readInt32();
579
- case CORE_TYPES.Int16:
580
- return this.readInt16();
581
- case CORE_TYPES.Int8:
582
- return this.readInt8();
583
- case CORE_TYPES.UInt32:
584
- return this.readInt32(false);
585
- case CORE_TYPES.UInt16:
586
- return this.readInt16(false);
587
- case CORE_TYPES.UInt8:
588
- return this.readInt8(false);
589
- case CORE_TYPES.Float:
590
- return this.readFloat();
591
- case CORE_TYPES.Double:
592
- return this.readDouble();
593
- case CORE_TYPES.Map:
594
- return this.readMap(false);
595
- case CORE_TYPES.Checksum:
596
- return void this.readChecksum(false);
597
- case CORE_TYPES.DictIndex: {
598
- const idx = this.readLength();
599
- return this.getDictionaryValue(idx);
781
+ return result;
782
+ }
783
+ function createBoundEncoder(encodeFn, key, isRequired, isArray) {
784
+ return function(value) {
785
+ const hasValue = value[key] !== void 0 && value[key] !== null;
786
+ if (!hasValue) {
787
+ toolkit.assert.ok(!isRequired, `Required property "${key}" is missing or null`);
788
+ if (value[key] === null) {
789
+ this.writeInt32(CONSTRUCTOR_OPTIONAL_NULL);
790
+ } else {
791
+ this.writeInt32(CONSTRUCTOR_OPTIONAL);
600
792
  }
601
- case CORE_TYPES.DictValue: {
602
- const value = this.readString();
603
- this.dictionaryExtended.maybeInsert(value);
604
- return value;
793
+ } else if (isArray) {
794
+ const arr = value[key];
795
+ toolkit.assert.array(arr, `Expected property "${key}" to be array.`);
796
+ this.writeLength(arr.length);
797
+ for (let idx = 0; idx < arr.length; idx++) {
798
+ encodeFn.call(this, arr, idx);
605
799
  }
606
- case CORE_TYPES.Repeat: {
607
- const size = this.readLength();
608
- this._repeat = { pool: size - 1, value: this._lastObject };
609
- return this._lastObject;
800
+ } else {
801
+ encodeFn.call(this, value, key);
802
+ }
803
+ };
804
+ }
805
+ function createBoundDecoder(decodeFn, key, isRequired, isArray) {
806
+ return function(result) {
807
+ let shouldRead = true;
808
+ if (!isRequired) {
809
+ shouldRead = !readMaybeInt32(this, CONSTRUCTOR_OPTIONAL);
810
+ if (shouldRead && readMaybeInt32(this, CONSTRUCTOR_OPTIONAL_NULL)) {
811
+ result[key] = null;
812
+ return;
813
+ }
814
+ }
815
+ if (shouldRead) {
816
+ if (isArray) {
817
+ const length = this.readLength();
818
+ const arrResult = Array.from({ length });
819
+ for (let idx = 0; idx < length; idx++) {
820
+ decodeFn.call(this, arrResult, idx);
821
+ }
822
+ result[key] = arrResult;
823
+ } else {
824
+ decodeFn.call(this, result, key);
610
825
  }
611
826
  }
612
- throw new Error(
613
- `Invalid constructor = ${CORE_TYPES[constructorId] || constructorId}, offset = ${this.offset - 1}`
614
- );
827
+ };
828
+ }
829
+ function defineStructure({
830
+ name,
831
+ properties,
832
+ version,
833
+ checksum = false
834
+ }) {
835
+ const compiled = compileStructure(name, version, properties, checksum);
836
+ return class DefinedStructure extends Structure {
837
+ static estimatedSizeBytes = compiled.estimatedSizeBytes;
838
+ static structures = compiled.structures;
839
+ static extension = {
840
+ token: compiled.id,
841
+ encode(value) {
842
+ const fns = compiled.encodeFns;
843
+ const length = fns.length;
844
+ for (let i = 0; i < length; i++) {
845
+ fns[i].call(this, value);
846
+ }
847
+ },
848
+ decode() {
849
+ const result = {};
850
+ const fns = compiled.decodeFns;
851
+ const length = fns.length;
852
+ for (let i = 0; i < length; i++) {
853
+ fns[i].call(this, result);
854
+ }
855
+ return result;
856
+ }
857
+ };
858
+ };
859
+ }
860
+ class Structure {
861
+ value;
862
+ constructor(value) {
863
+ this.value = value;
864
+ }
865
+ toBuffer(options) {
866
+ const ctor = this.constructor;
867
+ const writer = new BinaryWriter(options);
868
+ ctor.extension.encode.call(writer, this.value);
869
+ return writer.getBuffer();
870
+ }
871
+ static fromBuffer(buffer, options = {}) {
872
+ const reader = new BinaryReader(buffer, {
873
+ ...options,
874
+ structures: options.structures ? this.structures.concat(options.structures) : this.structures
875
+ });
876
+ return this.extension.decode.call(reader);
877
+ }
878
+ static estimatedSizeBytes = -1;
879
+ static structures = [];
880
+ static extension = {
881
+ token: CORE_TYPES.Binary,
882
+ encode: toolkit.noop,
883
+ decode: toolkit.noop
884
+ };
885
+ }
886
+
887
+ const encoder = new TextEncoder();
888
+ const decoder = new TextDecoder();
889
+ const fromCharCode = String.fromCharCode;
890
+ const int32 = new Int32Array(2);
891
+ const float32 = new Float32Array(int32.buffer);
892
+ const float64 = new Float64Array(int32.buffer);
893
+ function byteArrayAllocate(length) {
894
+ return new Uint8Array(length);
895
+ }
896
+ function coreType(value) {
897
+ if (value instanceof Structure) {
898
+ return CORE_TYPES.Structure;
899
+ } else if (value instanceof Uint8Array) {
900
+ return CORE_TYPES.Binary;
615
901
  }
616
- getDictionaryValue(index) {
617
- let value = null;
618
- if (this.dictionary) {
619
- value = this.dictionary.getValue(index);
902
+ switch (typeof value) {
903
+ case "string": {
904
+ return CORE_TYPES.String;
620
905
  }
621
- if (value === null) {
622
- value = this.dictionaryExtended.getValue(index);
906
+ case "boolean": {
907
+ return value ? CORE_TYPES.BoolTrue : CORE_TYPES.BoolFalse;
623
908
  }
624
- return value;
625
- }
626
- readDictionary() {
627
- const constructorId = this.readByte();
628
- let key = null;
629
- switch (constructorId) {
630
- case CORE_TYPES.DictIndex: {
631
- const idx = this.readLength();
632
- key = this.getDictionaryValue(idx);
633
- break;
909
+ case "number": {
910
+ if (Math.trunc(value) === value) {
911
+ if (value >= 0 && value <= 255) {
912
+ return CORE_TYPES.UInt8;
913
+ } else if (value >= 0 && value <= 65535) {
914
+ return CORE_TYPES.UInt16;
915
+ } else if (value >= 0 && value <= 4294967295) {
916
+ return CORE_TYPES.UInt32;
917
+ } else if (value >= -128 && value <= 127) {
918
+ return CORE_TYPES.Int8;
919
+ } else if (value >= -32768 && value <= 32767) {
920
+ return CORE_TYPES.Int16;
921
+ } else if (value >= -2147483648 && value <= 2147483647) {
922
+ return CORE_TYPES.Int32;
923
+ }
634
924
  }
635
- case CORE_TYPES.DictValue: {
636
- key = this.readString();
637
- this.dictionaryExtended.maybeInsert(key);
638
- break;
925
+ return CORE_TYPES.Double;
926
+ }
927
+ case "object": {
928
+ if (value === null) return CORE_TYPES.Null;
929
+ if (value instanceof Date) {
930
+ return CORE_TYPES.Date;
639
931
  }
640
- case CORE_TYPES.None: {
641
- key = null;
642
- break;
932
+ if (Array.isArray(value)) {
933
+ return CORE_TYPES.Vector;
643
934
  }
644
- default: {
645
- this.seek(-1);
935
+ if (toolkit.isPlainObject(value)) {
936
+ return CORE_TYPES.Map;
646
937
  }
647
938
  }
648
- return key;
649
939
  }
650
- readMap(checkConstructor = true) {
651
- if (checkConstructor) {
652
- this.assertConstructor(CORE_TYPES.Map);
940
+ return CORE_TYPES.None;
941
+ }
942
+ function utf8Read(target, length, offset) {
943
+ let result;
944
+ if (length < 16) {
945
+ if (result = utf8ReadShort(target, length, offset)) return result;
946
+ }
947
+ if (length > 64 && decoder)
948
+ return decoder.decode(target.subarray(offset, offset += length));
949
+ const end = offset + length;
950
+ const units = [];
951
+ result = "";
952
+ while (offset < end) {
953
+ const byte1 = target[offset++];
954
+ if ((byte1 & 128) === 0) {
955
+ units.push(byte1);
956
+ } else if ((byte1 & 224) === 192) {
957
+ const byte2 = target[offset++] & 63;
958
+ units.push((byte1 & 31) << 6 | byte2);
959
+ } else if ((byte1 & 240) === 224) {
960
+ const byte2 = target[offset++] & 63;
961
+ const byte3 = target[offset++] & 63;
962
+ units.push((byte1 & 31) << 12 | byte2 << 6 | byte3);
963
+ } else if ((byte1 & 248) === 240) {
964
+ const byte2 = target[offset++] & 63;
965
+ const byte3 = target[offset++] & 63;
966
+ const byte4 = target[offset++] & 63;
967
+ let unit = (byte1 & 7) << 18 | byte2 << 12 | byte3 << 6 | byte4;
968
+ if (unit > 65535) {
969
+ unit -= 65536;
970
+ units.push(unit >>> 10 & 1023 | 55296);
971
+ unit = 56320 | unit & 1023;
972
+ }
973
+ units.push(unit);
974
+ } else {
975
+ units.push(byte1);
653
976
  }
654
- const temp = {};
655
- let key = this.readDictionary();
656
- while (key !== null) {
657
- temp[key] = this.readObject();
658
- key = this.readDictionary();
977
+ if (units.length >= 4096) {
978
+ result += fromCharCode.apply(String, units);
979
+ units.length = 0;
659
980
  }
660
- return temp;
661
981
  }
662
- decode(value) {
663
- this.target = value;
664
- this._last = void 0;
665
- this._lastObject = void 0;
666
- this._repeat = void 0;
667
- this.offset = 0;
668
- this._checksumOffset = 0;
669
- this.length = value.length;
670
- return this.readObject();
982
+ if (units.length > 0) {
983
+ result += fromCharCode.apply(String, units);
671
984
  }
672
- /**
673
- * Reads a vector (a list) of objects.
674
- */
675
- readVector(checkConstructor = true) {
676
- if (checkConstructor) {
677
- this.assertConstructor(CORE_TYPES.Vector);
678
- }
679
- const count = this.readLength();
680
- const temp = [];
681
- for (let i = 0; i < count; i++) {
682
- temp.push(this.readObject());
985
+ return result;
986
+ }
987
+ function utf8ReadShort(target, length, offset) {
988
+ if (length < 4) {
989
+ if (length < 2) {
990
+ if (length === 0) return "";
991
+ else {
992
+ let a = target[offset++];
993
+ if ((a & 128) > 1) {
994
+ offset -= 1;
995
+ return;
996
+ }
997
+ return fromCharCode(a);
998
+ }
999
+ } else {
1000
+ let a = target[offset++];
1001
+ let b = target[offset++];
1002
+ if ((a & 128) > 0 || (b & 128) > 0) {
1003
+ offset -= 2;
1004
+ return;
1005
+ }
1006
+ if (length < 3) return fromCharCode(a, b);
1007
+ let c = target[offset++];
1008
+ if ((c & 128) > 0) {
1009
+ offset -= 3;
1010
+ return;
1011
+ }
1012
+ return fromCharCode(a, b, c);
683
1013
  }
684
- return temp;
685
- }
686
- /**
687
- * Reads a vector (a list) of objects.
688
- */
689
- readVectorDynamic(checkConstructor = true) {
690
- if (checkConstructor) {
691
- this.assertConstructor(CORE_TYPES.VectorDynamic);
1014
+ } else {
1015
+ let a = target[offset++];
1016
+ let b = target[offset++];
1017
+ let c = target[offset++];
1018
+ let d = target[offset++];
1019
+ if ((a & 128) > 0 || (b & 128) > 0 || (c & 128) > 0 || (d & 128) > 0) {
1020
+ offset -= 4;
1021
+ return;
692
1022
  }
693
- const temp = [];
694
- let complete = false;
695
- while (this.length > this.offset) {
696
- const constructorId = this.readByte();
697
- if (constructorId === CORE_TYPES.None) {
698
- complete = true;
699
- break;
1023
+ if (length < 6) {
1024
+ if (length === 4) return fromCharCode(a, b, c, d);
1025
+ else {
1026
+ let e = target[offset++];
1027
+ if ((e & 128) > 0) {
1028
+ offset -= 5;
1029
+ return;
1030
+ }
1031
+ return fromCharCode(a, b, c, d, e);
700
1032
  }
701
- const ext = this.extensions.get(constructorId);
702
- let value;
703
- if (ext) {
704
- value = ext.decode.call(this);
1033
+ } else if (length < 8) {
1034
+ let e = target[offset++];
1035
+ let f = target[offset++];
1036
+ if ((e & 128) > 0 || (f & 128) > 0) {
1037
+ offset -= 6;
1038
+ return;
1039
+ }
1040
+ if (length < 7) return fromCharCode(a, b, c, d, e, f);
1041
+ let g = target[offset++];
1042
+ if ((g & 128) > 0) {
1043
+ offset -= 7;
1044
+ return;
1045
+ }
1046
+ return fromCharCode(a, b, c, d, e, f, g);
1047
+ } else {
1048
+ let e = target[offset++];
1049
+ let f = target[offset++];
1050
+ let g = target[offset++];
1051
+ let h = target[offset++];
1052
+ if ((e & 128) > 0 || (f & 128) > 0 || (g & 128) > 0 || (h & 128) > 0) {
1053
+ offset -= 8;
1054
+ return;
1055
+ }
1056
+ if (length < 10) {
1057
+ if (length === 8) return fromCharCode(a, b, c, d, e, f, g, h);
1058
+ else {
1059
+ let i = target[offset++];
1060
+ if ((i & 128) > 0) {
1061
+ offset -= 9;
1062
+ return;
1063
+ }
1064
+ return fromCharCode(a, b, c, d, e, f, g, h, i);
1065
+ }
1066
+ } else if (length < 12) {
1067
+ let i = target[offset++];
1068
+ let j = target[offset++];
1069
+ if ((i & 128) > 0 || (j & 128) > 0) {
1070
+ offset -= 10;
1071
+ return;
1072
+ }
1073
+ if (length < 11) return fromCharCode(a, b, c, d, e, f, g, h, i, j);
1074
+ let k = target[offset++];
1075
+ if ((k & 128) > 0) {
1076
+ offset -= 11;
1077
+ return;
1078
+ }
1079
+ return fromCharCode(a, b, c, d, e, f, g, h, i, j, k);
705
1080
  } else {
706
- value = this.readCore(constructorId);
1081
+ let i = target[offset++];
1082
+ let j = target[offset++];
1083
+ let k = target[offset++];
1084
+ let l = target[offset++];
1085
+ if ((i & 128) > 0 || (j & 128) > 0 || (k & 128) > 0 || (l & 128) > 0) {
1086
+ offset -= 12;
1087
+ return;
1088
+ }
1089
+ if (length < 14) {
1090
+ if (length === 12)
1091
+ return fromCharCode(a, b, c, d, e, f, g, h, i, j, k, l);
1092
+ else {
1093
+ let m = target[offset++];
1094
+ if ((m & 128) > 0) {
1095
+ offset -= 13;
1096
+ return;
1097
+ }
1098
+ return fromCharCode(a, b, c, d, e, f, g, h, i, j, k, l, m);
1099
+ }
1100
+ } else {
1101
+ let m = target[offset++];
1102
+ let n = target[offset++];
1103
+ if ((m & 128) > 0 || (n & 128) > 0) {
1104
+ offset -= 14;
1105
+ return;
1106
+ }
1107
+ if (length < 15)
1108
+ return fromCharCode(a, b, c, d, e, f, g, h, i, j, k, l, m, n);
1109
+ let o = target[offset++];
1110
+ if ((o & 128) > 0) {
1111
+ offset -= 15;
1112
+ return;
1113
+ }
1114
+ return fromCharCode(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o);
1115
+ }
707
1116
  }
708
- temp.push(value);
709
- }
710
- if (!complete) {
711
- const err = new Error(`DynamicVector incomplete.`);
712
- err.incomplete = true;
713
- Error.captureStackTrace(err, this.readDictionary);
714
- throw err;
715
1117
  }
716
- this._last = temp;
717
- return temp;
718
1118
  }
719
- readChecksum(checkConstructor = true) {
720
- const offset = this.offset;
721
- if (checkConstructor) {
722
- this.assertConstructor(CORE_TYPES.Checksum);
723
- }
724
- const bytes = this.target.slice(this._checksumOffset, offset);
725
- const checksum = this.readLength();
726
- let sum = 0;
727
- for (const val of bytes) {
728
- sum += val;
729
- }
730
- if (checksum - sum !== 0) {
731
- throw new Error(
732
- `Invalid checksum = ${checksum - sum}, offset = ${offset}`
733
- );
1119
+ }
1120
+ const utf8Write = function(target, value, offset) {
1121
+ return value.length < 64 ? utf8WriteShort(target, value, offset) : encoder.encodeInto(value, target.subarray(offset)).written;
1122
+ };
1123
+ const utf8WriteShort = (target, value, offset) => {
1124
+ let i, c1, c2, strPosition = offset;
1125
+ const strLength = value.length;
1126
+ for (i = 0; i < strLength; i++) {
1127
+ c1 = value.charCodeAt(i);
1128
+ if (c1 < 128) {
1129
+ target[strPosition++] = c1;
1130
+ } else if (c1 < 2048) {
1131
+ target[strPosition++] = c1 >> 6 | 192;
1132
+ target[strPosition++] = c1 & 63 | 128;
1133
+ } else if ((c1 & 64512) === 55296 && ((c2 = value.charCodeAt(i + 1)) & 64512) === 56320) {
1134
+ c1 = 65536 + ((c1 & 1023) << 10) + (c2 & 1023);
1135
+ i++;
1136
+ target[strPosition++] = c1 >> 18 | 240;
1137
+ target[strPosition++] = c1 >> 12 & 63 | 128;
1138
+ target[strPosition++] = c1 >> 6 & 63 | 128;
1139
+ target[strPosition++] = c1 & 63 | 128;
1140
+ } else {
1141
+ target[strPosition++] = c1 >> 12 | 224;
1142
+ target[strPosition++] = c1 >> 6 & 63 | 128;
1143
+ target[strPosition++] = c1 & 63 | 128;
734
1144
  }
735
- this._checksumOffset = this.offset;
736
- }
737
- /**
738
- * Tells the current position on the stream.
739
- */
740
- tellPosition() {
741
- return this.offset;
742
- }
743
- /**
744
- * Sets the current position on the stream.
745
- */
746
- setPosition(position) {
747
- this.offset = position;
748
- }
749
- /**
750
- * Seeks the stream position given an offset from the current position.
751
- * The offset may be negative.
752
- */
753
- seek(offset) {
754
- this.offset += offset;
755
1145
  }
756
- }
1146
+ return strPosition - offset;
1147
+ };
757
1148
 
758
- const noop = Symbol();
759
- const NO_CONSTRUCTOR = /* @__PURE__ */ new Set([
760
- CORE_TYPES.BoolFalse,
761
- CORE_TYPES.BoolTrue,
762
- CORE_TYPES.Null
763
- ]);
764
- const SUPPORT_COMPRESSION = /* @__PURE__ */ new Set([CORE_TYPES.String]);
765
- class BinaryWriter {
766
- withGzip;
1149
+ const NOOP_DICTIONARY = new Dictionary();
1150
+ class BinaryReader {
767
1151
  target;
1152
+ _last;
1153
+ _lastObject;
768
1154
  dictionary;
769
1155
  dictionaryExtended;
770
1156
  extensions;
771
- _last = noop;
772
- _checksumOffset;
1157
+ structures;
773
1158
  _repeat;
1159
+ _checksumOffset;
774
1160
  offset;
775
- constructor(options) {
1161
+ length;
1162
+ /**
1163
+ * Small utility class to read binary data.
1164
+ */
1165
+ constructor(data, {
1166
+ dictionary = NOOP_DICTIONARY,
1167
+ extensions,
1168
+ structures
1169
+ } = {}) {
1170
+ this.target = data;
776
1171
  this.offset = 0;
777
1172
  this._checksumOffset = 0;
1173
+ this.length = data.length;
778
1174
  this.extensions = /* @__PURE__ */ new Map();
779
- this.withGzip = !!options && !!options.gzip;
780
- this.target = byteArrayAllocate(8192);
781
- if (options && options.extensions) {
782
- options.extensions.forEach((ext) => {
1175
+ this.structures = /* @__PURE__ */ new Map();
1176
+ if (extensions) {
1177
+ for (const ext of extensions) {
783
1178
  this.extensions.set(ext.token, ext);
784
- });
1179
+ }
1180
+ }
1181
+ if (structures) {
1182
+ for (const struct of structures) {
1183
+ this.structures.set(struct.extension.token, struct);
1184
+ }
785
1185
  }
786
- if (!options) {
787
- this.dictionary = new Dictionary();
788
- } else if (options.dictionary instanceof Dictionary) {
789
- this.dictionary = options.dictionary;
790
- } else if (Array.isArray(options.dictionary)) {
791
- this.dictionary = new Dictionary(options.dictionary);
1186
+ if (Array.isArray(dictionary)) {
1187
+ this.dictionary = new Dictionary(dictionary);
792
1188
  } else {
793
- this.dictionary = new Dictionary();
1189
+ this.dictionary = dictionary;
794
1190
  }
795
1191
  this.dictionaryExtended = new Dictionary(void 0, this.dictionary.size);
796
1192
  }
797
- allocate(size) {
798
- const position = this.offset + size;
799
- if (this.safeEnd < position) {
800
- this.makeRoom(position);
1193
+ readByte() {
1194
+ this.assertRead(1);
1195
+ this._last = this.target[this.offset++];
1196
+ return this._last;
1197
+ }
1198
+ readInt32(signed = true) {
1199
+ this.assertRead(4);
1200
+ this._last = this.target[this.offset++] | this.target[this.offset++] << 8 | this.target[this.offset++] << 16 | this.target[this.offset++] << 24;
1201
+ if (!signed) {
1202
+ this._last = this._last >>> 0;
801
1203
  }
802
- return this;
1204
+ return this._last;
803
1205
  }
804
- makeRoom(end) {
805
- let start = 0;
806
- let newSize = 0;
807
- let target = this.target;
808
- if (end > 16777216) {
809
- if (end - start > MAX_BUFFER_SIZE)
810
- throw new Error(
811
- "Packed buffer would be larger than maximum buffer size"
812
- );
813
- newSize = Math.min(
814
- MAX_BUFFER_SIZE,
815
- Math.round(
816
- Math.max((end - start) * (end > 67108864 ? 1.25 : 2), 4194304) / 4096
817
- ) * 4096
818
- );
819
- } else {
820
- newSize = (Math.max(end - start << 2, target.length - 1) >> 12) + 1 << 12;
1206
+ readInt16(signed = true) {
1207
+ this.assertRead(2);
1208
+ this._last = this.target[this.offset++] | this.target[this.offset++] << 8;
1209
+ if (signed) {
1210
+ this._last = this._last << 16 >> 16;
821
1211
  }
822
- const newBuffer = byteArrayAllocate(newSize);
823
- end = Math.min(end, target.length);
824
- newBuffer.set(target.slice(start, end));
825
- this.target = newBuffer;
1212
+ return this._last;
826
1213
  }
827
- get safeEnd() {
828
- return this.target.length - 10;
1214
+ readInt8(signed = true) {
1215
+ this.assertRead(1);
1216
+ this._last = this.target[this.offset++];
1217
+ if (signed) {
1218
+ this._last = this._last << 24 >> 24;
1219
+ }
1220
+ return this._last;
829
1221
  }
830
- getBuffer() {
831
- return this.target.subarray(0, this.offset);
1222
+ /**
1223
+ * Reads a real floating point (4 bytes) value.
1224
+ * @returns {number}
1225
+ */
1226
+ readFloat() {
1227
+ this.assertRead(4);
1228
+ int32[0] = this.readInt32();
1229
+ this._last = float32[0];
1230
+ return this._last;
832
1231
  }
833
- writeByte(value) {
834
- this.allocate(1);
835
- this.target[this.offset++] = value;
836
- return this;
1232
+ /**
1233
+ * Reads a real floating point (8 bytes) value.
1234
+ * @returns {BigInteger}
1235
+ */
1236
+ readDouble() {
1237
+ this.assertRead(8);
1238
+ int32[0] = this.readInt32();
1239
+ int32[1] = this.readInt32();
1240
+ this._last = float64[0];
1241
+ return this._last;
837
1242
  }
838
- writeBool(value) {
839
- if (value) {
840
- this.writeByte(CORE_TYPES.BoolTrue);
841
- } else {
842
- this.writeByte(CORE_TYPES.BoolFalse);
1243
+ /**
1244
+ * Throws error if provided length cannot be read from buffer
1245
+ * @param length {number}
1246
+ */
1247
+ assertRead(length) {
1248
+ if (this.length < this.offset + +length) {
1249
+ const left = this.target.length - this.offset;
1250
+ const result = this.target.subarray(this.offset, this.offset + left);
1251
+ const err = new Error(
1252
+ `No more data left to read (need ${length}, got ${left}: ${result}); last read ${this._last}`
1253
+ );
1254
+ err.incomplete = true;
1255
+ Error.captureStackTrace(err, this.assertRead);
1256
+ throw err;
843
1257
  }
844
- return this;
845
1258
  }
846
- writeNull() {
847
- this.writeByte(CORE_TYPES.Null);
848
- return this;
1259
+ assertConstructor(constructorId) {
1260
+ const byte = this.readByte();
1261
+ if (byte !== constructorId) {
1262
+ throw new Error(
1263
+ `Invalid constructor code, expected = ${CORE_TYPES[constructorId]}, got = ${CORE_TYPES[byte] || byte}, offset = ${this.offset - 1}`
1264
+ );
1265
+ }
849
1266
  }
850
- writeInt32(value, signed = true) {
851
- this.allocate(4);
852
- if (signed) {
853
- this.target[this.offset++] = value;
854
- this.target[this.offset++] = value >> 8;
855
- this.target[this.offset++] = value >> 16;
856
- this.target[this.offset++] = value >> 24;
857
- } else {
858
- this.target[this.offset++] = value;
859
- this.target[this.offset++] = value >> 8;
860
- this.target[this.offset++] = value >> 16;
861
- this.target[this.offset++] = value >> 24;
1267
+ /**
1268
+ * Gets the byte array representing the current buffer as a whole.
1269
+ */
1270
+ getBuffer() {
1271
+ return this.target;
1272
+ }
1273
+ readNull() {
1274
+ const value = this.readByte();
1275
+ if (value === CORE_TYPES.Null) {
1276
+ return null;
862
1277
  }
863
- return this;
1278
+ throw new Error(`Invalid boolean code ${value.toString(16)}`);
864
1279
  }
865
- writeInt16(value, signed = true) {
866
- this.allocate(2);
867
- if (signed) {
868
- this.target[this.offset++] = value;
869
- this.target[this.offset++] = value >> 8;
870
- } else {
871
- this.target[this.offset++] = value;
872
- this.target[this.offset++] = value >> 8;
1280
+ readLength() {
1281
+ const firstByte = this.readByte();
1282
+ if (firstByte === 254) {
1283
+ return this.readByte() | this.readByte() << 8 | this.readByte() << 16;
873
1284
  }
874
- return this;
1285
+ return firstByte;
875
1286
  }
876
- writeInt8(value, signed = true) {
877
- this.allocate(1);
878
- this.target[this.offset++] = value;
879
- return this;
1287
+ readAll() {
1288
+ const result = [];
1289
+ while (this.length > this.offset) {
1290
+ result.push(this.readObject());
1291
+ }
1292
+ return result;
880
1293
  }
881
- writeFloat(value) {
882
- this.allocate(4);
883
- float32[0] = value;
884
- this.writeInt32(int32[0]);
885
- return this;
1294
+ readBytes() {
1295
+ const length = this.readLength();
1296
+ this.assertRead(length);
1297
+ const bytes = this.target.subarray(this.offset, this.offset + length);
1298
+ this.offset += bytes.length;
1299
+ this._last = bytes;
1300
+ return bytes;
886
1301
  }
887
- writeDouble(value) {
888
- this.allocate(8);
889
- float64[0] = value;
890
- this.writeInt32(int32[0], false);
891
- this.writeInt32(int32[1], false);
892
- return this;
1302
+ /**
1303
+ * Reads encoded string.
1304
+ */
1305
+ readString() {
1306
+ const length = this.readLength();
1307
+ this.assertRead(length);
1308
+ const result = utf8Read(this.target, length, this.offset);
1309
+ this.offset += length;
1310
+ this._last = result;
1311
+ return result;
893
1312
  }
894
- writeDate(value) {
895
- let timestamp = 0;
896
- if (value instanceof Date) {
897
- timestamp = value.getTime();
898
- } else if (typeof value === "number") {
899
- timestamp = value;
1313
+ /**
1314
+ * Reads a boolean value.
1315
+ */
1316
+ readBool() {
1317
+ const value = this.readByte();
1318
+ if (value === CORE_TYPES.BoolTrue) {
1319
+ return true;
1320
+ } else if (value === CORE_TYPES.BoolFalse) {
1321
+ return false;
1322
+ } else {
1323
+ throw new Error(`Invalid boolean code ${value.toString(16)}`);
900
1324
  }
901
- this.writeDouble(timestamp);
902
- return this;
903
1325
  }
904
- writeString(value) {
905
- const strLength = value.length;
906
- let start = this.offset;
907
- let require = strLength << 2;
908
- if (require < 254) {
909
- require += 1;
910
- this.offset += 1;
911
- } else {
912
- require += 4;
913
- this.offset += 4;
1326
+ /**
1327
+ * Reads and converts Unix time
1328
+ * into a Javascript {Date} object.
1329
+ */
1330
+ readDate() {
1331
+ const value = this.readDouble();
1332
+ return new Date(value);
1333
+ }
1334
+ readStructure(checkConstructor = true) {
1335
+ if (checkConstructor) {
1336
+ this.assertConstructor(CORE_TYPES.Structure);
914
1337
  }
915
- this.allocate(require);
916
- const bytes = utf8Write(this.target, value, this.offset);
917
- if (require < 254) {
918
- this.target[start++] = bytes;
919
- } else {
920
- this.target[start++] = 254;
921
- this.target[start++] = bytes % 256;
922
- this.target[start++] = (bytes >> 8) % 256;
923
- this.target[start++] = (bytes >> 16) % 256;
1338
+ const structureId = this.readInt32(false);
1339
+ const struct = this.structures.get(structureId);
1340
+ if (!struct) {
1341
+ throw new Error(
1342
+ `Unknown structure id = ${structureId}, offset = ${this.offset - 1}`
1343
+ );
924
1344
  }
925
- this.offset += bytes;
926
- return this;
1345
+ return struct.extension.decode.call(this);
927
1346
  }
928
- writeChecksum(withConstructor = true) {
929
- const bytes = this.target.slice(this._checksumOffset, this.offset);
930
- let sum = 0;
931
- for (const val of bytes) {
932
- sum += val;
1347
+ /**
1348
+ * Reads a object.
1349
+ */
1350
+ readObject() {
1351
+ if (this._repeat) {
1352
+ if (this._repeat.pool > 0) {
1353
+ --this._repeat.pool;
1354
+ return this._repeat.value;
1355
+ } else {
1356
+ this._repeat = void 0;
1357
+ }
933
1358
  }
934
- if (withConstructor) {
935
- this.writeByte(CORE_TYPES.Checksum);
1359
+ const constructorId = this.readByte();
1360
+ const ext = this.extensions.get(constructorId);
1361
+ let value;
1362
+ if (ext) {
1363
+ value = ext.decode.call(this);
1364
+ } else {
1365
+ value = this._lastObject = this.readCore(constructorId);
936
1366
  }
937
- this.writeLength(sum);
938
- this._checksumOffset = this.offset;
939
- return this;
1367
+ return value;
940
1368
  }
941
- writeBytes(value) {
942
- const length = value.length;
943
- this.writeLength(length);
944
- this.allocate(length);
945
- this.target.set(value, this.offset);
946
- this.offset += length;
947
- return this;
1369
+ readObjectGzip() {
1370
+ const bytes = this.readGzip();
1371
+ const reader = new BinaryReader(bytes);
1372
+ reader.extensions = this.extensions;
1373
+ reader.dictionary = this.dictionary;
1374
+ reader.dictionaryExtended = this.dictionaryExtended;
1375
+ return reader.readObject();
948
1376
  }
949
- writeLength(value) {
950
- if (value < 254) {
951
- this.allocate(1);
952
- this.target[this.offset++] = value;
953
- } else {
954
- this.allocate(4);
955
- this.target[this.offset++] = 254;
956
- this.target[this.offset++] = value % 256;
957
- this.target[this.offset++] = (value >> 8) % 256;
958
- this.target[this.offset++] = (value >> 16) % 256;
1377
+ readGzip() {
1378
+ return pako__default.inflateRaw(this.readBytes());
1379
+ }
1380
+ readCore(constructorId) {
1381
+ switch (constructorId) {
1382
+ case CORE_TYPES.None:
1383
+ return this.readObject();
1384
+ case CORE_TYPES.GZIP:
1385
+ return this.readObjectGzip();
1386
+ case CORE_TYPES.BoolTrue:
1387
+ return true;
1388
+ case CORE_TYPES.BoolFalse:
1389
+ return false;
1390
+ case CORE_TYPES.Vector:
1391
+ return this.readVector(false);
1392
+ case CORE_TYPES.VectorDynamic:
1393
+ return this.readVectorDynamic(false);
1394
+ case CORE_TYPES.Null:
1395
+ return null;
1396
+ case CORE_TYPES.Binary:
1397
+ return this.readBytes();
1398
+ case CORE_TYPES.String:
1399
+ return this.readString();
1400
+ case CORE_TYPES.Date:
1401
+ return this.readDate();
1402
+ case CORE_TYPES.Int32:
1403
+ return this.readInt32();
1404
+ case CORE_TYPES.Int16:
1405
+ return this.readInt16();
1406
+ case CORE_TYPES.Int8:
1407
+ return this.readInt8();
1408
+ case CORE_TYPES.UInt32:
1409
+ return this.readInt32(false);
1410
+ case CORE_TYPES.UInt16:
1411
+ return this.readInt16(false);
1412
+ case CORE_TYPES.UInt8:
1413
+ return this.readInt8(false);
1414
+ case CORE_TYPES.Float:
1415
+ return this.readFloat();
1416
+ case CORE_TYPES.Double:
1417
+ return this.readDouble();
1418
+ case CORE_TYPES.Map:
1419
+ return this.readMap(false);
1420
+ case CORE_TYPES.Checksum:
1421
+ return void this.readChecksum(false);
1422
+ case CORE_TYPES.Structure:
1423
+ return this.readStructure(false);
1424
+ case CORE_TYPES.DictIndex: {
1425
+ const idx = this.readLength();
1426
+ return this.getDictionaryValue(idx);
1427
+ }
1428
+ case CORE_TYPES.DictValue: {
1429
+ const value = this.readString();
1430
+ this.dictionaryExtended.maybeInsert(value);
1431
+ return value;
1432
+ }
1433
+ case CORE_TYPES.Repeat: {
1434
+ const size = this.readLength();
1435
+ this._repeat = { pool: size - 1, value: this._lastObject };
1436
+ return this._lastObject;
1437
+ }
959
1438
  }
960
- return this;
1439
+ throw new Error(
1440
+ `Invalid constructor = ${CORE_TYPES[constructorId] || constructorId}, offset = ${this.offset - 1}`
1441
+ );
961
1442
  }
962
- writeVector(value) {
963
- const length = value.length;
964
- this.writeLength(length);
965
- for (let i = 0; i < length; i++) {
966
- if (value[i] === void 0) {
967
- this.writeNull();
968
- } else {
969
- this.writeObject(value[i]);
1443
+ getDictionaryValue(index) {
1444
+ let value = null;
1445
+ if (this.dictionary) {
1446
+ value = this.dictionary.getValue(index);
1447
+ }
1448
+ if (value === null) {
1449
+ value = this.dictionaryExtended.getValue(index);
1450
+ }
1451
+ return value;
1452
+ }
1453
+ readDictionary() {
1454
+ const constructorId = this.readByte();
1455
+ let key = null;
1456
+ switch (constructorId) {
1457
+ case CORE_TYPES.DictIndex: {
1458
+ const idx = this.readLength();
1459
+ key = this.getDictionaryValue(idx);
1460
+ break;
1461
+ }
1462
+ case CORE_TYPES.DictValue: {
1463
+ key = this.readString();
1464
+ this.dictionaryExtended.maybeInsert(key);
1465
+ break;
1466
+ }
1467
+ case CORE_TYPES.None: {
1468
+ key = null;
1469
+ break;
1470
+ }
1471
+ default: {
1472
+ this.seek(-1);
970
1473
  }
971
1474
  }
972
- return this;
973
- }
974
- writeMap(object) {
975
- for (const key in object) {
976
- if (object[key] === void 0) continue;
977
- this._last = noop;
978
- this.wireDictionary(key);
979
- this.writeObject(object[key]);
980
- }
981
- this.writeByte(CORE_TYPES.None);
982
- return this;
1475
+ return key;
983
1476
  }
984
- wireDictionary(value) {
985
- let idx = null;
986
- if (this.dictionary) {
987
- idx = this.dictionary.getIndex(value);
988
- }
989
- if (idx === null) {
990
- idx = this.dictionaryExtended.getIndex(value);
1477
+ readMap(checkConstructor = true) {
1478
+ if (checkConstructor) {
1479
+ this.assertConstructor(CORE_TYPES.Map);
991
1480
  }
992
- if (idx === null) {
993
- this.dictionaryExtended.maybeInsert(value);
994
- this.writeCore(CORE_TYPES.DictValue, value);
995
- } else {
996
- this.writeCore(CORE_TYPES.DictIndex, idx);
1481
+ const temp = {};
1482
+ let key = this.readDictionary();
1483
+ while (key !== null) {
1484
+ temp[key] = this.readObject();
1485
+ key = this.readDictionary();
997
1486
  }
998
- return this;
999
- }
1000
- writeGzip(value) {
1001
- const compressed = pako__default.deflateRaw(value, { level: 9 });
1002
- this.writeBytes(compressed);
1003
- return this;
1487
+ return temp;
1004
1488
  }
1005
- encode(value) {
1489
+ decode(value) {
1490
+ this.target = value;
1491
+ this._last = void 0;
1492
+ this._lastObject = void 0;
1493
+ this._repeat = void 0;
1006
1494
  this.offset = 0;
1007
1495
  this._checksumOffset = 0;
1008
- this._last = noop;
1009
- this._repeat = void 0;
1010
- this.target = byteArrayAllocate(256);
1011
- this.writeObject(value);
1012
- return this.getBuffer();
1013
- }
1014
- startDynamicVector() {
1015
- this.writeByte(CORE_TYPES.VectorDynamic);
1016
- return this;
1496
+ this.length = value.length;
1497
+ return this.readObject();
1017
1498
  }
1018
- endDynamicVector() {
1019
- this.writeByte(CORE_TYPES.None);
1020
- return this;
1499
+ /**
1500
+ * Reads a vector (a list) of objects.
1501
+ */
1502
+ readVector(checkConstructor = true) {
1503
+ if (checkConstructor) {
1504
+ this.assertConstructor(CORE_TYPES.Vector);
1505
+ }
1506
+ const count = this.readLength();
1507
+ const temp = [];
1508
+ for (let i = 0; i < count; i++) {
1509
+ temp.push(this.readObject());
1510
+ }
1511
+ return temp;
1021
1512
  }
1022
- _writeCustom(value) {
1023
- const start = this.offset;
1024
- this.allocate(1);
1025
- this.offset++;
1026
- let edgeExt;
1027
- for (const ext of this.extensions.values()) {
1028
- if (ext.token === -1) {
1029
- edgeExt = ext;
1030
- continue;
1513
+ /**
1514
+ * Reads a vector (a list) of objects.
1515
+ */
1516
+ readVectorDynamic(checkConstructor = true) {
1517
+ if (checkConstructor) {
1518
+ this.assertConstructor(CORE_TYPES.VectorDynamic);
1519
+ }
1520
+ const temp = [];
1521
+ let complete = false;
1522
+ while (this.length > this.offset) {
1523
+ const constructorId = this.readByte();
1524
+ if (constructorId === CORE_TYPES.None) {
1525
+ complete = true;
1526
+ break;
1031
1527
  }
1032
- ext.encode.call(this, value);
1033
- const processed = start + 1 < this.offset;
1034
- if (processed) {
1035
- const end = this.offset;
1036
- this.offset = start;
1037
- this.writeByte(ext.token);
1038
- this.offset = end;
1039
- return true;
1528
+ const ext = this.extensions.get(constructorId);
1529
+ let value;
1530
+ if (ext) {
1531
+ value = ext.decode.call(this);
1532
+ } else {
1533
+ value = this.readCore(constructorId);
1040
1534
  }
1535
+ temp.push(value);
1041
1536
  }
1042
- this.offset = start;
1043
- if (edgeExt) {
1044
- edgeExt.encode.call(this, value);
1045
- return start < this.offset;
1537
+ if (!complete) {
1538
+ const err = new Error(`DynamicVector incomplete.`);
1539
+ err.incomplete = true;
1540
+ Error.captureStackTrace(err, this.readDictionary);
1541
+ throw err;
1046
1542
  }
1047
- return false;
1543
+ this._last = temp;
1544
+ return temp;
1048
1545
  }
1049
- writeObject(value) {
1050
- if (value === void 0) return this;
1051
- const constructorId = coreType(value);
1052
- if (constructorId === CORE_TYPES.None) {
1053
- if (this._writeCustom(value)) {
1054
- return this;
1055
- }
1056
- throw new TypeError(`Invalid core type of ${value}`);
1546
+ readChecksum(checkConstructor = true) {
1547
+ const offset = this.offset;
1548
+ if (checkConstructor) {
1549
+ this.assertConstructor(CORE_TYPES.Checksum);
1057
1550
  }
1058
- if (this._last === value) {
1059
- this.writeRepeat();
1060
- } else {
1061
- this._last = value;
1062
- this._repeat = void 0;
1063
- this.writeCore(constructorId, value);
1551
+ const bytes = this.target.subarray(this._checksumOffset, offset);
1552
+ const checksum = this.readInt32();
1553
+ let sum = 0;
1554
+ for (const val of bytes) {
1555
+ sum += val;
1064
1556
  }
1065
- return this;
1557
+ if (checksum - sum !== 0) {
1558
+ throw new Error(
1559
+ `Invalid checksum = ${checksum - sum}, offset = ${offset}`
1560
+ );
1561
+ }
1562
+ this._checksumOffset = this.offset;
1066
1563
  }
1067
- writeObjectGzip(value) {
1068
- const writer = new BinaryWriter();
1069
- writer.extensions = this.extensions;
1070
- writer.dictionary = this.dictionary;
1071
- writer.dictionaryExtended = this.dictionaryExtended;
1072
- writer.writeObject(value);
1073
- this.writeCore(CORE_TYPES.GZIP, writer.getBuffer());
1074
- return this;
1564
+ /**
1565
+ * Tells the current position on the stream.
1566
+ */
1567
+ tellPosition() {
1568
+ return this.offset;
1075
1569
  }
1076
- writeCore(constructorId, value) {
1077
- if (this.withGzip && SUPPORT_COMPRESSION.has(constructorId)) {
1078
- this.writeObjectGzip(value);
1079
- return this;
1080
- } else if (!NO_CONSTRUCTOR.has(constructorId)) {
1081
- this.writeByte(constructorId);
1082
- }
1083
- switch (constructorId) {
1084
- case CORE_TYPES.GZIP: {
1085
- return this.writeGzip(value);
1086
- }
1087
- case CORE_TYPES.DictIndex: {
1088
- return this.writeLength(value);
1089
- }
1090
- case CORE_TYPES.DictValue: {
1091
- return this.writeString(value);
1092
- }
1093
- case CORE_TYPES.BoolFalse: {
1094
- return this.writeBool(value);
1095
- }
1096
- case CORE_TYPES.BoolTrue: {
1097
- return this.writeBool(value);
1098
- }
1099
- case CORE_TYPES.Date: {
1100
- return this.writeDate(value);
1101
- }
1102
- case CORE_TYPES.Int32: {
1103
- return this.writeInt32(value);
1104
- }
1105
- case CORE_TYPES.Int16: {
1106
- return this.writeInt16(value);
1107
- }
1108
- case CORE_TYPES.Int8: {
1109
- return this.writeInt8(value);
1110
- }
1111
- case CORE_TYPES.UInt32: {
1112
- return this.writeInt32(value, false);
1113
- }
1114
- case CORE_TYPES.UInt16: {
1115
- return this.writeInt16(value, false);
1116
- }
1117
- case CORE_TYPES.UInt8: {
1118
- return this.writeInt8(value, false);
1119
- }
1120
- case CORE_TYPES.Double: {
1121
- return this.writeDouble(value);
1122
- }
1123
- case CORE_TYPES.Float: {
1124
- return this.writeFloat(value);
1125
- }
1126
- case CORE_TYPES.Null: {
1127
- return this.writeNull();
1128
- }
1129
- case CORE_TYPES.String: {
1130
- if (value.length <= 16) {
1131
- this.offset--;
1132
- return this.wireDictionary(value);
1133
- }
1134
- return this.writeString(value);
1135
- }
1136
- case CORE_TYPES.Vector: {
1137
- return this.writeVector(value);
1138
- }
1139
- case CORE_TYPES.Map: {
1140
- return this.writeMap(value);
1141
- }
1142
- }
1143
- return this;
1570
+ /**
1571
+ * Sets the current position on the stream.
1572
+ */
1573
+ setPosition(position) {
1574
+ this.offset = position;
1144
1575
  }
1145
- writeRepeat() {
1146
- if (!this._repeat) {
1147
- this.writeByte(CORE_TYPES.Repeat);
1148
- this._repeat = { count: 0, offset: this.offset };
1149
- }
1150
- this.offset = this._repeat.offset;
1151
- this._repeat.count++;
1152
- this.writeLength(this._repeat.count);
1153
- return this;
1576
+ /**
1577
+ * Seeks the stream position given an offset from the current position.
1578
+ * The offset may be negative.
1579
+ */
1580
+ seek(offset) {
1581
+ this.offset += offset;
1154
1582
  }
1155
1583
  }
1156
1584
 
@@ -1158,5 +1586,7 @@ exports.BinaryReader = BinaryReader;
1158
1586
  exports.BinaryWriter = BinaryWriter;
1159
1587
  exports.CORE_TYPES = CORE_TYPES;
1160
1588
  exports.MAX_BUFFER_SIZE = MAX_BUFFER_SIZE;
1589
+ exports.Structure = Structure;
1161
1590
  exports.createDictionary = createDictionary;
1162
- //# sourceMappingURL=tl-pack.DfL54MjP.cjs.map
1591
+ exports.defineStructure = defineStructure;
1592
+ //# sourceMappingURL=tl-pack.c8vOMguk.cjs.map