@cloudpss/ubjson 0.5.11 → 0.5.13

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.
@@ -4,15 +4,29 @@ import { decode, decodeKey } from './string-decoder.js';
4
4
 
5
5
  const fromEntries = Object.fromEntries;
6
6
 
7
+ /** decoder options */
8
+ export interface DecoderOptions {
9
+ /** 对 {@link Uint8Array} 使用 subarray */
10
+ noAllocBuffer?: boolean;
11
+ }
12
+
7
13
  /** decoder */
8
- export class Decoder {
14
+ export class DecoderBase {
9
15
  protected readonly view: DataView;
10
16
  protected readonly data: Uint8Array;
11
17
  /** 当前读指针位置 */
12
18
  protected offset = 0;
13
- constructor(data: BinaryData) {
19
+
20
+ /** 选项 */
21
+ protected readonly noAllocBuffer;
22
+ constructor(data: BinaryData, options?: DecoderOptions) {
14
23
  this.data = toUint8Array(data);
15
24
  this.view = new DataView(this.data.buffer, this.data.byteOffset, this.data.byteLength);
25
+ if (options) {
26
+ this.noAllocBuffer = !!options.noAllocBuffer;
27
+ } else {
28
+ this.noAllocBuffer = false;
29
+ }
16
30
  }
17
31
 
18
32
  /** EOF */
@@ -76,9 +90,7 @@ export class Decoder {
76
90
  object.length = count;
77
91
  for (let i = 0; i < count; i++) {
78
92
  const key = this.readKey();
79
- const t = type ?? this.readMarker();
80
- if (t === undefined) this.eof();
81
- const value = this.readData(t);
93
+ const value = this.readData(type ?? this.readMarker());
82
94
  object[i] = [key, value];
83
95
  }
84
96
  return fromEntries(object);
@@ -99,13 +111,9 @@ export class Decoder {
99
111
  switch (type) {
100
112
  case constants.UINT8:
101
113
  try {
102
- const buf = new Uint8Array(
103
- this.data.buffer,
104
- this.data.byteOffset + this.offset,
105
- count,
106
- ).slice();
114
+ const buf = new Uint8Array(this.data.buffer, this.data.byteOffset + this.offset, count);
107
115
  this.offset += count;
108
- return buf;
116
+ return this.noAllocBuffer ? buf : buf.slice();
109
117
  } catch {
110
118
  return this.eof();
111
119
  }
@@ -154,8 +162,7 @@ export class Decoder {
154
162
  for (let i = 0; i < count; i++) {
155
163
  result[i] = this.readInt64Data();
156
164
  }
157
- throw new Error('Unsupported type int64');
158
- //return result;
165
+ return result;
159
166
  }
160
167
  case constants.NULL:
161
168
  return Array.from({ length: count }).fill(null);
@@ -193,8 +200,13 @@ export class Decoder {
193
200
  return true;
194
201
  case constants.FALSE:
195
202
  return false;
196
- case constants.INT64:
197
- return this.readInt64Data();
203
+ case constants.INT64: {
204
+ const n = this.readInt64Data();
205
+ if (n < Number.MIN_SAFE_INTEGER || n > Number.MAX_SAFE_INTEGER) {
206
+ return n;
207
+ }
208
+ return Number(n);
209
+ }
198
210
  case constants.HIGH_PRECISION_NUMBER: {
199
211
  const length = this.readIntLength();
200
212
  try {
@@ -227,9 +239,14 @@ export class Decoder {
227
239
  case constants.INT32:
228
240
  length = this.readInt32Data();
229
241
  break;
230
- case constants.INT64:
231
- length = this.readInt64Data();
242
+ case constants.INT64: {
243
+ const l = this.readInt64Data();
244
+ if (l < 0 || l > Number.MAX_SAFE_INTEGER) {
245
+ throw new Error('Invalid length');
246
+ }
247
+ length = Number(l);
232
248
  break;
249
+ }
233
250
  default:
234
251
  throw new Error(`Unexpected marker '${String.fromCharCode(marker)}'(${marker}) for int length`);
235
252
  }
@@ -284,15 +301,14 @@ export class Decoder {
284
301
  }
285
302
  }
286
303
  /** readInt64Data */
287
- private readInt64Data(): never {
304
+ private readInt64Data(): bigint {
288
305
  try {
289
- const _result = this.view.getBigInt64(this.offset);
306
+ const result = this.view.getBigInt64(this.offset);
290
307
  this.offset += 8;
291
- // return result;
308
+ return result;
292
309
  } catch {
293
310
  this.eof();
294
311
  }
295
- throw new Error('Unsupported type int64');
296
312
  }
297
313
  /** readFloat32Data */
298
314
  private readFloat32Data(): number {
@@ -96,9 +96,9 @@ export abstract class EncoderBase {
96
96
  this.ensureCapacity(1);
97
97
  this.buffer[this.length++] = constants.ARRAY_END;
98
98
  } else if (!ArrayBuffer.isView(value)) {
99
- const toJSON = typeof (value as Record<string, unknown>)['toJSON'] == 'function';
100
- if (toJSON) {
101
- this.write((value as { toJSON: () => unknown }).toJSON());
99
+ const { toJSON } = value as Record<string, unknown>;
100
+ if (typeof toJSON == 'function') {
101
+ this.write(toJSON.call(value));
102
102
  return;
103
103
  }
104
104
  this.ensureCapacity(1);
@@ -130,8 +130,9 @@ export abstract class EncoderBase {
130
130
  return;
131
131
  }
132
132
 
133
- const arrayLength = (value as Int16Array | Int32Array | Float32Array | Float64Array).length;
134
- const elementSize = (value as Int16Array | Int32Array | Float32Array | Float64Array)
133
+ const arrayLength = (value as Int16Array | Int32Array | BigInt64Array | Float32Array | Float64Array)
134
+ .length;
135
+ const elementSize = (value as Int16Array | Int32Array | BigInt64Array | Float32Array | Float64Array)
135
136
  .BYTES_PER_ELEMENT;
136
137
  if (value instanceof Int16Array) {
137
138
  this.buffer[this.length++] = constants.INT16;
@@ -165,6 +166,14 @@ export abstract class EncoderBase {
165
166
  this.view.setFloat64(this.length, value[i]);
166
167
  this.length += elementSize;
167
168
  }
169
+ } else if (value instanceof BigInt64Array) {
170
+ this.buffer[this.length++] = constants.INT64;
171
+ this.buffer[this.length++] = constants.COUNT_MARKER;
172
+ this.setLength(arrayLength);
173
+ for (let i = 0; i < arrayLength; i++) {
174
+ this.view.setBigInt64(this.length, value[i]);
175
+ this.length += elementSize;
176
+ }
168
177
  } else {
169
178
  throw new TypeError(`Unsupported typed array type ${Object.prototype.toString.call(value)}`);
170
179
  }
@@ -175,6 +184,21 @@ export abstract class EncoderBase {
175
184
  this.ensureCapacity(1);
176
185
  this.buffer[this.length++] = value ? constants.TRUE : constants.FALSE;
177
186
  return;
187
+ case 'bigint':
188
+ // int32 range
189
+ if (value >= -2_147_483_648n && value <= 2_147_483_647n) {
190
+ this.write(Number(value));
191
+ }
192
+ // int64 range
193
+ else if (value >= -9_223_372_036_854_775_808n && value <= 9_223_372_036_854_775_807n) {
194
+ this.ensureCapacity(9);
195
+ this.buffer[this.length++] = constants.INT64;
196
+ this.view.setBigInt64(this.length, value);
197
+ this.length += 8;
198
+ } else {
199
+ throw new RangeError(`BigInt value out of range: ${value}`);
200
+ }
201
+ return;
178
202
  default:
179
203
  throw new Error(`Unsupported type ${Object.prototype.toString.call(value)}`);
180
204
  }
package/src/decoder.ts CHANGED
@@ -1 +1,10 @@
1
- export { Decoder } from './common/decoder.js';
1
+ import { DecoderBase } from './common/decoder.js';
2
+ export type { DecoderOptions } from './common/decoder.js';
3
+
4
+ /** 解码 UBJSON */
5
+ export class Decoder extends DecoderBase {
6
+ /** 读取完毕 */
7
+ get ended(): boolean {
8
+ return this.offset >= this.data.byteLength;
9
+ }
10
+ }
package/src/encoder.ts CHANGED
@@ -45,11 +45,10 @@ export class Encoder extends EncoderBase {
45
45
  this.length = 0;
46
46
  }
47
47
 
48
- /** 获取写入结果 */
49
- encode(value: unknown): Uint8Array {
50
- this.allocUnsafe(BLOCK_SIZE);
51
- this.writeValue(value);
48
+ /** 获取结果 */
49
+ private getResult(): Uint8Array {
52
50
  if (this.flushedBuffers.length === 0) {
51
+ // 缓冲区为空,复制当前 buffer
53
52
  return this.buffer.slice(0, this.length);
54
53
  }
55
54
 
@@ -65,6 +64,37 @@ export class Encoder extends EncoderBase {
65
64
  result.set(this.buffer.subarray(0, this.length), offset);
66
65
  return result;
67
66
  }
67
+
68
+ /** 抛弃结果 */
69
+ private cleanResult(): void {
70
+ this.flushedBuffers.splice(0);
71
+ }
72
+
73
+ /** 获取写入结果 */
74
+ encode(value: unknown): Uint8Array {
75
+ try {
76
+ this.allocUnsafe(BLOCK_SIZE);
77
+ this.writeValue(value);
78
+ return this.getResult();
79
+ } catch (e) {
80
+ this.cleanResult();
81
+ throw e;
82
+ }
83
+ }
84
+
85
+ /** 获取写入结果 */
86
+ encodeMany(value: Iterable<unknown>): Uint8Array {
87
+ try {
88
+ this.allocUnsafe(BLOCK_SIZE);
89
+ for (const v of value) {
90
+ this.writeValue(v);
91
+ }
92
+ return this.getResult();
93
+ } catch (e) {
94
+ this.cleanResult();
95
+ throw e;
96
+ }
97
+ }
68
98
  }
69
99
 
70
100
  let _ENCODER: Encoder | undefined;
package/src/index.ts CHANGED
@@ -1,14 +1,29 @@
1
1
  import { getEncoder } from './encoder.js';
2
- import { Decoder } from './decoder.js';
2
+ import { Decoder, type DecoderOptions } from './decoder.js';
3
3
  export { UnexpectedEof } from './utils.js';
4
4
 
5
+ export type { DecoderOptions };
6
+
5
7
  /** 编码为 UBJSON */
6
8
  export function encode(value: unknown): Uint8Array {
7
9
  return getEncoder().encode(value);
8
10
  }
9
11
 
12
+ /** 编码为 UBJSON */
13
+ export function encodeMany(value: Iterable<unknown>): Uint8Array {
14
+ return getEncoder().encodeMany(value);
15
+ }
16
+
10
17
  /** 解码 UBJSON */
11
- export function decode(value: BinaryData): unknown {
12
- const decoder = new Decoder(value);
18
+ export function decode(value: BinaryData, options?: DecoderOptions): unknown {
19
+ const decoder = new Decoder(value, options);
13
20
  return decoder.decode();
14
21
  }
22
+
23
+ /** 解码 UBJSON */
24
+ export function* decodeMany(value: BinaryData, options?: DecoderOptions): Iterable<unknown> {
25
+ const decoder = new Decoder(value, options);
26
+ while (!decoder.ended) {
27
+ yield decoder.decode();
28
+ }
29
+ }
@@ -14,6 +14,22 @@ export function encode(value: unknown): Readable {
14
14
  encoder.end();
15
15
  return encoder;
16
16
  }
17
+ /** 编码为 UBJSON */
18
+ export function encodeMany(value: AsyncIterable<unknown>): Readable {
19
+ const encoder = new StreamEncoder();
20
+ void (async () => {
21
+ try {
22
+ for await (const v of value) {
23
+ if (v == null) encoder.write(undefined);
24
+ else encoder.write(v);
25
+ }
26
+ encoder.end();
27
+ } catch (ex) {
28
+ encoder.destroy(ex as Error);
29
+ }
30
+ })();
31
+ return encoder;
32
+ }
17
33
 
18
34
  /** 编码为 UBJSON */
19
35
  export function encoder(): Transform {
@@ -31,6 +47,12 @@ export function decode(stream: NodeJS.ReadableStream): Promise<unknown> {
31
47
  });
32
48
  }
33
49
 
50
+ /** 解码 UBJSON */
51
+ export function decodeMany(stream: NodeJS.ReadableStream): AsyncIterable<unknown> {
52
+ const decoder = new StreamDecoder();
53
+ return stream.pipe(decoder);
54
+ }
55
+
34
56
  /** 解码 UBJSON */
35
57
  export function decoder(): Transform {
36
58
  return new StreamDecoder();
@@ -1,10 +1,10 @@
1
- import { Decoder } from '../common/decoder.js';
1
+ import { DecoderBase } from '../common/decoder.js';
2
2
 
3
3
  /** 未结束的流 */
4
4
  export const kEof = Symbol('EOF');
5
5
 
6
6
  /** 流式解码 UBJSON */
7
- export class StreamDecoderHelper extends Decoder {
7
+ export class StreamDecoderHelper extends DecoderBase {
8
8
  constructor(data: Uint8Array) {
9
9
  super(data);
10
10
  }
package/tests/decode.js CHANGED
@@ -54,8 +54,9 @@ test('decode int32', () => {
54
54
  expect(decode(toBuffer('l', 0x12, 0x34, 0x56, 0x78))).toBe(0x1234_5678);
55
55
  });
56
56
 
57
- test('decode int64 [error]', () => {
58
- expect(() => decode(toBuffer('L', 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0))).toThrow();
57
+ test('decode int64', () => {
58
+ expect(decode(toBuffer('L', 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0))).toBe(0x1234_5678_9abc_def0n);
59
+ expect(decode(toBuffer('L', 0x00, 0x04, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0))).toBe(0x04_5678_9abc_def0);
59
60
  });
60
61
 
61
62
  test('decode float32', () => {
@@ -156,9 +157,10 @@ test('decode huge string', () => {
156
157
  expect(decode(toBuffer('S', 'l', 0x00, 0x00, 0x00, 6, 'u', 'b', 'j', 's', 'o', 'n'))).toBe('ubjson');
157
158
  });
158
159
 
159
- test('decode huge string [error]', () => {
160
- expect(() => decode(toBuffer('S', 'L', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 'x'))).toThrow(
161
- /Unsupported type int64/,
160
+ test('decode huge string [int64 length]', () => {
161
+ expect(decode(toBuffer('S', 'L', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 'x'))).toBe('x');
162
+ expect(() => decode(toBuffer('S', 'L', 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 'x'))).toThrow(
163
+ /Invalid length/,
162
164
  );
163
165
  });
164
166
 
@@ -200,6 +202,24 @@ test('decode N-D array (strongly typed, optimized)', () => {
200
202
  ).toEqual([new Int8Array([1, 2, 3]), new Int8Array([4, 5, 6])]);
201
203
  });
202
204
 
205
+ test('decode N-D array (strongly typed, optimized, no alloc buffer)', () => {
206
+ const buf = toBuffer('[', '$', '[', '#', 'i', 2, '$', 'i', '#', 'i', 3, 1, 2, 3, '$', 'U', '#', 'U', 3, 4, 5, 6);
207
+
208
+ const decoded1 = /** @type {[Int8Array, Uint8Array]} */ (decode(buf));
209
+ const decoded2 = /** @type {[Int8Array, Uint8Array]} */ (decode(buf, { noAllocBuffer: true }));
210
+ // @ts-expect-error Falsy value
211
+ const decoded3 = /** @type {[Int8Array, Uint8Array]} */ (decode(buf, { noAllocBuffer: 0 }));
212
+ expect(decoded1).toEqual([new Int8Array([1, 2, 3]), new Uint8Array([4, 5, 6])]);
213
+ expect(decoded2).toEqual([new Int8Array([1, 2, 3]), new Uint8Array([4, 5, 6])]);
214
+ expect(decoded3).toEqual([new Int8Array([1, 2, 3]), new Uint8Array([4, 5, 6])]);
215
+ expect(decoded1[0].buffer).not.toBe(buf.buffer);
216
+ expect(decoded1[1].buffer).not.toBe(buf.buffer);
217
+ expect(decoded2[0].buffer).not.toBe(buf.buffer);
218
+ expect(decoded2[1].buffer).toBe(buf.buffer);
219
+ expect(decoded3[0].buffer).not.toBe(buf.buffer);
220
+ expect(decoded3[1].buffer).not.toBe(buf.buffer);
221
+ });
222
+
203
223
  test('decode array of objects (optimized)', () => {
204
224
  expect(
205
225
  decode(
@@ -389,13 +409,13 @@ test('decode array (int32, strongly typed, optimized) [use typed array]', () =>
389
409
  });
390
410
 
391
411
  test('decode array (int64, strongly typed, optimized) [use typed array]', () => {
392
- expect(() =>
393
- decode(toBuffer('[', '$', 'L', '#', 'i', 1, 0x12, 0x34, 0x56, 0x78, 0xfe, 0xdc, 0xba, 0x98)),
394
- ).toThrow();
412
+ expect(decode(toBuffer('[', '$', 'L', '#', 'i', 1, 0x12, 0x34, 0x56, 0x78, 0xfe, 0xdc, 0xba, 0x98))).toEqual(
413
+ new BigInt64Array([0x1234_5678_fedc_ba98n]),
414
+ );
395
415
  });
396
416
 
397
417
  test('decode array (int64, strongly typed, optimized, empty) [use typed array]', () => {
398
- expect(() => decode(toBuffer('[', '$', 'L', '#', 'i', 0))).toThrow();
418
+ expect(decode(toBuffer('[', '$', 'L', '#', 'i', 0))).toEqual(new BigInt64Array([]));
399
419
  });
400
420
 
401
421
  test('decode array (float32, strongly typed, optimized) [use typed array]', () => {
@@ -492,3 +512,13 @@ test('decode object (empty key, optimized)', () => {
492
512
  b: null,
493
513
  });
494
514
  });
515
+
516
+ test('decode (eof at marker)', () => {
517
+ expect(() => decode(toBuffer('i'))).toThrow(UnexpectedEof);
518
+ expect(() => decode(toBuffer('{'))).toThrow(UnexpectedEof);
519
+ expect(() => decode(toBuffer('{', 'i', 1, 'a'))).toThrow(UnexpectedEof);
520
+ });
521
+
522
+ test('decode (eof at key)', () => {
523
+ expect(() => decode(toBuffer('{', 'i', 2, 'a'))).toThrow(UnexpectedEof);
524
+ });
package/tests/encode.js CHANGED
@@ -20,7 +20,11 @@ test('encode function', () => {
20
20
  });
21
21
 
22
22
  test('encode bigint', () => {
23
- expect(() => encode(1n)).toThrow();
23
+ expect(toArray(encode(1n))).toEqual(toArray(encode(1)));
24
+ expect(toArray(encode(0x1234_5678_90ab_cdefn))).toEqual(
25
+ toArray('L', 0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef),
26
+ );
27
+ expect(() => encode(0x8234_5678_90ab_cdefn)).toThrow(/BigInt value out of range:/);
24
28
  // @ts-expect-error Access private property
25
29
  expect(getEncoder().pool).toBe(poolInit);
26
30
  });
@@ -365,7 +369,32 @@ test('encode array (uint64 typed array)', () => {
365
369
  });
366
370
 
367
371
  test('encode array (int64 typed array)', () => {
368
- expect(() => encode(new BigInt64Array())).toThrow();
372
+ expect(toArray(encode(new BigInt64Array([1n, 0x1234_5678_1234_5678n])))).toEqual(
373
+ toArray(
374
+ '[',
375
+ '$',
376
+ 'L',
377
+ '#',
378
+ 'i',
379
+ 2,
380
+ 0x00,
381
+ 0x00,
382
+ 0x00,
383
+ 0x00,
384
+ 0x00,
385
+ 0x00,
386
+ 0x00,
387
+ 0x01,
388
+ 0x12,
389
+ 0x34,
390
+ 0x56,
391
+ 0x78,
392
+ 0x12,
393
+ 0x34,
394
+ 0x56,
395
+ 0x78,
396
+ ),
397
+ );
369
398
  // @ts-expect-error Access private property
370
399
  expect(getEncoder().pool).toBe(poolInit);
371
400
  });
package/tests/many.js ADDED
@@ -0,0 +1,44 @@
1
+ import { encodeMany, decodeMany } from '../dist/index.js';
2
+
3
+ test('encode/decode many', () => {
4
+ const data = [
5
+ {
6
+ a: 1,
7
+ b: 2,
8
+ c: 3,
9
+ d: 4,
10
+ e: 5,
11
+ },
12
+ 1,
13
+ null,
14
+ 'x',
15
+ true,
16
+ [1, 2, 3],
17
+ Uint8Array.of(3, 3, 1),
18
+ ];
19
+ const encoded = encodeMany(data);
20
+ const decoded = [...decodeMany(encoded)];
21
+ expect(decoded).toEqual(data);
22
+ });
23
+
24
+ test('encode/decode many with error', () => {
25
+ expect(() =>
26
+ encodeMany(
27
+ (function* () {
28
+ yield 1;
29
+ throw new Error('xx');
30
+ })(),
31
+ ),
32
+ ).toThrow('xx');
33
+ });
34
+
35
+ test('encode/decode many with invalid value', () => {
36
+ expect(() => encodeMany([1, () => 1])).toThrow();
37
+ });
38
+
39
+ test('encode/decode many with undefined', () => {
40
+ const data = [1, null, undefined, [undefined]];
41
+ const encoded = encodeMany(data);
42
+ const decoded = [...decodeMany(encoded)];
43
+ expect(decoded).toEqual([1, null, [null]]);
44
+ });
@@ -77,8 +77,9 @@ test('decode int32', async () => {
77
77
  expect(await decode(toBuffer('l', 0x12, 0x34, 0x56, 0x78))).toBe(0x1234_5678);
78
78
  });
79
79
 
80
- test('decode int64 [error]', async () => {
81
- await expect(() => decode(toBuffer('L', 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0))).rejects.toThrow();
80
+ test('decode int64', async () => {
81
+ expect(await decode(toBuffer('L', 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0))).toBe(0x1234_5678_9abc_def0n);
82
+ expect(await decode(toBuffer('L', 0x00, 0x00, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0))).toBe(0x5678_9abc_def0);
82
83
  });
83
84
 
84
85
  test('decode float32', async () => {
@@ -140,9 +141,10 @@ test('decode huge string', async () => {
140
141
  expect(await decode(toBuffer('S', 'l', 0x00, 0x00, 0x00, 6, 'u', 'b', 'j', 's', 'o', 'n'))).toBe('ubjson');
141
142
  });
142
143
 
143
- test('decode huge string [error]', async () => {
144
- await expect(() => decode(toBuffer('S', 'L', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 'x'))).rejects.toThrow(
145
- /Unsupported type int64/,
144
+ test('decode huge string [int64 length]', async () => {
145
+ expect(await decode(toBuffer('S', 'L', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 'x'))).toBe('x');
146
+ await expect(() => decode(toBuffer('S', 'L', 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 'x'))).rejects.toThrow(
147
+ /Invalid length/,
146
148
  );
147
149
  });
148
150
 
@@ -359,9 +361,9 @@ test('decode array (int32, strongly typed, optimized) [use typed array]', async
359
361
  });
360
362
 
361
363
  test('decode array (int64, strongly typed, optimized) [use typed array]', async () => {
362
- await expect(() =>
363
- decode(toBuffer('[', '$', 'L', '#', 'i', 1, 0x12, 0x34, 0x56, 0x78, 0xfe, 0xdc, 0xba, 0x98)),
364
- ).rejects.toThrow();
364
+ expect(await decode(toBuffer('[', '$', 'L', '#', 'i', 1, 0x12, 0x34, 0x56, 0x78, 0xfe, 0xdc, 0xba, 0x98))).toEqual(
365
+ new BigInt64Array([0x1234_5678_fedc_ba98n]),
366
+ );
365
367
  });
366
368
 
367
369
  test('decode array (float32, strongly typed, optimized) [use typed array]', async () => {
@@ -28,7 +28,11 @@ test('encode function', async () => {
28
28
  });
29
29
 
30
30
  test('encode bigint', async () => {
31
- await expect(() => encodeAsync(1n)).rejects.toThrow();
31
+ expect(toArray(await encodeAsync(1n))).toEqual(toArray('U', 1));
32
+ expect(toArray(await encodeAsync(0x1876_9876_1234_1234n))).toEqual(
33
+ toArray('L', 0x18, 0x76, 0x98, 0x76, 0x12, 0x34, 0x12, 0x34),
34
+ );
35
+ await expect(encodeAsync(0x8234_5678_90ab_cdefn)).rejects.toThrow(/BigInt value out of range:/);
32
36
  });
33
37
 
34
38
  test('encode symbol', async () => {
@@ -268,7 +272,7 @@ test('encode array (uint64 typed array)', async () => {
268
272
  });
269
273
 
270
274
  test('encode array (int64 typed array)', async () => {
271
- await expect(() => encodeAsync(new BigInt64Array())).rejects.toThrow();
275
+ expect(toArray(await encodeAsync(new BigInt64Array()))).toEqual(toArray('[', '$', 'L', '#', 'i', 0));
272
276
  });
273
277
 
274
278
  test('encode object', async () => {
@@ -72,8 +72,9 @@ test('decode int32', async () => {
72
72
  expect(await decode(toBuffer('l', 0x12, 0x34, 0x56, 0x78))).toBe(0x1234_5678);
73
73
  });
74
74
 
75
- test('decode int64 [error]', async () => {
76
- await expect(() => decode(toBuffer('L', 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0))).rejects.toThrow();
75
+ test('decode int64', async () => {
76
+ expect(await decode(toBuffer('L', 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0))).toBe(0x1234_5678_9abc_def0n);
77
+ expect(await decode(toBuffer('L', 0x00, 0x04, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0))).toBe(0x04_5678_9abc_def0);
77
78
  });
78
79
 
79
80
  test('decode float32', async () => {
@@ -126,9 +127,10 @@ test('decode huge string', async () => {
126
127
  expect(await decode(toBuffer('S', 'l', 0x00, 0x00, 0x00, 6, 'u', 'b', 'j', 's', 'o', 'n'))).toBe('ubjson');
127
128
  });
128
129
 
129
- test('decode huge string [error]', async () => {
130
- await expect(() => decode(toBuffer('S', 'L', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 'x'))).rejects.toThrow(
131
- /Unsupported type int64/,
130
+ test('decode huge string [int64 length]', async () => {
131
+ expect(await decode(toBuffer('S', 'L', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 'x'))).toBe('x');
132
+ await expect(() => decode(toBuffer('S', 'L', 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 'x'))).rejects.toThrow(
133
+ /Invalid length/,
132
134
  );
133
135
  });
134
136
 
@@ -345,9 +347,9 @@ test('decode array (int32, strongly typed, optimized) [use typed array]', async
345
347
  });
346
348
 
347
349
  test('decode array (int64, strongly typed, optimized) [use typed array]', async () => {
348
- await expect(() =>
349
- decode(toBuffer('[', '$', 'L', '#', 'i', 1, 0x12, 0x34, 0x56, 0x78, 0xfe, 0xdc, 0xba, 0x98)),
350
- ).rejects.toThrow();
350
+ expect(await decode(toBuffer('[', '$', 'L', '#', 'i', 1, 0x12, 0x34, 0x56, 0x78, 0xfe, 0xdc, 0xba, 0x98))).toEqual(
351
+ new BigInt64Array([0x1234_5678_fedc_ba98n]),
352
+ );
351
353
  });
352
354
 
353
355
  test('decode array (float32, strongly typed, optimized) [use typed array]', async () => {
@@ -23,7 +23,11 @@ test('encode function', async () => {
23
23
  });
24
24
 
25
25
  test('encode bigint', async () => {
26
- await expect(() => encodeAsync(1n)).rejects.toThrow();
26
+ expect(toArray(await encodeAsync(1n))).toEqual(toArray('U', 1));
27
+ expect(toArray(await encodeAsync(0x1234_5678_8765_4321n))).toEqual(
28
+ toArray('L', 0x12, 0x34, 0x56, 0x78, 0x87, 0x65, 0x43, 0x21),
29
+ );
30
+ await expect(encodeAsync(0x8234_5678_90ab_cdefn)).rejects.toThrow(/BigInt value out of range:/);
27
31
  });
28
32
 
29
33
  test('encode symbol', async () => {
@@ -263,7 +267,7 @@ test('encode array (uint64 typed array)', async () => {
263
267
  });
264
268
 
265
269
  test('encode array (int64 typed array)', async () => {
266
- await expect(() => encodeAsync(new BigInt64Array())).rejects.toThrow();
270
+ expect(toArray(await encodeAsync(new BigInt64Array()))).toEqual(toArray('[', '$', 'L', '#', 'i', 0));
267
271
  });
268
272
 
269
273
  test('encode object', async () => {