@cloudpss/ubjson 0.5.36 → 0.5.38
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.
- package/dist/base/decoder.d.ts +12 -0
- package/dist/base/decoder.js +26 -0
- package/dist/base/decoder.js.map +1 -0
- package/dist/{common → base}/encoder.d.ts +2 -6
- package/dist/{common → base}/encoder.js +71 -121
- package/dist/base/encoder.js.map +1 -0
- package/dist/decoder.d.ts +1 -2
- package/dist/decoder.js +1 -1
- package/dist/decoder.js.map +1 -1
- package/dist/encoder.d.ts +1 -1
- package/dist/encoder.js +11 -11
- package/dist/encoder.js.map +1 -1
- package/dist/{common → helper}/constants.js.map +1 -1
- package/dist/helper/decode.d.ts +49 -0
- package/dist/helper/decode.js +344 -0
- package/dist/helper/decode.js.map +1 -0
- package/dist/helper/encode.d.ts +20 -0
- package/dist/helper/encode.js +84 -0
- package/dist/helper/encode.js.map +1 -0
- package/dist/{common → helper}/errors.d.ts +4 -0
- package/dist/{common → helper}/errors.js +10 -2
- package/dist/helper/errors.js.map +1 -0
- package/dist/{common → helper}/string-decoder.js +1 -1
- package/dist/{common → helper}/string-decoder.js.map +1 -1
- package/dist/{common → helper}/string-encoder.js.map +1 -1
- package/dist/{utils.d.ts → helper/utils.d.ts} +0 -4
- package/dist/{utils.js → helper/utils.js} +0 -6
- package/dist/helper/utils.js.map +1 -0
- package/dist/index.d.ts +3 -5
- package/dist/index.js +5 -5
- package/dist/index.js.map +1 -1
- package/dist/rxjs/decoder.js +1 -1
- package/dist/rxjs/decoder.js.map +1 -1
- package/dist/rxjs/index.d.ts +1 -1
- package/dist/rxjs/index.js +1 -1
- package/dist/rxjs/index.js.map +1 -1
- package/dist/stream/index.d.ts +2 -2
- package/dist/stream/index.js +2 -2
- package/dist/stream/index.js.map +1 -1
- package/dist/stream-helper/decoder.d.ts +2 -3
- package/dist/stream-helper/decoder.js +3 -6
- package/dist/stream-helper/decoder.js.map +1 -1
- package/dist/stream-helper/encoder.d.ts +1 -1
- package/dist/stream-helper/encoder.js +15 -15
- package/dist/stream-helper/encoder.js.map +1 -1
- package/package.json +4 -4
- package/src/base/decoder.ts +27 -0
- package/src/{common → base}/encoder.ts +72 -116
- package/src/decoder.ts +1 -2
- package/src/encoder.ts +11 -11
- package/src/helper/decode.ts +362 -0
- package/src/helper/encode.ts +89 -0
- package/src/{common → helper}/errors.ts +12 -2
- package/src/{common → helper}/string-decoder.ts +1 -1
- package/src/{utils.ts → helper/utils.ts} +0 -7
- package/src/index.ts +6 -8
- package/src/rxjs/decoder.ts +1 -1
- package/src/rxjs/index.ts +1 -1
- package/src/stream/index.ts +3 -3
- package/src/stream-helper/decoder.ts +3 -6
- package/src/stream-helper/encoder.ts +16 -16
- package/tests/.utils.js +6 -4
- package/tests/decode.js +0 -18
- package/tests/e2e/no-encode-into.js +1 -1
- package/tests/encode.js +1 -1
- package/tests/huge-string.js +1 -0
- package/tests/rxjs/decode.js +14 -13
- package/tests/rxjs/encode.js +13 -12
- package/tests/stream/decode.js +15 -13
- package/tests/stream/encode.js +9 -8
- package/tests/stream/many.js +2 -1
- package/tests/string-encoding.js +4 -6
- package/benchmark-small.js +0 -81
- package/benchmark-string-decode.js +0 -41
- package/benchmark-string-encode.js +0 -32
- package/benchmark-string-size-caculation.js +0 -50
- package/benchmark.js +0 -50
- package/dist/common/decoder.d.ts +0 -45
- package/dist/common/decoder.js +0 -348
- package/dist/common/decoder.js.map +0 -1
- package/dist/common/encoder.js.map +0 -1
- package/dist/common/errors.js.map +0 -1
- package/dist/utils.js.map +0 -1
- package/src/common/decoder.ts +0 -356
- /package/dist/{common → helper}/constants.d.ts +0 -0
- /package/dist/{common → helper}/constants.js +0 -0
- /package/dist/{common → helper}/string-decoder.d.ts +0 -0
- /package/dist/{common → helper}/string-encoder.d.ts +0 -0
- /package/dist/{common → helper}/string-encoder.js +0 -0
- /package/src/{common → helper}/constants.ts +0 -0
- /package/src/{common → helper}/string-encoder.ts +0 -0
package/tests/.utils.js
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
|
-
import { resetEnv as resetDecoderEnv } from '../dist/
|
|
2
|
-
import { resetEnv as resetEncoderEnv } from '../dist/
|
|
1
|
+
import { resetEnv as resetDecoderEnv } from '../dist/helper/string-decoder.js';
|
|
2
|
+
import { resetEnv as resetEncoderEnv } from '../dist/helper/string-encoder.js';
|
|
3
3
|
import { resetEncoder } from '../dist/encoder.js';
|
|
4
|
+
import '../dist/helper/constants.js';
|
|
4
5
|
|
|
6
|
+
/**
|
|
7
|
+
* 重设所有环境
|
|
8
|
+
*/
|
|
5
9
|
export function resetEnv() {
|
|
6
10
|
resetDecoderEnv();
|
|
7
11
|
resetEncoderEnv();
|
|
@@ -10,7 +14,6 @@ export function resetEnv() {
|
|
|
10
14
|
|
|
11
15
|
/**
|
|
12
16
|
* 输入转为数字数组以便比较
|
|
13
|
-
*
|
|
14
17
|
* @param {[ArrayBuffer] | [Uint8Array] | (number | string)[]} args 输入
|
|
15
18
|
* @returns {number[]} 数字数组
|
|
16
19
|
*/
|
|
@@ -26,7 +29,6 @@ export function toArray(...args) {
|
|
|
26
29
|
|
|
27
30
|
/**
|
|
28
31
|
* 将数字或字符串转换为 Uint8Array
|
|
29
|
-
*
|
|
30
32
|
* @param {...string | number} args 数字或 char 的数组
|
|
31
33
|
* @returns {Uint8Array} Uint8Array
|
|
32
34
|
*/
|
package/tests/decode.js
CHANGED
|
@@ -202,24 +202,6 @@ test('decode N-D array (strongly typed, optimized)', () => {
|
|
|
202
202
|
).toEqual([new Int8Array([1, 2, 3]), new Int8Array([4, 5, 6])]);
|
|
203
203
|
});
|
|
204
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
|
-
|
|
223
205
|
test('decode array of objects (optimized)', () => {
|
|
224
206
|
expect(
|
|
225
207
|
decode(
|
|
@@ -4,7 +4,7 @@ import { encode, decode } from '../../dist/index.js';
|
|
|
4
4
|
|
|
5
5
|
describe('no encodeInto', () => {
|
|
6
6
|
// eslint-disable-next-line @typescript-eslint/unbound-method
|
|
7
|
-
const encodeInto = TextEncoder.prototype
|
|
7
|
+
const { encodeInto } = TextEncoder.prototype;
|
|
8
8
|
beforeAll(() => {
|
|
9
9
|
// @ts-expect-error 移除 encodeInto 以测试兼容性
|
|
10
10
|
TextEncoder.prototype.encodeInto = undefined;
|
package/tests/encode.js
CHANGED
|
@@ -157,7 +157,7 @@ test('encode string (len = 180)', () => {
|
|
|
157
157
|
|
|
158
158
|
test('encode string (no encodeInto)', () => {
|
|
159
159
|
// eslint-disable-next-line @typescript-eslint/unbound-method
|
|
160
|
-
const encodeInto = TextEncoder.prototype
|
|
160
|
+
const { encodeInto } = TextEncoder.prototype;
|
|
161
161
|
// @ts-expect-error 移除 encodeInto 以测试兼容性
|
|
162
162
|
TextEncoder.prototype.encodeInto = undefined;
|
|
163
163
|
expect(toArray(encode('ubjson'))).toEqual(toArray('S', 'i', 6, ...'ubjson'));
|
package/tests/huge-string.js
CHANGED
package/tests/rxjs/decode.js
CHANGED
|
@@ -5,11 +5,12 @@ import { jest } from '@jest/globals';
|
|
|
5
5
|
import { firstValueFrom, of, Subject } from 'rxjs';
|
|
6
6
|
import { decode as decodePipe } from '../../dist/rxjs/index.js';
|
|
7
7
|
import { toBuffer } from '../.utils.js';
|
|
8
|
-
import { UnexpectedEof } from '../../dist/
|
|
8
|
+
import { UnexpectedEofError as UnexpectedEof } from '../../dist/helper/errors.js';
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* 包装为 promise
|
|
12
12
|
* @param {Uint8Array} data ubjson 数据
|
|
13
|
+
* @returns {Promise<unknown>}
|
|
13
14
|
*/
|
|
14
15
|
async function decode(data) {
|
|
15
16
|
const readable = of(data);
|
|
@@ -21,7 +22,7 @@ async function decode(data) {
|
|
|
21
22
|
* @param {import("rxjs").Observable<Uint8Array>} observable ubjson 数据流
|
|
22
23
|
* @param {(data: unknown) => void} onData 数据回调
|
|
23
24
|
*/
|
|
24
|
-
function decodeStream(observable, onData) {
|
|
25
|
+
async function decodeStream(observable, onData) {
|
|
25
26
|
return /** @type {Promise<void>} */ (
|
|
26
27
|
new Promise((resolve, reject) => {
|
|
27
28
|
observable.pipe(decodePipe()).subscribe({
|
|
@@ -34,7 +35,7 @@ function decodeStream(observable, onData) {
|
|
|
34
35
|
}
|
|
35
36
|
|
|
36
37
|
test('decode unsupported type', async () => {
|
|
37
|
-
await expect(() => decode(toBuffer('!'))).rejects.toThrow();
|
|
38
|
+
await expect(async () => decode(toBuffer('!'))).rejects.toThrow();
|
|
38
39
|
});
|
|
39
40
|
|
|
40
41
|
test('decode undefined', async () => {
|
|
@@ -91,7 +92,7 @@ test('decode float64', async () => {
|
|
|
91
92
|
});
|
|
92
93
|
|
|
93
94
|
test('decode high-precision number [error]', async () => {
|
|
94
|
-
await expect(() => decode(toBuffer('H', 'i', 3, '1', '.', '1'))).rejects.toThrow();
|
|
95
|
+
await expect(async () => decode(toBuffer('H', 'i', 3, '1', '.', '1'))).rejects.toThrow();
|
|
95
96
|
});
|
|
96
97
|
|
|
97
98
|
test('decode char', async () => {
|
|
@@ -107,11 +108,11 @@ test('decode empty string', async () => {
|
|
|
107
108
|
});
|
|
108
109
|
|
|
109
110
|
test('decode string (bad size) [error]', async () => {
|
|
110
|
-
await expect(() => decode(toBuffer('S', 'i', 0xff, 'x'))).rejects.toThrow(/Invalid length/);
|
|
111
|
+
await expect(async () => decode(toBuffer('S', 'i', 0xff, 'x'))).rejects.toThrow(/Invalid length/);
|
|
111
112
|
});
|
|
112
113
|
|
|
113
114
|
test('decode string (unexpected eof) [error]', async () => {
|
|
114
|
-
await expect(() => decode(toBuffer('S', 'i', 2, 'x'))).rejects.toThrow(UnexpectedEof);
|
|
115
|
+
await expect(async () => decode(toBuffer('S', 'i', 2, 'x'))).rejects.toThrow(UnexpectedEof);
|
|
115
116
|
});
|
|
116
117
|
|
|
117
118
|
test('decode ascii string', async () => {
|
|
@@ -143,9 +144,9 @@ test('decode huge string', async () => {
|
|
|
143
144
|
|
|
144
145
|
test('decode huge string [int64 length]', async () => {
|
|
145
146
|
expect(await decode(toBuffer('S', 'L', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 'x'))).toBe('x');
|
|
146
|
-
await expect(() =>
|
|
147
|
-
|
|
148
|
-
);
|
|
147
|
+
await expect(async () =>
|
|
148
|
+
decode(toBuffer('S', 'L', 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 'x')),
|
|
149
|
+
).rejects.toThrow(/Invalid length/);
|
|
149
150
|
});
|
|
150
151
|
|
|
151
152
|
test('decode array', async () => {
|
|
@@ -309,19 +310,19 @@ test('decode array of objects of arrays (optimized)', async () => {
|
|
|
309
310
|
});
|
|
310
311
|
|
|
311
312
|
test('decode array (strongly typed, unexpected eof, optimized)', async () => {
|
|
312
|
-
await expect(() => decode(toBuffer('[', '$', 'i', '#', 'i', 3, 1, 2))).rejects.toThrow(UnexpectedEof);
|
|
313
|
+
await expect(async () => decode(toBuffer('[', '$', 'i', '#', 'i', 3, 1, 2))).rejects.toThrow(UnexpectedEof);
|
|
313
314
|
});
|
|
314
315
|
|
|
315
316
|
test('decode array (strongly typed, invalid length value, optimized)', async () => {
|
|
316
|
-
await expect(() => decode(toBuffer('[', '$', 'i', '#', 'i', -1))).rejects.toThrow();
|
|
317
|
+
await expect(async () => decode(toBuffer('[', '$', 'i', '#', 'i', -1))).rejects.toThrow();
|
|
317
318
|
});
|
|
318
319
|
|
|
319
320
|
test('decode array (strongly typed, invalid length type, optimized)', async () => {
|
|
320
|
-
await expect(() => decode(toBuffer('[', '$', 'i', '#', 'C', '0'))).rejects.toThrow();
|
|
321
|
+
await expect(async () => decode(toBuffer('[', '$', 'i', '#', 'C', '0'))).rejects.toThrow();
|
|
321
322
|
});
|
|
322
323
|
|
|
323
324
|
test('decode array (strongly typed, malformed, optimized)', async () => {
|
|
324
|
-
await expect(() => decode(toBuffer('[', '$', 'i', 1, 2, 3, ']'))).rejects.toThrow();
|
|
325
|
+
await expect(async () => decode(toBuffer('[', '$', 'i', 1, 2, 3, ']'))).rejects.toThrow();
|
|
325
326
|
});
|
|
326
327
|
|
|
327
328
|
test('decode array (only null values, optimized)', async () => {
|
package/tests/rxjs/encode.js
CHANGED
|
@@ -9,8 +9,9 @@ import { toArray } from '../.utils.js';
|
|
|
9
9
|
/**
|
|
10
10
|
* 包装为 promise
|
|
11
11
|
* @param {unknown} value 要编码的值
|
|
12
|
+
* @returns {Promise<Buffer>}
|
|
12
13
|
*/
|
|
13
|
-
function encodeAsync(value) {
|
|
14
|
+
async function encodeAsync(value) {
|
|
14
15
|
return firstValueFrom(
|
|
15
16
|
of(value).pipe(
|
|
16
17
|
encode(),
|
|
@@ -21,7 +22,7 @@ function encodeAsync(value) {
|
|
|
21
22
|
}
|
|
22
23
|
|
|
23
24
|
test('encode function', async () => {
|
|
24
|
-
await expect(() =>
|
|
25
|
+
await expect(async () =>
|
|
25
26
|
encodeAsync(function () {
|
|
26
27
|
// noop
|
|
27
28
|
}),
|
|
@@ -37,7 +38,7 @@ test('encode bigint', async () => {
|
|
|
37
38
|
});
|
|
38
39
|
|
|
39
40
|
test('encode symbol', async () => {
|
|
40
|
-
await expect(() => encodeAsync(Symbol('sym'))).rejects.toThrow();
|
|
41
|
+
await expect(async () => encodeAsync(Symbol('sym'))).rejects.toThrow();
|
|
41
42
|
});
|
|
42
43
|
|
|
43
44
|
test('encode undefined', async () => {
|
|
@@ -113,7 +114,7 @@ test('encode huge string', async () => {
|
|
|
113
114
|
|
|
114
115
|
test('encode string (no encodeInto)', async () => {
|
|
115
116
|
// eslint-disable-next-line @typescript-eslint/unbound-method
|
|
116
|
-
const encodeInto = TextEncoder.prototype
|
|
117
|
+
const { encodeInto } = TextEncoder.prototype;
|
|
117
118
|
// @ts-expect-error 移除 encodeInto 以测试兼容性
|
|
118
119
|
TextEncoder.prototype.encodeInto = undefined;
|
|
119
120
|
expect(toArray(await encodeAsync('ubjson'))).toEqual(toArray('S', 'i', 6, 'u', 'b', 'j', 's', 'o', 'n'));
|
|
@@ -257,19 +258,19 @@ test('encode array (float64 typed array)', async () => {
|
|
|
257
258
|
});
|
|
258
259
|
|
|
259
260
|
test('encode array (uint8clamped typed array)', async () => {
|
|
260
|
-
await expect(() => encodeAsync(new Uint8ClampedArray())).rejects.toThrow();
|
|
261
|
+
await expect(async () => encodeAsync(new Uint8ClampedArray())).rejects.toThrow();
|
|
261
262
|
});
|
|
262
263
|
|
|
263
264
|
test('encode array (uint16 typed array)', async () => {
|
|
264
|
-
await expect(() => encodeAsync(new Uint16Array())).rejects.toThrow();
|
|
265
|
+
await expect(async () => encodeAsync(new Uint16Array())).rejects.toThrow();
|
|
265
266
|
});
|
|
266
267
|
|
|
267
268
|
test('encode array (uint32 typed array)', async () => {
|
|
268
|
-
await expect(() => encodeAsync(new Uint32Array())).rejects.toThrow();
|
|
269
|
+
await expect(async () => encodeAsync(new Uint32Array())).rejects.toThrow();
|
|
269
270
|
});
|
|
270
271
|
|
|
271
272
|
test('encode array (uint64 typed array)', async () => {
|
|
272
|
-
await expect(() => encodeAsync(new BigUint64Array())).rejects.toThrow();
|
|
273
|
+
await expect(async () => encodeAsync(new BigUint64Array())).rejects.toThrow();
|
|
273
274
|
});
|
|
274
275
|
|
|
275
276
|
test('encode array (int64 typed array)', async () => {
|
|
@@ -303,10 +304,10 @@ test('encode object (only null values)', async () => {
|
|
|
303
304
|
});
|
|
304
305
|
|
|
305
306
|
test('encode object (skip prototype)', async () => {
|
|
306
|
-
const obj = Object.create({ a: 2, x: 'xx' });
|
|
307
|
-
obj
|
|
308
|
-
obj
|
|
309
|
-
obj
|
|
307
|
+
const obj = /** @type {Record<string, unknown>} */ (Object.create({ a: 2, x: 'xx' }));
|
|
308
|
+
obj['a'] = 1;
|
|
309
|
+
obj['b'] = 'a';
|
|
310
|
+
obj['c'] = true;
|
|
310
311
|
expect(toArray(await encodeAsync(obj))).toEqual(
|
|
311
312
|
toArray('{', 'i', 1, 'a', 'U', 1, 'i', 1, 'b', 'C', 'a', 'i', 1, 'c', 'T', '}'),
|
|
312
313
|
);
|
package/tests/stream/decode.js
CHANGED
|
@@ -5,11 +5,12 @@ import { jest } from '@jest/globals';
|
|
|
5
5
|
import { Readable } from 'node:stream';
|
|
6
6
|
import { decoder as decodeStream, decode as decodeAsync } from '../../dist/stream/index.js';
|
|
7
7
|
import { toBuffer } from '../.utils.js';
|
|
8
|
-
import { UnexpectedEof } from '../../dist/
|
|
8
|
+
import { UnexpectedEofError as UnexpectedEof } from '../../dist/helper/errors.js';
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* 包装为 promise
|
|
12
12
|
* @param {Uint8Array} data ubjson 数据
|
|
13
|
+
* @returns {Promise<unknown>}
|
|
13
14
|
*/
|
|
14
15
|
async function decode(data) {
|
|
15
16
|
const readable = Readable.from([data], { objectMode: false });
|
|
@@ -19,8 +20,9 @@ async function decode(data) {
|
|
|
19
20
|
/**
|
|
20
21
|
* 包装为 promise
|
|
21
22
|
* @param {import("stream").Transform} stream ubjson 流
|
|
23
|
+
* @returns {Promise<void>}
|
|
22
24
|
*/
|
|
23
|
-
function eos(stream) {
|
|
25
|
+
async function eos(stream) {
|
|
24
26
|
return new Promise((resolve, reject) => {
|
|
25
27
|
stream.on('error', reject);
|
|
26
28
|
stream.on('end', resolve);
|
|
@@ -28,7 +30,7 @@ function eos(stream) {
|
|
|
28
30
|
}
|
|
29
31
|
|
|
30
32
|
test('decode unsupported type', async () => {
|
|
31
|
-
await expect(() => decode(toBuffer('!'))).rejects.toThrow();
|
|
33
|
+
await expect(async () => decode(toBuffer('!'))).rejects.toThrow();
|
|
32
34
|
});
|
|
33
35
|
|
|
34
36
|
test('decode undefined', async () => {
|
|
@@ -86,7 +88,7 @@ test('decode float64', async () => {
|
|
|
86
88
|
});
|
|
87
89
|
|
|
88
90
|
test('decode high-precision number [error]', async () => {
|
|
89
|
-
await expect(() => decode(toBuffer('H', 'i', 3, '1', '.', '1'))).rejects.toThrow();
|
|
91
|
+
await expect(async () => decode(toBuffer('H', 'i', 3, '1', '.', '1'))).rejects.toThrow();
|
|
90
92
|
});
|
|
91
93
|
|
|
92
94
|
test('decode char', async () => {
|
|
@@ -102,11 +104,11 @@ test('decode empty string', async () => {
|
|
|
102
104
|
});
|
|
103
105
|
|
|
104
106
|
test('decode string (bad size) [error]', async () => {
|
|
105
|
-
await expect(() => decode(toBuffer('S', 'i', 0xff, 'x'))).rejects.toThrow(/Invalid length/);
|
|
107
|
+
await expect(async () => decode(toBuffer('S', 'i', 0xff, 'x'))).rejects.toThrow(/Invalid length/);
|
|
106
108
|
});
|
|
107
109
|
|
|
108
110
|
test('decode string (unexpected eof) [error]', async () => {
|
|
109
|
-
await expect(() => decode(toBuffer('S', 'i', 2, 'x'))).rejects.toThrow(UnexpectedEof);
|
|
111
|
+
await expect(async () => decode(toBuffer('S', 'i', 2, 'x'))).rejects.toThrow(UnexpectedEof);
|
|
110
112
|
});
|
|
111
113
|
|
|
112
114
|
test('decode ascii string', async () => {
|
|
@@ -129,9 +131,9 @@ test('decode huge string', async () => {
|
|
|
129
131
|
|
|
130
132
|
test('decode huge string [int64 length]', async () => {
|
|
131
133
|
expect(await decode(toBuffer('S', 'L', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 'x'))).toBe('x');
|
|
132
|
-
await expect(() =>
|
|
133
|
-
|
|
134
|
-
);
|
|
134
|
+
await expect(async () =>
|
|
135
|
+
decode(toBuffer('S', 'L', 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 'x')),
|
|
136
|
+
).rejects.toThrow(/Invalid length/);
|
|
135
137
|
});
|
|
136
138
|
|
|
137
139
|
test('decode array', async () => {
|
|
@@ -295,19 +297,19 @@ test('decode array of objects of arrays (optimized)', async () => {
|
|
|
295
297
|
});
|
|
296
298
|
|
|
297
299
|
test('decode array (strongly typed, unexpected eof, optimized)', async () => {
|
|
298
|
-
await expect(() => decode(toBuffer('[', '$', 'i', '#', 'i', 3, 1, 2))).rejects.toThrow();
|
|
300
|
+
await expect(async () => decode(toBuffer('[', '$', 'i', '#', 'i', 3, 1, 2))).rejects.toThrow();
|
|
299
301
|
});
|
|
300
302
|
|
|
301
303
|
test('decode array (strongly typed, invalid length value, optimized)', async () => {
|
|
302
|
-
await expect(() => decode(toBuffer('[', '$', 'i', '#', 'i', -1))).rejects.toThrow();
|
|
304
|
+
await expect(async () => decode(toBuffer('[', '$', 'i', '#', 'i', -1))).rejects.toThrow();
|
|
303
305
|
});
|
|
304
306
|
|
|
305
307
|
test('decode array (strongly typed, invalid length type, optimized)', async () => {
|
|
306
|
-
await expect(() => decode(toBuffer('[', '$', 'i', '#', 'C', '0'))).rejects.toThrow();
|
|
308
|
+
await expect(async () => decode(toBuffer('[', '$', 'i', '#', 'C', '0'))).rejects.toThrow();
|
|
307
309
|
});
|
|
308
310
|
|
|
309
311
|
test('decode array (strongly typed, malformed, optimized)', async () => {
|
|
310
|
-
await expect(() => decode(toBuffer('[', '$', 'i', 1, 2, 3, ']'))).rejects.toThrow();
|
|
312
|
+
await expect(async () => decode(toBuffer('[', '$', 'i', 1, 2, 3, ']'))).rejects.toThrow();
|
|
311
313
|
});
|
|
312
314
|
|
|
313
315
|
test('decode array (only null values, optimized)', async () => {
|
package/tests/stream/encode.js
CHANGED
|
@@ -9,13 +9,14 @@ import { toArray } from '../.utils.js';
|
|
|
9
9
|
/**
|
|
10
10
|
* 包装为 promise
|
|
11
11
|
* @param {unknown} value 值
|
|
12
|
+
* @returns {Promise<Buffer>} 返回值
|
|
12
13
|
*/
|
|
13
|
-
function encodeAsync(value) {
|
|
14
|
+
async function encodeAsync(value) {
|
|
14
15
|
return buffer(encode(value));
|
|
15
16
|
}
|
|
16
17
|
|
|
17
18
|
test('encode function', async () => {
|
|
18
|
-
await expect(() =>
|
|
19
|
+
await expect(async () =>
|
|
19
20
|
encodeAsync(function () {
|
|
20
21
|
// noop
|
|
21
22
|
}),
|
|
@@ -31,7 +32,7 @@ test('encode bigint', async () => {
|
|
|
31
32
|
});
|
|
32
33
|
|
|
33
34
|
test('encode symbol', async () => {
|
|
34
|
-
await expect(() => encodeAsync(Symbol('sym'))).rejects.toThrow();
|
|
35
|
+
await expect(async () => encodeAsync(Symbol('sym'))).rejects.toThrow();
|
|
35
36
|
});
|
|
36
37
|
|
|
37
38
|
test('encode undefined', async () => {
|
|
@@ -107,7 +108,7 @@ test('encode huge string', async () => {
|
|
|
107
108
|
|
|
108
109
|
test('encode string (no encodeInto)', async () => {
|
|
109
110
|
// eslint-disable-next-line @typescript-eslint/unbound-method
|
|
110
|
-
const encodeInto = TextEncoder.prototype
|
|
111
|
+
const { encodeInto } = TextEncoder.prototype;
|
|
111
112
|
// @ts-expect-error 移除 encodeInto 以测试兼容性
|
|
112
113
|
TextEncoder.prototype.encodeInto = undefined;
|
|
113
114
|
expect(toArray(await encodeAsync('ubjson'))).toEqual(toArray('S', 'i', 6, 'u', 'b', 'j', 's', 'o', 'n'));
|
|
@@ -251,19 +252,19 @@ test('encode array (float64 typed array)', async () => {
|
|
|
251
252
|
});
|
|
252
253
|
|
|
253
254
|
test('encode array (uint8clamped typed array)', async () => {
|
|
254
|
-
await expect(() => encodeAsync(new Uint8ClampedArray())).rejects.toThrow();
|
|
255
|
+
await expect(async () => encodeAsync(new Uint8ClampedArray())).rejects.toThrow();
|
|
255
256
|
});
|
|
256
257
|
|
|
257
258
|
test('encode array (uint16 typed array)', async () => {
|
|
258
|
-
await expect(() => encodeAsync(new Uint16Array())).rejects.toThrow();
|
|
259
|
+
await expect(async () => encodeAsync(new Uint16Array())).rejects.toThrow();
|
|
259
260
|
});
|
|
260
261
|
|
|
261
262
|
test('encode array (uint32 typed array)', async () => {
|
|
262
|
-
await expect(() => encodeAsync(new Uint32Array())).rejects.toThrow();
|
|
263
|
+
await expect(async () => encodeAsync(new Uint32Array())).rejects.toThrow();
|
|
263
264
|
});
|
|
264
265
|
|
|
265
266
|
test('encode array (uint64 typed array)', async () => {
|
|
266
|
-
await expect(() => encodeAsync(new BigUint64Array())).rejects.toThrow();
|
|
267
|
+
await expect(async () => encodeAsync(new BigUint64Array())).rejects.toThrow();
|
|
267
268
|
});
|
|
268
269
|
|
|
269
270
|
test('encode array (int64 typed array)', async () => {
|
package/tests/stream/many.js
CHANGED
|
@@ -14,7 +14,8 @@ function iterableToAsyncIterable(iterable) {
|
|
|
14
14
|
[Symbol.asyncIterator]: () => {
|
|
15
15
|
const iterator = iterable[Symbol.iterator]();
|
|
16
16
|
return {
|
|
17
|
-
next
|
|
17
|
+
// eslint-disable-next-line unicorn/no-useless-promise-resolve-reject
|
|
18
|
+
next: async () => Promise.resolve(iterator.next()),
|
|
18
19
|
};
|
|
19
20
|
},
|
|
20
21
|
};
|
package/tests/string-encoding.js
CHANGED
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
import { Encoder } from '../dist/encoder.js';
|
|
2
|
-
import { decode, decodeKey, jsDecode } from '../dist/
|
|
3
|
-
import '../dist/common/constants.js';
|
|
2
|
+
import { decode, decodeKey, jsDecode } from '../dist/helper/string-decoder.js';
|
|
4
3
|
|
|
5
4
|
/**
|
|
6
5
|
* 测试编码
|
|
6
|
+
* @param {Pick<TextEncoder, 'encode'>} encoder encoder
|
|
7
|
+
* @param {Pick<TextDecoder, 'decode'>} decoder decoder
|
|
7
8
|
*/
|
|
8
|
-
function testEncoding(
|
|
9
|
-
/** @type {Pick<TextEncoder, 'encode'>} */ encoder,
|
|
10
|
-
/** @type {Pick<TextDecoder, 'decode'>} */ decoder,
|
|
11
|
-
) {
|
|
9
|
+
function testEncoding(encoder, decoder) {
|
|
12
10
|
expect(decoder.decode(encoder.encode(''))).toEqual('');
|
|
13
11
|
expect(decoder.decode(encoder.encode('a'))).toEqual('a');
|
|
14
12
|
expect(decoder.decode(encoder.encode('p4'))).toEqual('p4');
|
package/benchmark-small.js
DELETED
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
import { load } from '@cloudpss/yaml';
|
|
2
|
-
import { encode, decode } from './dist/index.js';
|
|
3
|
-
import { encode as encodeAsync } from './dist/stream/index.js';
|
|
4
|
-
import { encode as oldEncode, decode as oldDecode } from 'ref-impl';
|
|
5
|
-
import { encode as oldEncodeAsync } from 'ref-impl/stream';
|
|
6
|
-
import lodash from 'lodash';
|
|
7
|
-
|
|
8
|
-
const LOOP = 100000;
|
|
9
|
-
const WARM_UP = 10000;
|
|
10
|
-
|
|
11
|
-
const t = (/** @type {number} */ time) => (time * 1_000_000).toFixed(2).padStart(6) + 'ns';
|
|
12
|
-
|
|
13
|
-
/* eslint-disable no-console */
|
|
14
|
-
const obj = decode(
|
|
15
|
-
encode(
|
|
16
|
-
load(`
|
|
17
|
-
verb: create
|
|
18
|
-
type: plot
|
|
19
|
-
key: plot-0
|
|
20
|
-
version: 1
|
|
21
|
-
data: {title: 三台电机转速wr, traces: [{name: '#wr1:0', type: scatter, x: !!js/Float64Array +anx0k1iUD8AqvHSTWJgP/B+arx0k2g/8Knx0k1icD9oFK5H4Xp0P+B+arx0k3g/WOkmMQisfD/sqfHSTWKAPzzfT42XboI/jBSuR+F6hD8=, 'y': !!js/Float64Array AAAAAAAA8D8AAAAAAADwPwAAAAAAAPA/AAAAAAAA8D8AAAAAAADwPwAAAAAAAPA/AAAAAAAA8D8AAAAAAADwPwAAAAAAAPA/AAAAAAAA8D8=}, {name: '#wr2:0', type: scatter, x: !!js/Float64Array +anx0k1iUD8AqvHSTWJgP/B+arx0k2g/8Knx0k1icD9oFK5H4Xp0P+B+arx0k3g/WOkmMQisfD/sqfHSTWKAPzzfT42XboI/jBSuR+F6hD8=, 'y': !!js/Float64Array AAAAAAAA8D8AAAAAAADwPwAAAAAAAPA/AAAAAAAA8D8AAAAAAADwPwAAAAAAAPA/AAAAAAAA8D8AAAAAAADwPwAAAAAAAPA/AAAAAAAA8D8=}, {name: '#wr3:0', type: scatter, x: !!js/Float64Array +anx0k1iUD8AqvHSTWJgP/B+arx0k2g/8Knx0k1icD9oFK5H4Xp0P+B+arx0k3g/WOkmMQisfD/sqfHSTWKAPzzfT42XboI/jBSuR+F6hD8=, 'y': !!js/Float64Array AAAAAAAA8D8AAAAAAADwPwAAAAAAAPA/AAAAAAAA8D8AAAAAAADwPwAAAAAAAPA/AAAAAAAA8D8AAAAAAADwPwAAAAAAAPA/AAAAAAAA8D8=}]}
|
|
22
|
-
`),
|
|
23
|
-
),
|
|
24
|
-
);
|
|
25
|
-
|
|
26
|
-
const impl = [
|
|
27
|
-
['REF', oldEncode, oldDecode, oldEncodeAsync],
|
|
28
|
-
['CURRENT', encode, decode, encodeAsync],
|
|
29
|
-
];
|
|
30
|
-
|
|
31
|
-
async function run() {
|
|
32
|
-
let encodeTime = {};
|
|
33
|
-
let encodeAsyncTime = {};
|
|
34
|
-
let decodeTime = {};
|
|
35
|
-
let obj2 = {};
|
|
36
|
-
for (const [name] of impl) {
|
|
37
|
-
encodeTime[name] = 0;
|
|
38
|
-
encodeAsyncTime[name] = 0;
|
|
39
|
-
decodeTime[name] = 0;
|
|
40
|
-
}
|
|
41
|
-
for (let i = 0; i < WARM_UP; i++) {
|
|
42
|
-
for (const [, encode, decode, encodeAsync] of impl) {
|
|
43
|
-
const encoded = encode(obj);
|
|
44
|
-
for await (const _piece of encodeAsync(obj)) {
|
|
45
|
-
continue;
|
|
46
|
-
}
|
|
47
|
-
decode(encoded);
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
for (let i = 0; i < LOOP; i++) {
|
|
51
|
-
for (const [name, encode, decode, encodeAsync] of impl) {
|
|
52
|
-
let start = performance.now();
|
|
53
|
-
const encoded = encode(obj);
|
|
54
|
-
encodeTime[name] += performance.now() - start;
|
|
55
|
-
|
|
56
|
-
start = performance.now();
|
|
57
|
-
for await (const _piece of encodeAsync(obj)) {
|
|
58
|
-
continue;
|
|
59
|
-
}
|
|
60
|
-
encodeAsyncTime[name] += performance.now() - start;
|
|
61
|
-
|
|
62
|
-
start = performance.now();
|
|
63
|
-
obj2[name] = decode(encoded);
|
|
64
|
-
decodeTime[name] += performance.now() - start;
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
for (const [name] of impl) {
|
|
68
|
-
console.assert(lodash.isEqual(obj, obj2[name]));
|
|
69
|
-
}
|
|
70
|
-
for (const [name] of impl) {
|
|
71
|
-
console.log(
|
|
72
|
-
`${name}\tencode: ${t(encodeTime[name] / LOOP)}\tencode stream: ${t(
|
|
73
|
-
encodeAsyncTime[name] / LOOP,
|
|
74
|
-
)}\tdecode: ${t(decodeTime[name] / LOOP)}`,
|
|
75
|
-
);
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
await run();
|
|
80
|
-
|
|
81
|
-
console.log('');
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import { nativeDecode, decode, jsDecode } from './dist/common/string-decoder.js';
|
|
2
|
-
|
|
3
|
-
const LOOP = 500000;
|
|
4
|
-
|
|
5
|
-
const t = (/** @type {number} */ time) => time.toFixed(10) + 'ms';
|
|
6
|
-
|
|
7
|
-
/** 测试数据 */
|
|
8
|
-
function createTestData(/** @type {number} */ size) {
|
|
9
|
-
return new Uint8Array(size).fill(50);
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
/* eslint-disable no-console */
|
|
13
|
-
|
|
14
|
-
console.log(` Size\tTextDecoder MyStringDecoder my/sys%\tJsDecoder js/sys%`);
|
|
15
|
-
for (let index = 10; index < 1000; index = Math.trunc(index * 1.2)) {
|
|
16
|
-
const data = createTestData(index);
|
|
17
|
-
|
|
18
|
-
let decodeTimeSystem = 0;
|
|
19
|
-
let decodeTimeOptimal = 0;
|
|
20
|
-
let decodeTimeJs = 0;
|
|
21
|
-
for (let i = 0; i < LOOP; i++) {
|
|
22
|
-
let start = performance.now();
|
|
23
|
-
nativeDecode(data);
|
|
24
|
-
decodeTimeSystem += performance.now() - start;
|
|
25
|
-
|
|
26
|
-
start = performance.now();
|
|
27
|
-
decode(data, 0, data.byteLength);
|
|
28
|
-
decodeTimeOptimal += performance.now() - start;
|
|
29
|
-
|
|
30
|
-
start = performance.now();
|
|
31
|
-
jsDecode(data, 0, data.byteLength);
|
|
32
|
-
decodeTimeJs += performance.now() - start;
|
|
33
|
-
}
|
|
34
|
-
const ratioOptimal = decodeTimeOptimal / decodeTimeSystem;
|
|
35
|
-
const ratioJs = decodeTimeJs / decodeTimeSystem;
|
|
36
|
-
console.log(
|
|
37
|
-
`Data: ${data.byteLength} \t${t(decodeTimeSystem / LOOP)} ${t(decodeTimeOptimal / LOOP)} ${(
|
|
38
|
-
ratioOptimal * 100
|
|
39
|
-
).toFixed(3)}%\t${t(decodeTimeJs / LOOP)} ${(ratioJs * 100).toFixed(3)}%`,
|
|
40
|
-
);
|
|
41
|
-
}
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { jsEncodeInto, nativeEncodeInto } from './dist/common/string-encoder.js';
|
|
2
|
-
|
|
3
|
-
const LOOP = 500000;
|
|
4
|
-
|
|
5
|
-
const t = (/** @type {number} */ time) => time.toFixed(10) + 'ms';
|
|
6
|
-
|
|
7
|
-
/** 测试数据 */
|
|
8
|
-
function createTestData(/** @type {number} */ size) {
|
|
9
|
-
return ['a'.repeat(size), 'Ӓ'.repeat(size / 2), '水'.repeat(size / 3), 'aӒ水'.repeat(size / 6)];
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
/* eslint-disable no-console */
|
|
13
|
-
|
|
14
|
-
console.log(` Size\tnativeEncodeInto \tjsEncodeInto \tmy/sys%`);
|
|
15
|
-
for (let index = 10; index < 1000; index = Math.trunc(index * 1.2)) {
|
|
16
|
-
const data1 = createTestData(index)[0];
|
|
17
|
-
const buf = new Uint8Array(index + 10);
|
|
18
|
-
|
|
19
|
-
let encodeSystem = 0;
|
|
20
|
-
let encodeJs = 0;
|
|
21
|
-
for (let i = 0; i < LOOP; i++) {
|
|
22
|
-
let start = performance.now();
|
|
23
|
-
nativeEncodeInto(data1, buf, 1);
|
|
24
|
-
encodeSystem += performance.now() - start;
|
|
25
|
-
|
|
26
|
-
start = performance.now();
|
|
27
|
-
jsEncodeInto(data1, buf, 1);
|
|
28
|
-
encodeJs += performance.now() - start;
|
|
29
|
-
}
|
|
30
|
-
const ratioJs = encodeJs / encodeSystem;
|
|
31
|
-
console.log(`Data: ${index} \t${t(encodeSystem / LOOP)} ${t(encodeJs / LOOP)} ${(ratioJs * 100).toFixed(3)}%`);
|
|
32
|
-
}
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
import prettyBytes from 'pretty-bytes';
|
|
2
|
-
import { jsStringByteLength, nodeStringByteLength } from './dist/common/string-encoder.js';
|
|
3
|
-
|
|
4
|
-
const LOOP = 100;
|
|
5
|
-
|
|
6
|
-
const t = (/** @type {number} */ time) => time.toFixed(6) + 'ms';
|
|
7
|
-
const pb = (/** @type {number} */ size) => prettyBytes(size, { binary: true });
|
|
8
|
-
|
|
9
|
-
/** 测试数据 */
|
|
10
|
-
function createTestData(/** @type {number} */ size) {
|
|
11
|
-
return ['a'.repeat(size), 'Ӓ'.repeat(size / 2), '水'.repeat(size / 3), 'aӒ水'.repeat(size / 6)];
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
/* eslint-disable no-console */
|
|
15
|
-
|
|
16
|
-
console.log(`Size \tTime1 \tTime2 \tTime3 \tTimeMixed`);
|
|
17
|
-
|
|
18
|
-
for (const i of [8, 16, 32, 64, 256, 1024, 8192, 16384, 32768, 65536, 131072, 262144, 524288, 1048576]) {
|
|
19
|
-
const [data1, data2, data3, dataMixed] = createTestData(i);
|
|
20
|
-
for (const withBuffer of [true, false]) {
|
|
21
|
-
const encode = withBuffer ? nodeStringByteLength : jsStringByteLength;
|
|
22
|
-
let size;
|
|
23
|
-
let time1 = 0,
|
|
24
|
-
time2 = 0,
|
|
25
|
-
time3 = 0,
|
|
26
|
-
timeMixed = 0;
|
|
27
|
-
for (let i = 0; i < LOOP; i++) {
|
|
28
|
-
let start = performance.now();
|
|
29
|
-
size = encode(data1);
|
|
30
|
-
time1 += performance.now() - start;
|
|
31
|
-
|
|
32
|
-
start = performance.now();
|
|
33
|
-
size = encode(data2);
|
|
34
|
-
time2 += performance.now() - start;
|
|
35
|
-
|
|
36
|
-
start = performance.now();
|
|
37
|
-
size = encode(data3);
|
|
38
|
-
time3 += performance.now() - start;
|
|
39
|
-
|
|
40
|
-
start = performance.now();
|
|
41
|
-
size = encode(dataMixed);
|
|
42
|
-
timeMixed += performance.now() - start;
|
|
43
|
-
}
|
|
44
|
-
console.log(
|
|
45
|
-
`[${withBuffer ? 'w/ ' : 'w/o'} buffer] ${pb(size)}\t${t(time1 / LOOP)} \t${t(time2 / LOOP)} \t${t(
|
|
46
|
-
time3 / LOOP,
|
|
47
|
-
)} \t${t(timeMixed / LOOP)}`,
|
|
48
|
-
);
|
|
49
|
-
}
|
|
50
|
-
}
|