@cloudpss/ubjson 0.4.11 → 0.4.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.
Files changed (56) hide show
  1. package/benchmark-string.js +32 -32
  2. package/benchmark.js +33 -35
  3. package/dist/common/constants.d.ts +21 -21
  4. package/dist/common/constants.js +21 -21
  5. package/dist/common/decoder.d.ts +52 -52
  6. package/dist/common/decoder.js +277 -277
  7. package/dist/common/encoder.d.ts +74 -74
  8. package/dist/common/encoder.js +282 -282
  9. package/dist/common/string-decoder.d.ts +13 -13
  10. package/dist/common/string-decoder.js +106 -106
  11. package/dist/common/string-encoder.d.ts +6 -6
  12. package/dist/common/string-encoder.js +37 -37
  13. package/dist/decoder.d.ts +2 -2
  14. package/dist/decoder.js +2 -2
  15. package/dist/encoder.d.ts +11 -11
  16. package/dist/encoder.js +77 -77
  17. package/dist/index.d.ts +6 -6
  18. package/dist/index.js +15 -15
  19. package/dist/rxjs/decoder.d.ts +3 -3
  20. package/dist/rxjs/decoder.js +69 -69
  21. package/dist/rxjs/decoder.js.map +1 -1
  22. package/dist/rxjs/encoder.d.ts +3 -3
  23. package/dist/rxjs/encoder.js +27 -27
  24. package/dist/rxjs/encoder.js.map +1 -1
  25. package/dist/rxjs/index.d.ts +2 -2
  26. package/dist/rxjs/index.js +2 -2
  27. package/dist/stream/decoder.d.ts +13 -13
  28. package/dist/stream/decoder.js +51 -51
  29. package/dist/stream/decoder.js.map +1 -1
  30. package/dist/stream/encoder.d.ts +9 -9
  31. package/dist/stream/encoder.js +22 -22
  32. package/dist/stream/encoder.js.map +1 -1
  33. package/dist/stream/index.d.ts +11 -11
  34. package/dist/stream/index.js +31 -31
  35. package/dist/stream/index.js.map +1 -1
  36. package/dist/stream-helper/decoder.d.ts +8 -8
  37. package/dist/stream-helper/decoder.js +12 -12
  38. package/dist/stream-helper/encoder.d.ts +12 -12
  39. package/dist/stream-helper/encoder.js +56 -56
  40. package/dist/utils.d.ts +2 -2
  41. package/dist/utils.js +7 -7
  42. package/package.json +3 -2
  43. package/src/rxjs/decoder.ts +1 -1
  44. package/src/rxjs/encoder.ts +1 -1
  45. package/src/stream/decoder.ts +1 -1
  46. package/src/stream/encoder.ts +1 -1
  47. package/tests/.utils.js +25 -0
  48. package/tests/decode.js +2 -9
  49. package/tests/e2e.js +2 -0
  50. package/tests/encode.js +13 -17
  51. package/tests/rxjs/decode.js +8 -11
  52. package/tests/rxjs/encode.js +17 -19
  53. package/tests/stream/decode.js +7 -10
  54. package/tests/stream/encode.js +16 -18
  55. package/tests/string-encoding.js +7 -14
  56. package/yarn-error.log +4520 -0
@@ -1,107 +1,107 @@
1
- export const textDecoder = typeof TextDecoder == 'function' ? new TextDecoder('utf-8', { ignoreBOM: true, fatal: false }) : null;
2
- export const TEXT_ENCODER_THRESHOLD = textDecoder == null ? 4294967295 : 200;
3
- const CHUNK_SIZE = 4096;
4
- const REPLACE_CHAR = 0xfffd;
5
- /** 解码 */
6
- export function decodeJs(bytes, begin, end) {
7
- let offset = begin;
8
- const units = [];
9
- let result = '';
10
- while (offset < end) {
11
- const byte1 = bytes[offset++];
12
- if ((byte1 & 0x80) === 0) {
13
- // 1 byte
14
- units.push(byte1);
15
- }
16
- else if ((byte1 & 0xe0) === 0xc0) {
17
- // 2 bytes
18
- const byte2 = bytes[offset++] & 0x3f;
19
- units.push(((byte1 & 0x1f) << 6) | byte2);
20
- }
21
- else if ((byte1 & 0xf0) === 0xe0) {
22
- // 3 bytes
23
- const byte2 = bytes[offset++] & 0x3f;
24
- const byte3 = bytes[offset++] & 0x3f;
25
- units.push(((byte1 & 0x1f) << 12) | (byte2 << 6) | byte3);
26
- }
27
- else if ((byte1 & 0xf8) === 0xf0) {
28
- // 4 bytes
29
- const byte2 = bytes[offset++] & 0x3f;
30
- const byte3 = bytes[offset++] & 0x3f;
31
- const byte4 = bytes[offset++] & 0x3f;
32
- let unit = ((byte1 & 0x07) << 0x12) | (byte2 << 0x0c) | (byte3 << 0x06) | byte4;
33
- if (unit > 0xffff) {
34
- unit -= 0x10000;
35
- units.push(((unit >>> 10) & 0x3ff) | 0xd800);
36
- unit = 0xdc00 | (unit & 0x3ff);
37
- }
38
- units.push(unit);
39
- }
40
- else {
41
- units.push(REPLACE_CHAR);
42
- }
43
- if (units.length >= CHUNK_SIZE) {
44
- result += String.fromCharCode(...units);
45
- units.length = 0;
46
- }
47
- }
48
- if (units.length > 0) {
49
- result += String.fromCharCode(...units);
50
- }
51
- return result;
52
- }
53
- /** 解码 */
54
- export function decode(data, begin, end) {
55
- if (end - begin <
56
- TEXT_ENCODER_THRESHOLD // 只有小字符串有优化价值,见 benchmark-string.js
57
- ) {
58
- // 为小字符串优化
59
- return decodeJs(data, begin, end);
60
- }
61
- // 使用系统解码
62
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
63
- return textDecoder.decode(data.subarray(begin, end));
64
- }
65
- /** 特别优化字符串解码速度 */
66
- export class StringDecoder {
67
- constructor() {
68
- /** 小字符串缓存 */
69
- this.cache = [
70
- undefined,
71
- undefined,
72
- new Map(),
73
- new Map(),
74
- new Map(),
75
- new Map(),
76
- new Map(), // 6 字节
77
- ];
78
- }
79
- /** 字符串解码 */
80
- decode(data, begin, end) {
81
- const length = (end - begin);
82
- // 这里,length 类型为 Uint32
83
- if (length > 6)
84
- return decode(data, begin, end);
85
- // 这里,length 类型为 0 | 1 | 2 | 3 | 4 | 5 | 6
86
- // 为小字符串优化
87
- if (length === 0)
88
- return '';
89
- if (length === 1)
90
- return String.fromCharCode(data[begin]);
91
- // number 最多存储 6 字节数据
92
- const cache = this.cache[length];
93
- // 计算缓存 key
94
- let key = 0;
95
- for (let i = begin; i < end; i++) {
96
- // 不要用位运算,JS 位运算只支持 32 位
97
- key = key * 0xff + data[i];
98
- }
99
- const match = cache.get(key);
100
- if (match != null)
101
- return match;
102
- const string = decodeJs(data, begin, end);
103
- cache.set(key, string);
104
- return string;
105
- }
106
- }
1
+ export const textDecoder = typeof TextDecoder == 'function' ? new TextDecoder('utf-8', { ignoreBOM: true, fatal: false }) : null;
2
+ export const TEXT_ENCODER_THRESHOLD = textDecoder == null ? 4294967295 : 200;
3
+ const CHUNK_SIZE = 4096;
4
+ const REPLACE_CHAR = 0xfffd;
5
+ /** 解码 */
6
+ export function decodeJs(bytes, begin, end) {
7
+ let offset = begin;
8
+ const units = [];
9
+ let result = '';
10
+ while (offset < end) {
11
+ const byte1 = bytes[offset++];
12
+ if ((byte1 & 0x80) === 0) {
13
+ // 1 byte
14
+ units.push(byte1);
15
+ }
16
+ else if ((byte1 & 0xe0) === 0xc0) {
17
+ // 2 bytes
18
+ const byte2 = bytes[offset++] & 0x3f;
19
+ units.push(((byte1 & 0x1f) << 6) | byte2);
20
+ }
21
+ else if ((byte1 & 0xf0) === 0xe0) {
22
+ // 3 bytes
23
+ const byte2 = bytes[offset++] & 0x3f;
24
+ const byte3 = bytes[offset++] & 0x3f;
25
+ units.push(((byte1 & 0x1f) << 12) | (byte2 << 6) | byte3);
26
+ }
27
+ else if ((byte1 & 0xf8) === 0xf0) {
28
+ // 4 bytes
29
+ const byte2 = bytes[offset++] & 0x3f;
30
+ const byte3 = bytes[offset++] & 0x3f;
31
+ const byte4 = bytes[offset++] & 0x3f;
32
+ let unit = ((byte1 & 0x07) << 0x12) | (byte2 << 0x0c) | (byte3 << 0x06) | byte4;
33
+ if (unit > 0xffff) {
34
+ unit -= 0x10000;
35
+ units.push(((unit >>> 10) & 0x3ff) | 0xd800);
36
+ unit = 0xdc00 | (unit & 0x3ff);
37
+ }
38
+ units.push(unit);
39
+ }
40
+ else {
41
+ units.push(REPLACE_CHAR);
42
+ }
43
+ if (units.length >= CHUNK_SIZE) {
44
+ result += String.fromCharCode(...units);
45
+ units.length = 0;
46
+ }
47
+ }
48
+ if (units.length > 0) {
49
+ result += String.fromCharCode(...units);
50
+ }
51
+ return result;
52
+ }
53
+ /** 解码 */
54
+ export function decode(data, begin, end) {
55
+ if (end - begin <
56
+ TEXT_ENCODER_THRESHOLD // 只有小字符串有优化价值,见 benchmark-string.js
57
+ ) {
58
+ // 为小字符串优化
59
+ return decodeJs(data, begin, end);
60
+ }
61
+ // 使用系统解码
62
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
63
+ return textDecoder.decode(data.subarray(begin, end));
64
+ }
65
+ /** 特别优化字符串解码速度 */
66
+ export class StringDecoder {
67
+ constructor() {
68
+ /** 小字符串缓存 */
69
+ this.cache = [
70
+ undefined,
71
+ undefined,
72
+ new Map(),
73
+ new Map(),
74
+ new Map(),
75
+ new Map(),
76
+ new Map(), // 6 字节
77
+ ];
78
+ }
79
+ /** 字符串解码 */
80
+ decode(data, begin, end) {
81
+ const length = (end - begin);
82
+ // 这里,length 类型为 Uint32
83
+ if (length > 6)
84
+ return decode(data, begin, end);
85
+ // 这里,length 类型为 0 | 1 | 2 | 3 | 4 | 5 | 6
86
+ // 为小字符串优化
87
+ if (length === 0)
88
+ return '';
89
+ if (length === 1)
90
+ return String.fromCharCode(data[begin]);
91
+ // number 最多存储 6 字节数据
92
+ const cache = this.cache[length];
93
+ // 计算缓存 key
94
+ let key = 0;
95
+ for (let i = begin; i < end; i++) {
96
+ // 不要用位运算,JS 位运算只支持 32 位
97
+ key = key * 0xff + data[i];
98
+ }
99
+ const match = cache.get(key);
100
+ if (match != null)
101
+ return match;
102
+ const string = decodeJs(data, begin, end);
103
+ cache.set(key, string);
104
+ return string;
105
+ }
106
+ }
107
107
  //# sourceMappingURL=string-decoder.js.map
@@ -1,6 +1,6 @@
1
- /** 字符串编码器 */
2
- export declare class StringEncoder extends TextEncoder {
3
- private readonly cache;
4
- /** 编码字符串 */
5
- encode(value: string): Uint8Array;
6
- }
1
+ /** 字符串编码器 */
2
+ export declare class StringEncoder extends TextEncoder {
3
+ private readonly cache;
4
+ /** 编码字符串 */
5
+ encode(value: string): Uint8Array;
6
+ }
@@ -1,38 +1,38 @@
1
- /** 字符串编码器 */
2
- export class StringEncoder extends TextEncoder {
3
- constructor() {
4
- super(...arguments);
5
- this.cache = new Map();
6
- }
7
- /** 编码字符串 */
8
- encode(value) {
9
- if (value.length > 16) {
10
- return super.encode(value);
11
- }
12
- // 优化小字符串
13
- let buf = this.cache.get(value);
14
- if (buf == null) {
15
- let isAscii = true;
16
- for (let index = 0; index < value.length; index++) {
17
- const ch = value.charCodeAt(index);
18
- if (ch >= 128) {
19
- isAscii = false;
20
- break;
21
- }
22
- }
23
- if (isAscii) {
24
- buf = new Uint8Array(value.length);
25
- for (let index = 0; index < value.length; index++) {
26
- const ch = value.charCodeAt(index);
27
- buf[index] = ch;
28
- }
29
- }
30
- else {
31
- buf = super.encode(value);
32
- }
33
- this.cache.set(value, buf);
34
- }
35
- return buf;
36
- }
37
- }
1
+ /** 字符串编码器 */
2
+ export class StringEncoder extends TextEncoder {
3
+ constructor() {
4
+ super(...arguments);
5
+ this.cache = new Map();
6
+ }
7
+ /** 编码字符串 */
8
+ encode(value) {
9
+ if (value.length > 16) {
10
+ return super.encode(value);
11
+ }
12
+ // 优化小字符串
13
+ let buf = this.cache.get(value);
14
+ if (buf == null) {
15
+ let isAscii = true;
16
+ for (let index = 0; index < value.length; index++) {
17
+ const ch = value.charCodeAt(index);
18
+ if (ch >= 128) {
19
+ isAscii = false;
20
+ break;
21
+ }
22
+ }
23
+ if (isAscii) {
24
+ buf = new Uint8Array(value.length);
25
+ for (let index = 0; index < value.length; index++) {
26
+ const ch = value.charCodeAt(index);
27
+ buf[index] = ch;
28
+ }
29
+ }
30
+ else {
31
+ buf = super.encode(value);
32
+ }
33
+ this.cache.set(value, buf);
34
+ }
35
+ return buf;
36
+ }
37
+ }
38
38
  //# sourceMappingURL=string-encoder.js.map
package/dist/decoder.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- import { Decoder } from './common/decoder.js';
2
- export { Decoder };
1
+ import { Decoder } from './common/decoder.js';
2
+ export { Decoder };
package/dist/decoder.js CHANGED
@@ -1,3 +1,3 @@
1
- import { Decoder } from './common/decoder.js';
2
- export { Decoder };
1
+ import { Decoder } from './common/decoder.js';
2
+ export { Decoder };
3
3
  //# sourceMappingURL=decoder.js.map
package/dist/encoder.d.ts CHANGED
@@ -1,11 +1,11 @@
1
- import { EncoderBase } from './common/encoder.js';
2
- /** 编码至 ubjson */
3
- export declare class Encoder extends EncoderBase {
4
- private flushedBuffers;
5
- /**
6
- * 确保 buffer 还有 capacity 的空闲空间
7
- */
8
- protected ensureCapacity(capacity: number): void;
9
- /** 获取写入结果 */
10
- encode(): Uint8Array;
11
- }
1
+ import { EncoderBase } from './common/encoder.js';
2
+ /** 编码至 ubjson */
3
+ export declare class Encoder extends EncoderBase {
4
+ private flushedBuffers;
5
+ /**
6
+ * 确保 buffer 还有 capacity 的空闲空间
7
+ */
8
+ protected ensureCapacity(capacity: number): void;
9
+ /** 获取写入结果 */
10
+ encode(): Uint8Array;
11
+ }
package/dist/encoder.js CHANGED
@@ -1,78 +1,78 @@
1
- import { EncoderBase } from './common/encoder.js';
2
- const BLOCK_SIZE = 1024 * 16; // 8 KiB
3
- const MAX_SIZE = 1024 * 1024 * 128; //128 MiB
4
- /** 编码至 ubjson */
5
- export class Encoder extends EncoderBase {
6
- constructor() {
7
- super(...arguments);
8
- this.flushedBuffers = [];
9
- }
10
- /**
11
- * 确保 buffer 还有 capacity 的空闲空间
12
- */
13
- ensureCapacity(capacity) {
14
- if (capacity > MAX_SIZE) {
15
- // 超过最大尺寸限制
16
- throw new Error('Buffer has exceed max size');
17
- }
18
- if (this.buffer == null) {
19
- this.buffer = new Uint8Array(capacity);
20
- this.view = new DataView(this.buffer.buffer);
21
- return;
22
- }
23
- // 无需扩容
24
- if (this.buffer.byteLength >= this.length + capacity)
25
- return;
26
- // 提交目前的数据
27
- this.flushedBuffers.push(this.buffer.subarray(0, this.length));
28
- // 重新分配缓冲区
29
- if (capacity < BLOCK_SIZE)
30
- capacity = BLOCK_SIZE;
31
- this.buffer = new Uint8Array(capacity);
32
- this.view = new DataView(this.buffer.buffer);
33
- this.length = 0;
34
- }
35
- /** 获取写入结果 */
36
- encode() {
37
- if (ArrayBuffer.isView(this.value)) {
38
- // 为根 typed array 优化,减少不必要的分配
39
- if (this.value.byteLength < 128)
40
- this.ensureCapacity(6 + this.value.byteLength);
41
- else if (this.value.byteLength < 32768)
42
- this.ensureCapacity(7 + this.value.byteLength);
43
- else if (this.value.byteLength < 2147483648)
44
- this.ensureCapacity(9 + this.value.byteLength);
45
- else
46
- this.ensureCapacity(13 + this.value.byteLength);
47
- this.writeTypedArray(this.value);
48
- // 取消注释后运行测试
49
- // if (this.buffer.byteLength !== this.length) {
50
- // // 这里永远无法到达
51
- // throw new Error('Bad buffer size');
52
- // }
53
- }
54
- else {
55
- this.ensureCapacity(BLOCK_SIZE);
56
- this.write(this.value);
57
- }
58
- if (this.flushedBuffers.length === 0) {
59
- if (this.buffer.byteLength === this.length) {
60
- // 无需再拷贝一次
61
- return this.buffer;
62
- }
63
- else {
64
- return this.buffer.slice(0, this.length);
65
- }
66
- }
67
- // 合并缓冲区
68
- const result = new Uint8Array(this.length + this.flushedBuffers.reduce((sum, buffer) => sum + buffer.byteLength, 0));
69
- let offset = 0;
70
- for (const buffer of this.flushedBuffers) {
71
- result.set(buffer, offset);
72
- offset += buffer.byteLength;
73
- }
74
- result.set(this.buffer.subarray(0, this.length), offset);
75
- return result;
76
- }
77
- }
1
+ import { EncoderBase } from './common/encoder.js';
2
+ const BLOCK_SIZE = 1024 * 16; // 8 KiB
3
+ const MAX_SIZE = 1024 * 1024 * 128; //128 MiB
4
+ /** 编码至 ubjson */
5
+ export class Encoder extends EncoderBase {
6
+ constructor() {
7
+ super(...arguments);
8
+ this.flushedBuffers = [];
9
+ }
10
+ /**
11
+ * 确保 buffer 还有 capacity 的空闲空间
12
+ */
13
+ ensureCapacity(capacity) {
14
+ if (capacity > MAX_SIZE) {
15
+ // 超过最大尺寸限制
16
+ throw new Error('Buffer has exceed max size');
17
+ }
18
+ if (this.buffer == null) {
19
+ this.buffer = new Uint8Array(capacity);
20
+ this.view = new DataView(this.buffer.buffer);
21
+ return;
22
+ }
23
+ // 无需扩容
24
+ if (this.buffer.byteLength >= this.length + capacity)
25
+ return;
26
+ // 提交目前的数据
27
+ this.flushedBuffers.push(this.buffer.subarray(0, this.length));
28
+ // 重新分配缓冲区
29
+ if (capacity < BLOCK_SIZE)
30
+ capacity = BLOCK_SIZE;
31
+ this.buffer = new Uint8Array(capacity);
32
+ this.view = new DataView(this.buffer.buffer);
33
+ this.length = 0;
34
+ }
35
+ /** 获取写入结果 */
36
+ encode() {
37
+ if (ArrayBuffer.isView(this.value)) {
38
+ // 为根 typed array 优化,减少不必要的分配
39
+ if (this.value.byteLength < 128)
40
+ this.ensureCapacity(6 + this.value.byteLength);
41
+ else if (this.value.byteLength < 32768)
42
+ this.ensureCapacity(7 + this.value.byteLength);
43
+ else if (this.value.byteLength < 2147483648)
44
+ this.ensureCapacity(9 + this.value.byteLength);
45
+ else
46
+ this.ensureCapacity(13 + this.value.byteLength);
47
+ this.writeTypedArray(this.value);
48
+ // 取消注释后运行测试
49
+ // if (this.buffer.byteLength !== this.length) {
50
+ // // 这里永远无法到达
51
+ // throw new Error('Bad buffer size');
52
+ // }
53
+ }
54
+ else {
55
+ this.ensureCapacity(BLOCK_SIZE);
56
+ this.write(this.value);
57
+ }
58
+ if (this.flushedBuffers.length === 0) {
59
+ if (this.buffer.byteLength === this.length) {
60
+ // 无需再拷贝一次
61
+ return this.buffer;
62
+ }
63
+ else {
64
+ return this.buffer.slice(0, this.length);
65
+ }
66
+ }
67
+ // 合并缓冲区
68
+ const result = new Uint8Array(this.length + this.flushedBuffers.reduce((sum, buffer) => sum + buffer.byteLength, 0));
69
+ let offset = 0;
70
+ for (const buffer of this.flushedBuffers) {
71
+ result.set(buffer, offset);
72
+ offset += buffer.byteLength;
73
+ }
74
+ result.set(this.buffer.subarray(0, this.length), offset);
75
+ return result;
76
+ }
77
+ }
78
78
  //# sourceMappingURL=encoder.js.map
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- /** 编码为 UBJSON */
2
- export declare function encode(value: unknown): Uint8Array;
3
- /** 解码 UBJSON */
4
- export declare function decode(value: BinaryData): unknown;
5
- export { StringEncoder } from './common/string-encoder.js';
6
- export { StringDecoder } from './common/string-decoder.js';
1
+ /** 编码为 UBJSON */
2
+ export declare function encode(value: unknown): Uint8Array;
3
+ /** 解码 UBJSON */
4
+ export declare function decode(value: BinaryData): unknown;
5
+ export { StringEncoder } from './common/string-encoder.js';
6
+ export { StringDecoder } from './common/string-decoder.js';
package/dist/index.js CHANGED
@@ -1,16 +1,16 @@
1
- import { Encoder } from './encoder.js';
2
- import { Decoder } from './decoder.js';
3
- import { toUint8Array } from './utils.js';
4
- /** 编码为 UBJSON */
5
- export function encode(value) {
6
- const encoder = new Encoder(value);
7
- return encoder.encode();
8
- }
9
- /** 解码 UBJSON */
10
- export function decode(value) {
11
- const decoder = new Decoder(toUint8Array(value));
12
- return decoder.decode();
13
- }
14
- export { StringEncoder } from './common/string-encoder.js';
15
- export { StringDecoder } from './common/string-decoder.js';
1
+ import { Encoder } from './encoder.js';
2
+ import { Decoder } from './decoder.js';
3
+ import { toUint8Array } from './utils.js';
4
+ /** 编码为 UBJSON */
5
+ export function encode(value) {
6
+ const encoder = new Encoder(value);
7
+ return encoder.encode();
8
+ }
9
+ /** 解码 UBJSON */
10
+ export function decode(value) {
11
+ const decoder = new Decoder(toUint8Array(value));
12
+ return decoder.decode();
13
+ }
14
+ export { StringEncoder } from './common/string-encoder.js';
15
+ export { StringDecoder } from './common/string-decoder.js';
16
16
  //# sourceMappingURL=index.js.map
@@ -1,3 +1,3 @@
1
- import { OperatorFunction } from 'rxjs';
2
- /** 流式解码 UBJSON */
3
- export declare function decode(): OperatorFunction<BinaryData, unknown>;
1
+ import { type OperatorFunction } from 'rxjs';
2
+ /** 流式解码 UBJSON */
3
+ export declare function decode(): OperatorFunction<BinaryData, unknown>;