@cloudpss/ubjson 0.4.15 → 0.4.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.
Files changed (43) hide show
  1. package/benchmark-string-size-caculation.js +50 -0
  2. package/benchmark-string.js +3 -3
  3. package/benchmark.js +3 -3
  4. package/dist/common/decoder.js +3 -3
  5. package/dist/common/decoder.js.map +1 -1
  6. package/dist/common/encoder.d.ts +0 -1
  7. package/dist/common/encoder.js +26 -23
  8. package/dist/common/encoder.js.map +1 -1
  9. package/dist/common/string-decoder.js +3 -3
  10. package/dist/common/string-decoder.js.map +1 -1
  11. package/dist/common/string-encoder.d.ts +2 -0
  12. package/dist/common/string-encoder.js +51 -0
  13. package/dist/common/string-encoder.js.map +1 -1
  14. package/dist/decoder.d.ts +1 -2
  15. package/dist/decoder.js +1 -2
  16. package/dist/decoder.js.map +1 -1
  17. package/dist/encoder.js.map +1 -1
  18. package/dist/stream-helper/decoder.d.ts +2 -2
  19. package/dist/stream-helper/decoder.js +2 -2
  20. package/dist/stream-helper/decoder.js.map +1 -1
  21. package/dist/utils.js +3 -0
  22. package/dist/utils.js.map +1 -1
  23. package/package.json +2 -2
  24. package/src/common/decoder.ts +3 -3
  25. package/src/common/encoder.ts +27 -25
  26. package/src/common/string-decoder.ts +3 -4
  27. package/src/common/string-encoder.ts +63 -0
  28. package/src/decoder.ts +1 -3
  29. package/src/encoder.ts +2 -4
  30. package/src/stream-helper/decoder.ts +3 -3
  31. package/src/utils.ts +3 -0
  32. package/tests/decode.js +12 -44
  33. package/tests/e2e.js +20 -21
  34. package/tests/encode.js +31 -53
  35. package/tests/huge-string.js +122 -0
  36. package/tests/rxjs/decode.js +18 -50
  37. package/tests/rxjs/encode.js +17 -61
  38. package/tests/stream/decode.js +17 -49
  39. package/tests/stream/encode.js +17 -61
  40. package/tests/string-encoding.js +4 -7
  41. package/tests/tsconfig.json +8 -0
  42. package/tsconfig.json +7 -0
  43. package/yarn-error.log +0 -4520
@@ -1,3 +1,58 @@
1
+ // https://github.com/ehmicky/string-byte-length/blob/main/src/char_code.js
2
+
3
+ // Last ASCII character (1 byte)
4
+ const LAST_ASCII_CODEPOINT = 0x7f;
5
+ // Last 2-bytes character
6
+ const LAST_TWO_BYTES_CODEPOINT = 0x7ff;
7
+ // Others are 3 bytes characters
8
+ // However, U+d800 to U+dbff:
9
+ // - Followed by U+dc00 to U+dfff -> 4 bytes together (astral character)
10
+ // - Otherwise -> 3 bytes (like above)
11
+ const FIRST_HIGH_SURROGATE = 0xd800;
12
+ const LAST_HIGH_SURROGATE = 0xdbff;
13
+ const FIRST_LOW_SURROGATE = 0xdc00;
14
+ const LAST_LOW_SURROGATE = 0xdfff;
15
+ /** 计算使用的空间 */
16
+ function getCharCodeByteLength(string: string): number {
17
+ const charLength = string.length;
18
+ let byteLength = charLength;
19
+
20
+ for (let charIndex = 0; charIndex < charLength; charIndex += 1) {
21
+ const codepoint = string.charCodeAt(charIndex);
22
+
23
+ if (codepoint <= LAST_ASCII_CODEPOINT) {
24
+ continue;
25
+ }
26
+
27
+ if (codepoint <= LAST_TWO_BYTES_CODEPOINT) {
28
+ byteLength += 1;
29
+ continue;
30
+ }
31
+
32
+ byteLength += 2;
33
+
34
+ if (codepoint < FIRST_HIGH_SURROGATE || codepoint > LAST_HIGH_SURROGATE) {
35
+ continue;
36
+ }
37
+
38
+ // When out-of-bound, this returns NaN, which is `false` with the
39
+ // next condition
40
+ const nextCodepoint = string.charCodeAt(charIndex + 1);
41
+
42
+ // High surrogates should be followed by low surrogates.
43
+ // However, JavaScript strings allow invalid surrogates, which are counted
44
+ // as a normal 3-byte character. This should not happen often in real code
45
+ // though.
46
+ if (nextCodepoint < FIRST_LOW_SURROGATE || nextCodepoint > LAST_LOW_SURROGATE) {
47
+ continue;
48
+ }
49
+
50
+ charIndex += 1;
51
+ }
52
+
53
+ return byteLength;
54
+ }
55
+
1
56
  /** 字符串编码器 */
2
57
  export class StringEncoder extends TextEncoder {
3
58
  private readonly cache = new Map<string, Uint8Array>();
@@ -31,4 +86,12 @@ export class StringEncoder extends TextEncoder {
31
86
  }
32
87
  return buf;
33
88
  }
89
+
90
+ /** 计算使用的空间 */
91
+ byteLength(value: string): number {
92
+ if (typeof Buffer == 'function' && typeof Buffer.byteLength == 'function') {
93
+ return Buffer.byteLength(value, 'utf8');
94
+ }
95
+ return getCharCodeByteLength(value);
96
+ }
34
97
  }
package/src/decoder.ts CHANGED
@@ -1,3 +1 @@
1
- import { Decoder } from './common/decoder.js';
2
-
3
- export { Decoder };
1
+ export { Decoder } from './common/decoder.js';
package/src/encoder.ts CHANGED
@@ -38,7 +38,7 @@ export class Encoder extends EncoderBase {
38
38
  // 为根 typed array 优化,减少不必要的分配
39
39
  if (this.value.byteLength < 128) this.ensureCapacity(6 + this.value.byteLength);
40
40
  else if (this.value.byteLength < 32768) this.ensureCapacity(7 + this.value.byteLength);
41
- else if (this.value.byteLength < 2147483648) this.ensureCapacity(9 + this.value.byteLength);
41
+ else if (this.value.byteLength < 2_147_483_648) this.ensureCapacity(9 + this.value.byteLength);
42
42
  else this.ensureCapacity(13 + this.value.byteLength);
43
43
  this.writeTypedArray(this.value);
44
44
  // 取消注释后运行测试
@@ -60,9 +60,7 @@ export class Encoder extends EncoderBase {
60
60
  }
61
61
 
62
62
  // 合并缓冲区
63
- const result = new Uint8Array(
64
- this.length + this.flushedBuffers.reduce((sum, buffer) => sum + buffer.byteLength, 0),
65
- );
63
+ const result = new Uint8Array(this.length + this.flushedBuffers.reduce((sum, buffer) => sum + buffer.byteLength, 0));
66
64
  let offset = 0;
67
65
  for (const buffer of this.flushedBuffers) {
68
66
  result.set(buffer, offset);
@@ -1,6 +1,4 @@
1
- import { Decoder, UnexpectedEof } from '../common/decoder.js';
2
-
3
- export { UnexpectedEof };
1
+ import { Decoder } from '../common/decoder.js';
4
2
 
5
3
  /** 流式解码 UBJSON */
6
4
  export class StreamDecoderHelper extends Decoder {
@@ -13,3 +11,5 @@ export class StreamDecoderHelper extends Decoder {
13
11
  return this.offset;
14
12
  }
15
13
  }
14
+
15
+ export { UnexpectedEof } from '../common/decoder.js';
package/src/utils.ts CHANGED
@@ -1,5 +1,8 @@
1
1
  /** 支持的数据转为 Uint8Array */
2
2
  export function toUint8Array(data: BinaryData): Uint8Array {
3
+ if (data == null || typeof data != 'object' || typeof data.byteLength != 'number') {
4
+ throw new TypeError('Invalid data');
5
+ }
3
6
  if (ArrayBuffer.isView(data)) {
4
7
  return new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
5
8
  }
package/tests/decode.js CHANGED
@@ -51,7 +51,7 @@ test('decode int16', () => {
51
51
  });
52
52
 
53
53
  test('decode int32', () => {
54
- expect(decode(toBuffer('l', 0x12, 0x34, 0x56, 0x78))).toBe(0x12345678);
54
+ expect(decode(toBuffer('l', 0x12, 0x34, 0x56, 0x78))).toBe(0x1234_5678);
55
55
  });
56
56
 
57
57
  test('decode int64 [error]', () => {
@@ -59,11 +59,11 @@ test('decode int64 [error]', () => {
59
59
  });
60
60
 
61
61
  test('decode float32', () => {
62
- expect(decode(toBuffer('d', 0x3f, 0x80, 0x80, 0x00))).toBe(1.00390625);
62
+ expect(decode(toBuffer('d', 0x3f, 0x80, 0x80, 0x00))).toBe(1.003_906_25);
63
63
  });
64
64
 
65
65
  test('decode float64', () => {
66
- expect(decode(toBuffer('D', 0x40, 0xf8, 0x6a, 0x00, 0x10, 0x00, 0x00, 0x00))).toBe(100000.00390625);
66
+ expect(decode(toBuffer('D', 0x40, 0xf8, 0x6a, 0x00, 0x10, 0x00, 0x00, 0x00))).toBe(100_000.003_906_25);
67
67
  });
68
68
 
69
69
  test('decode high-precision number [error]', () => {
@@ -109,9 +109,7 @@ test('decode huge string', () => {
109
109
  });
110
110
 
111
111
  test('decode huge string [error]', () => {
112
- expect(() => decode(toBuffer('S', 'L', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 'x'))).toThrow(
113
- /Unsupported type int64/,
114
- );
112
+ expect(() => decode(toBuffer('S', 'L', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 'x'))).toThrow(/Unsupported type int64/);
115
113
  });
116
114
 
117
115
  test('decode array', () => {
@@ -147,9 +145,10 @@ test('decode array (strongly typed, empty, optimized)', () => {
147
145
  });
148
146
 
149
147
  test('decode N-D array (strongly typed, optimized)', () => {
150
- expect(
151
- decode(toBuffer('[', '$', '[', '#', 'i', 2, '$', 'i', '#', 'i', 3, 1, 2, 3, '$', 'i', '#', 'i', 3, 4, 5, 6)),
152
- ).toEqual([new Int8Array([1, 2, 3]), new Int8Array([4, 5, 6])]);
148
+ expect(decode(toBuffer('[', '$', '[', '#', 'i', 2, '$', 'i', '#', 'i', 3, 1, 2, 3, '$', 'i', '#', 'i', 3, 4, 5, 6))).toEqual([
149
+ new Int8Array([1, 2, 3]),
150
+ new Int8Array([4, 5, 6]),
151
+ ]);
153
152
  });
154
153
 
155
154
  test('decode array of objects (optimized)', () => {
@@ -321,13 +320,11 @@ test('decode array (int16, strongly typed, optimized) [use typed array]', () =>
321
320
  test('decode array (int32, strongly typed, optimized) [use typed array]', () => {
322
321
  const actual = decode(toBuffer('[', '$', 'l', '#', 'i', 2, 0x12, 0x34, 0x56, 0x78, 0xfe, 0xdc, 0xba, 0x98));
323
322
  expect(actual).toBeInstanceOf(Int32Array);
324
- expect(actual).toEqual(Int32Array.from([305419896, -19088744]));
323
+ expect(actual).toEqual(Int32Array.from([305_419_896, -19_088_744]));
325
324
  });
326
325
 
327
326
  test('decode array (int64, strongly typed, optimized) [use typed array]', () => {
328
- expect(() =>
329
- decode(toBuffer('[', '$', 'L', '#', 'i', 1, 0x12, 0x34, 0x56, 0x78, 0xfe, 0xdc, 0xba, 0x98)),
330
- ).toThrow();
327
+ expect(() => decode(toBuffer('[', '$', 'L', '#', 'i', 1, 0x12, 0x34, 0x56, 0x78, 0xfe, 0xdc, 0xba, 0x98))).toThrow();
331
328
  });
332
329
 
333
330
  test('decode array (float32, strongly typed, optimized) [use typed array]', () => {
@@ -337,32 +334,7 @@ test('decode array (float32, strongly typed, optimized) [use typed array]', () =
337
334
  });
338
335
 
339
336
  test('decode array (float64, strongly typed, optimized) [use typed array]', () => {
340
- const actual = decode(
341
- toBuffer(
342
- '[',
343
- '$',
344
- 'D',
345
- '#',
346
- 'i',
347
- 2,
348
- 0x3f,
349
- 0xd0,
350
- 0x00,
351
- 0x00,
352
- 0x00,
353
- 0x00,
354
- 0x00,
355
- 0x00,
356
- 0x3f,
357
- 0xc0,
358
- 0x00,
359
- 0x00,
360
- 0x00,
361
- 0x00,
362
- 0x00,
363
- 0x00,
364
- ),
365
- );
337
+ const actual = decode(toBuffer('[', '$', 'D', '#', 'i', 2, 0x3f, 0xd0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00));
366
338
  expect(actual).toBeInstanceOf(Float64Array);
367
339
  expect(actual).toEqual(Float64Array.from([0.25, 0.125]));
368
340
  });
@@ -376,11 +348,7 @@ test('decode object', () => {
376
348
  });
377
349
 
378
350
  test('decode object (with no-op)', () => {
379
- expect(
380
- decode(
381
- toBuffer('N', '{', 'N', 'i', 1, 'a', 'i', 1, 'i', 1, 'b', 'N', 'i', 2, 'i', 1, 'c', 'i', 3, 'N', '}', 'N'),
382
- ),
383
- ).toEqual({ a: 1, b: 2, c: 3 });
351
+ expect(decode(toBuffer('N', '{', 'N', 'i', 1, 'a', 'i', 1, 'i', 1, 'b', 'N', 'i', 2, 'i', 1, 'c', 'i', 3, 'N', '}', 'N'))).toEqual({ a: 1, b: 2, c: 3 });
384
352
  });
385
353
 
386
354
  test('decode array (empty, optimized)', () => {
package/tests/e2e.js CHANGED
@@ -19,14 +19,14 @@ test('encode/decode complex object', () => {
19
19
  id: 1,
20
20
  name: 'test',
21
21
  content: null,
22
- timestamp: 1532432408.008,
22
+ timestamp: 1_532_432_408.008,
23
23
  published: false,
24
24
  },
25
25
  {
26
26
  id: 2,
27
27
  name: 'lorem',
28
28
  content: 'Lorem ipsum...',
29
- timestamp: 1532432416.346,
29
+ timestamp: 1_532_432_416.346,
30
30
  published: true,
31
31
  },
32
32
  ],
@@ -34,12 +34,12 @@ test('encode/decode complex object', () => {
34
34
  traces: [
35
35
  {
36
36
  name: 'test',
37
- x: new Float64Array([1, 2, 3, -Infinity, Infinity, NaN, Number.MAX_VALUE, Number.MIN_VALUE]),
37
+ x: new Float64Array([1, 2, 3, Number.NEGATIVE_INFINITY, Number.POSITIVE_INFINITY, Number.NaN, Number.MAX_VALUE, Number.MIN_VALUE]),
38
38
  y: new Int8Array([0, 4, 5, 6, -128, -1, 127]),
39
39
  },
40
40
  {
41
41
  name: 'test2',
42
- x: new Float32Array([1, 2, 3, -Infinity, Infinity, NaN, Number.MAX_VALUE, Number.MIN_VALUE]),
42
+ x: new Float32Array([1, 2, 3, Number.NEGATIVE_INFINITY, Number.POSITIVE_INFINITY, Number.NaN, Number.MAX_VALUE, Number.MIN_VALUE]),
43
43
  y: new Int16Array([4, 5, 6, -32768, 32767]),
44
44
  },
45
45
  {
@@ -52,7 +52,7 @@ test('encode/decode complex object', () => {
52
52
  description1: 'medium text'.repeat(100),
53
53
  description2: 'medium text'.repeat(1000),
54
54
  document1: 'long text'.repeat(10000),
55
- document2: 'long text'.repeat(100000),
55
+ document2: 'long text'.repeat(100_000),
56
56
  };
57
57
  const encoded = encode(expected);
58
58
  const actual = decode(Buffer.from(encoded));
@@ -78,7 +78,7 @@ test('encode/decode model', () => {
78
78
  pins: {
79
79
  input: {
80
80
  position: {
81
- x: 0.9999999,
81
+ x: 0.999_999_9,
82
82
  y: 0.5,
83
83
  },
84
84
  },
@@ -90,7 +90,7 @@ test('encode/decode model', () => {
90
90
  },
91
91
  electrical: {
92
92
  position: {
93
- x: 0.9999999,
93
+ x: 0.999_999_9,
94
94
  y: 0.5,
95
95
  },
96
96
  },
@@ -102,7 +102,7 @@ test('encode/decode model', () => {
102
102
  refPath: {
103
103
  d: 'm90000 0h-60000a10000 10000 0 0 0 0 20000h60000zm0 10000h20000',
104
104
  h: 20000,
105
- w: 110000,
105
+ w: 110_000,
106
106
  },
107
107
  fillOpacity: 'var(--fill-opacity)',
108
108
  strokeWidth: 'var(--stroke-width)',
@@ -114,7 +114,7 @@ test('encode/decode model', () => {
114
114
  refPath: {
115
115
  d: 'm90000 0h-60000a10000 10000 0 0 0 0 20000h60000zm0 10000h20000',
116
116
  h: 20000,
117
- w: 110000,
117
+ w: 110_000,
118
118
  },
119
119
  fillOpacity: 'var(--fill-opacity)',
120
120
  strokeWidth: 'var(--stroke-width)',
@@ -126,7 +126,7 @@ test('encode/decode model', () => {
126
126
  refPath: {
127
127
  d: 'm20000 10000m-5000 -5000l5000 5000l-5000 5000',
128
128
  h: 20000,
129
- w: 110000,
129
+ w: 110_000,
130
130
  },
131
131
  fillOpacity: 'var(--fill-opacity)',
132
132
  strokeWidth: 'var(--stroke-width)',
@@ -138,7 +138,7 @@ test('encode/decode model', () => {
138
138
  refPath: {
139
139
  d: 'm20000 0h60000a10000 10000 0 0 1 0 20000h-60000zm0 10000h-20000',
140
140
  h: 20000,
141
- w: 110000,
141
+ w: 110_000,
142
142
  },
143
143
  fillOpacity: 'var(--fill-opacity)',
144
144
  strokeWidth: 'var(--stroke-width)',
@@ -150,7 +150,7 @@ test('encode/decode model', () => {
150
150
  refPath: {
151
151
  d: 'm110000 10000m-5000 -5000l5000 5000l-5000 5000',
152
152
  h: 20000,
153
- w: 110000,
153
+ w: 110_000,
154
154
  },
155
155
  fillOpacity: 'var(--fill-opacity)',
156
156
  strokeWidth: 'var(--stroke-width)',
@@ -219,8 +219,7 @@ test('encode/decode model', () => {
219
219
  name: 'Pin Key',
220
220
  type: 'choice',
221
221
  value: '',
222
- choices:
223
- '=mapper(p,index,array) = {key: p.key, name: p.key, description: p.description};\n$$.revision.pins.map(mapper)',
222
+ choices: '=mapper(p,index,array) = {key: p.key, name: p.key, description: p.description};\n$$.revision.pins.map(mapper)',
224
223
  condition: 'true',
225
224
  description: '绑定端口',
226
225
  },
@@ -298,14 +297,14 @@ test('encode/decode complex object (no encodeInto)', () => {
298
297
  id: 1,
299
298
  name: 'test',
300
299
  content: null,
301
- timestamp: 1532432408.008,
300
+ timestamp: 1_532_432_408.008,
302
301
  published: false,
303
302
  },
304
303
  {
305
304
  id: 2,
306
305
  name: 'lorem',
307
306
  content: 'Lorem ipsum...',
308
- timestamp: 1532432416.346,
307
+ timestamp: 1_532_432_416.346,
309
308
  published: true,
310
309
  },
311
310
  ],
@@ -313,12 +312,12 @@ test('encode/decode complex object (no encodeInto)', () => {
313
312
  traces: [
314
313
  {
315
314
  name: 'test',
316
- x: new Float64Array([1, 2, 3, -Infinity, Infinity, NaN, Number.MAX_VALUE, Number.MIN_VALUE]),
315
+ x: new Float64Array([1, 2, 3, Number.NEGATIVE_INFINITY, Number.POSITIVE_INFINITY, Number.NaN, Number.MAX_VALUE, Number.MIN_VALUE]),
317
316
  y: new Int8Array([0, 4, 5, 6, -128, -1, 127]),
318
317
  },
319
318
  {
320
319
  name: 'test2',
321
- x: new Float32Array([1, 2, 3, -Infinity, Infinity, NaN, Number.MAX_VALUE, Number.MIN_VALUE]),
320
+ x: new Float32Array([1, 2, 3, Number.NEGATIVE_INFINITY, Number.POSITIVE_INFINITY, Number.NaN, Number.MAX_VALUE, Number.MIN_VALUE]),
322
321
  y: new Int16Array([4, 5, 6, -32768, 32767]),
323
322
  },
324
323
  {
@@ -331,7 +330,7 @@ test('encode/decode complex object (no encodeInto)', () => {
331
330
  description1: 'medium text'.repeat(100),
332
331
  description2: 'medium text'.repeat(1000),
333
332
  document1: 'long text'.repeat(10000),
334
- document2: 'long text'.repeat(100000),
333
+ document2: 'long text'.repeat(100_000),
335
334
  };
336
335
  const encoded = encode(expected);
337
336
  const actual = decode(encoded);
@@ -340,10 +339,10 @@ test('encode/decode complex object (no encodeInto)', () => {
340
339
  });
341
340
 
342
341
  test('encode/decode large array', () => {
343
- const array = new Array(100000);
342
+ const array = Array.from({ length: 100_000 });
344
343
  array[12345] = 'item';
345
344
 
346
- const expected = Array.from({ length: 100000 }).fill(null);
345
+ const expected = Array.from({ length: 100_000 }).fill(null);
347
346
  expected[12345] = 'item';
348
347
 
349
348
  expect(decode(encode(array))).toEqual(expected);
package/tests/encode.js CHANGED
@@ -50,19 +50,19 @@ test('encode int16', () => {
50
50
  });
51
51
 
52
52
  test('encode int32', () => {
53
- expect(toArray(encode(0x12345678))).toEqual(toArray('l', 0x12, 0x34, 0x56, 0x78));
53
+ expect(toArray(encode(0x1234_5678))).toEqual(toArray('l', 0x12, 0x34, 0x56, 0x78));
54
54
  });
55
55
 
56
56
  test('encode float32', () => {
57
- expect(toArray(encode(1.00390625))).toEqual(toArray('d', 0x3f, 0x80, 0x80, 0x00));
57
+ expect(toArray(encode(1.003_906_25))).toEqual(toArray('d', 0x3f, 0x80, 0x80, 0x00));
58
58
  });
59
59
 
60
60
  test('encode float32 (too large integer)', () => {
61
- expect(toArray(encode(2147483648))).toEqual(toArray('d', 0x4f, 0x00, 0x00, 0x00));
61
+ expect(toArray(encode(2_147_483_648))).toEqual(toArray('d', 0x4f, 0x00, 0x00, 0x00));
62
62
  });
63
63
 
64
64
  test('encode float64', () => {
65
- expect(toArray(encode(100000.00390625))).toEqual(toArray('D', 0x40, 0xf8, 0x6a, 0x00, 0x10, 0x00, 0x00, 0x00));
65
+ expect(toArray(encode(100_000.003_906_25))).toEqual(toArray('D', 0x40, 0xf8, 0x6a, 0x00, 0x10, 0x00, 0x00, 0x00));
66
66
  });
67
67
 
68
68
  test('encode char', () => {
@@ -70,7 +70,7 @@ test('encode char', () => {
70
70
  });
71
71
 
72
72
  test('encode char 128', () => {
73
- expect(toArray(encode('\xcc'))).toEqual(toArray('C', '\xcc'));
73
+ expect(toArray(encode('\u00CC'))).toEqual(toArray('C', '\u00CC'));
74
74
  });
75
75
 
76
76
  test('encode char 257', () => {
@@ -109,7 +109,7 @@ test('encode array (undefined)', () => {
109
109
  });
110
110
 
111
111
  test('encode array (spares)', () => {
112
- const array = new Array(3);
112
+ const array = Array.from({ length: 3 });
113
113
  array[1] = true;
114
114
  expect(toArray(encode(array))).toEqual(toArray('[', 'Z', 'T', 'Z', ']'));
115
115
  });
@@ -185,49 +185,22 @@ test('encode array (buffer array)', () => {
185
185
  });
186
186
 
187
187
  test('encode array (int16 typed array)', () => {
188
- expect(toArray(encode(Int16Array.from([4660, -292])))).toEqual(
189
- toArray('[', '$', 'I', '#', 'i', 2, 0x12, 0x34, 0xfe, 0xdc),
190
- );
188
+ expect(toArray(encode(Int16Array.from([4660, -292])))).toEqual(toArray('[', '$', 'I', '#', 'i', 2, 0x12, 0x34, 0xfe, 0xdc));
191
189
  });
192
190
 
193
191
  test('encode array (int32 typed array)', () => {
194
- expect(toArray(encode(Int32Array.from([305419896, -19088744])))).toEqual(
192
+ expect(toArray(encode(Int32Array.from([305_419_896, -19_088_744])))).toEqual(
195
193
  toArray('[', '$', 'l', '#', 'i', 2, 0x12, 0x34, 0x56, 0x78, 0xfe, 0xdc, 0xba, 0x98),
196
194
  );
197
195
  });
198
196
 
199
197
  test('encode array (float32 typed array)', () => {
200
- expect(toArray(encode(Float32Array.from([0.25, 0.125])))).toEqual(
201
- toArray('[', '$', 'd', '#', 'i', 2, 0x3e, 0x80, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00),
202
- );
198
+ expect(toArray(encode(Float32Array.from([0.25, 0.125])))).toEqual(toArray('[', '$', 'd', '#', 'i', 2, 0x3e, 0x80, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00));
203
199
  });
204
200
 
205
201
  test('encode array (float64 typed array)', () => {
206
202
  expect(toArray(encode(Float64Array.from([0.25, 0.125])))).toEqual(
207
- toArray(
208
- '[',
209
- '$',
210
- 'D',
211
- '#',
212
- 'i',
213
- 2,
214
- 0x3f,
215
- 0xd0,
216
- 0x00,
217
- 0x00,
218
- 0x00,
219
- 0x00,
220
- 0x00,
221
- 0x00,
222
- 0x3f,
223
- 0xc0,
224
- 0x00,
225
- 0x00,
226
- 0x00,
227
- 0x00,
228
- 0x00,
229
- 0x00,
230
- ),
203
+ toArray('[', '$', 'D', '#', 'i', 2, 0x3f, 0xd0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
231
204
  );
232
205
  });
233
206
 
@@ -252,9 +225,7 @@ test('encode array (int64 typed array)', () => {
252
225
  });
253
226
 
254
227
  test('encode object', () => {
255
- expect(toArray(encode({ a: 1, b: 2, c: 3 }))).toEqual(
256
- toArray('{', 'i', 1, 'a', 'U', 1, 'i', 1, 'b', 'U', 2, 'i', 1, 'c', 'U', 3, '}'),
257
- );
228
+ expect(toArray(encode({ a: 1, b: 2, c: 3 }))).toEqual(toArray('{', 'i', 1, 'a', 'U', 1, 'i', 1, 'b', 'U', 2, 'i', 1, 'c', 'U', 3, '}'));
258
229
  });
259
230
 
260
231
  test('encode object (empty)', () => {
@@ -266,15 +237,11 @@ test('encode object (empty key)', () => {
266
237
  });
267
238
 
268
239
  test('encode object (mixed)', () => {
269
- expect(toArray(encode({ a: 1, b: 'a', c: true }))).toEqual(
270
- toArray('{', 'i', 1, 'a', 'U', 1, 'i', 1, 'b', 'C', 'a', 'i', 1, 'c', 'T', '}'),
271
- );
240
+ expect(toArray(encode({ a: 1, b: 'a', c: true }))).toEqual(toArray('{', 'i', 1, 'a', 'U', 1, 'i', 1, 'b', 'C', 'a', 'i', 1, 'c', 'T', '}'));
272
241
  });
273
242
 
274
243
  test('encode object (only null values)', () => {
275
- expect(toArray(encode({ a: null, b: null, c: null }))).toEqual(
276
- toArray('{', 'i', 1, 'a', 'Z', 'i', 1, 'b', 'Z', 'i', 1, 'c', 'Z', '}'),
277
- );
244
+ expect(toArray(encode({ a: null, b: null, c: null }))).toEqual(toArray('{', 'i', 1, 'a', 'Z', 'i', 1, 'b', 'Z', 'i', 1, 'c', 'Z', '}'));
278
245
  });
279
246
 
280
247
  test('encode object (skip prototype)', () => {
@@ -282,9 +249,7 @@ test('encode object (skip prototype)', () => {
282
249
  obj.a = 1;
283
250
  obj.b = 'a';
284
251
  obj.c = true;
285
- expect(toArray(encode(obj))).toEqual(
286
- toArray('{', 'i', 1, 'a', 'U', 1, 'i', 1, 'b', 'C', 'a', 'i', 1, 'c', 'T', '}'),
287
- );
252
+ expect(toArray(encode(obj))).toEqual(toArray('{', 'i', 1, 'a', 'U', 1, 'i', 1, 'b', 'C', 'a', 'i', 1, 'c', 'T', '}'));
288
253
  });
289
254
 
290
255
  test('encode object (skip symbol)', () => {
@@ -347,19 +312,32 @@ test('encode huge data (~128M)', () => {
347
312
  const obj = [new Uint8Array(128 * 1024 * 1024 - 20)];
348
313
  obj[0][0] = 0x12;
349
314
  obj[0][1] = 0x34;
350
- expect(toArray(encode(obj).slice(0, 12))).toEqual(
351
- toArray('[', '[', '$', 'U', '#', 'l', 0x7, 0xff, 0xff, 0xec, 0x12, 0x34),
352
- );
315
+ expect(toArray(encode(obj).slice(0, 12))).toEqual(toArray('[', '[', '$', 'U', '#', 'l', 0x7, 0xff, 0xff, 0xec, 0x12, 0x34));
353
316
  });
354
317
 
355
318
  test('encode huge data (128M)', () => {
356
319
  const obj = [new Uint8Array(128 * 1024 * 1024)];
357
320
  obj[0][0] = 0x12;
358
321
  obj[0][1] = 0x34;
359
- expect(toArray(encode(obj).slice(0, 12))).toEqual(toArray('[', '[', '$', 'U', '#', 'l', 0x8, 0, 0, 0, 0x12, 0x34));
322
+ const encoded = encode(obj);
323
+ expect(encoded.length).toBe(128 * 1024 * 1024 + 9 + 2);
324
+ expect(toArray(encoded.slice(0, 12))).toEqual(toArray('[', '[', '$', 'U', '#', 'l', 0x8, 0, 0, 0, 0x12, 0x34));
360
325
  });
361
326
 
362
327
  test('encode huge data (128M + 1) [error]', () => {
363
328
  const obj = [new Uint8Array(128 * 1024 * 1024 + 1)];
364
329
  expect(() => encode(obj)).toThrow(/Buffer has exceed max size/);
365
330
  });
331
+
332
+ test('encode huge data (256M)', () => {
333
+ const obj = [new Uint8Array(128 * 1024 * 1024), new Uint8Array(128 * 1024 * 1024)];
334
+ obj[0][0] = 0x12;
335
+ obj[0][1] = 0x34;
336
+ obj[1][0] = 0x56;
337
+ obj[1][1] = 0x78;
338
+ const encoded = encode(obj);
339
+ expect(encoded.length).toBe(128 * 1024 * 1024 * 2 + 9 * 2 + 2);
340
+ expect(toArray(encoded.slice(0, 12))).toEqual(toArray('[', '[', '$', 'U', '#', 'l', 0x8, 0, 0, 0, 0x12, 0x34));
341
+ expect(toArray(encoded.slice(128 * 1024 * 1024 + 10, 128 * 1024 * 1024 + 10 + 11))).toEqual(toArray('[', '$', 'U', '#', 'l', 0x8, 0, 0, 0, 0x56, 0x78));
342
+ expect(toArray(encoded.slice(-1))).toEqual(toArray(']'));
343
+ });