@cloudpss/ubjson 0.4.32 → 0.4.34

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 (59) hide show
  1. package/dist/common/constants.d.ts +22 -20
  2. package/dist/common/constants.js +1 -21
  3. package/dist/common/constants.js.map +1 -1
  4. package/dist/common/decoder.d.ts +4 -20
  5. package/dist/common/decoder.js +217 -178
  6. package/dist/common/decoder.js.map +1 -1
  7. package/dist/common/encoder.d.ts +8 -54
  8. package/dist/common/encoder.js +241 -259
  9. package/dist/common/encoder.js.map +1 -1
  10. package/dist/common/string-decoder.d.ts +3 -8
  11. package/dist/common/string-decoder.js +190 -46
  12. package/dist/common/string-decoder.js.map +1 -1
  13. package/dist/common/string-encoder.d.ts +2 -8
  14. package/dist/common/string-encoder.js +8 -44
  15. package/dist/common/string-encoder.js.map +1 -1
  16. package/dist/encoder.js +2 -21
  17. package/dist/encoder.js.map +1 -1
  18. package/dist/index.d.ts +1 -2
  19. package/dist/index.js +2 -4
  20. package/dist/index.js.map +1 -1
  21. package/dist/rxjs/decoder.js +2 -2
  22. package/dist/rxjs/decoder.js.map +1 -1
  23. package/dist/rxjs/index.d.ts +1 -0
  24. package/dist/rxjs/index.js +1 -0
  25. package/dist/rxjs/index.js.map +1 -1
  26. package/dist/stream/index.d.ts +1 -0
  27. package/dist/stream/index.js +2 -1
  28. package/dist/stream/index.js.map +1 -1
  29. package/dist/stream-helper/decoder.d.ts +1 -1
  30. package/dist/stream-helper/decoder.js +1 -1
  31. package/dist/stream-helper/decoder.js.map +1 -1
  32. package/dist/stream-helper/encoder.js +2 -2
  33. package/dist/stream-helper/encoder.js.map +1 -1
  34. package/dist/utils.d.ts +5 -1
  35. package/dist/utils.js +13 -4
  36. package/dist/utils.js.map +1 -1
  37. package/package.json +3 -2
  38. package/src/common/constants.ts +22 -21
  39. package/src/common/decoder.ts +197 -162
  40. package/src/common/encoder.ts +230 -277
  41. package/src/common/string-decoder.ts +173 -41
  42. package/src/common/string-encoder.ts +10 -41
  43. package/src/encoder.ts +2 -16
  44. package/src/index.ts +2 -5
  45. package/src/rxjs/decoder.ts +2 -2
  46. package/src/rxjs/index.ts +1 -0
  47. package/src/stream/index.ts +2 -0
  48. package/src/stream-helper/decoder.ts +1 -1
  49. package/src/stream-helper/encoder.ts +2 -2
  50. package/src/utils.ts +14 -4
  51. package/tests/decode.js +69 -5
  52. package/tests/e2e.js +12 -1
  53. package/tests/encode.js +52 -23
  54. package/tests/rxjs/decode.js +3 -2
  55. package/tests/rxjs/encode.js +5 -8
  56. package/tests/stream/decode.js +2 -1
  57. package/tests/stream/encode.js +4 -5
  58. package/tests/string-encoding.js +77 -25
  59. package/tsconfig.json +3 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cloudpss/ubjson",
3
- "version": "0.4.32",
3
+ "version": "0.4.34",
4
4
  "author": "CloudPSS",
5
5
  "license": "MIT",
6
6
  "keywords": [
@@ -50,7 +50,8 @@
50
50
  },
51
51
  "devDependencies": {
52
52
  "@msgpack/msgpack": "^3.0.0-beta2",
53
- "@types/lodash": "^4.14.197"
53
+ "@types/lodash": "^4.14.197",
54
+ "msgpackr": "^1.9.7"
54
55
  },
55
56
  "dependencies": {
56
57
  "rxjs": "^7.8.1"
@@ -1,24 +1,25 @@
1
1
  /** Constants of markers */
2
+ export const enum constants {
3
+ NULL = 90, //'Z'.charCodeAt(0)
4
+ NO_OP = 78, //'N'.charCodeAt(0)
5
+ TRUE = 84, //'T'.charCodeAt(0)
6
+ FALSE = 70, //'F'.charCodeAt(0)
7
+ INT8 = 105, //'i'.charCodeAt(0)
8
+ UINT8 = 85, //'U'.charCodeAt(0)
9
+ INT16 = 73, //'I'.charCodeAt(0)
10
+ INT32 = 108, //'l'.charCodeAt(0)
11
+ INT64 = 76, //'L'.charCodeAt(0)
12
+ FLOAT32 = 100, //'d'.charCodeAt(0)
13
+ FLOAT64 = 68, //'D'.charCodeAt(0)
14
+ HIGH_PRECISION_NUMBER = 72, //'H'.charCodeAt(0)
15
+ CHAR = 67, //'C'.charCodeAt(0)
16
+ STRING = 83, //'S'.charCodeAt(0)
2
17
 
3
- export const NULL = 'Z'.charCodeAt(0);
4
- export const NO_OP = 'N'.charCodeAt(0);
5
- export const TRUE = 'T'.charCodeAt(0);
6
- export const FALSE = 'F'.charCodeAt(0);
7
- export const INT8 = 'i'.charCodeAt(0);
8
- export const UINT8 = 'U'.charCodeAt(0);
9
- export const INT16 = 'I'.charCodeAt(0);
10
- export const INT32 = 'l'.charCodeAt(0);
11
- export const INT64 = 'L'.charCodeAt(0);
12
- export const FLOAT32 = 'd'.charCodeAt(0);
13
- export const FLOAT64 = 'D'.charCodeAt(0);
14
- export const HIGH_PRECISION_NUMBER = 'H'.charCodeAt(0);
15
- export const CHAR = 'C'.charCodeAt(0);
16
- export const STRING = 'S'.charCodeAt(0);
18
+ ARRAY = 91, //'['.charCodeAt(0)
19
+ ARRAY_END = 93, //']'.charCodeAt(0)
20
+ OBJECT = 123, //'{'.charCodeAt(0)
21
+ OBJECT_END = 125, //'}'.charCodeAt(0)
17
22
 
18
- export const ARRAY = '['.charCodeAt(0);
19
- export const ARRAY_END = ']'.charCodeAt(0);
20
- export const OBJECT = '{'.charCodeAt(0);
21
- export const OBJECT_END = '}'.charCodeAt(0);
22
-
23
- export const TYPE_MARKER = '$'.charCodeAt(0);
24
- export const COUNT_MARKER = '#'.charCodeAt(0);
23
+ TYPE_MARKER = 36, //'$'.charCodeAt(0)
24
+ COUNT_MARKER = 35, //'#'.charCodeAt(0)
25
+ }
@@ -1,44 +1,40 @@
1
- import * as constants from './constants.js';
2
- import { StringDecoder } from './string-decoder.js';
1
+ import { UnexpectedEof, toUint8Array } from '../utils.js';
2
+ import { constants } from './constants.js';
3
+ import { decode, decodeKey } from './string-decoder.js';
3
4
 
4
- /** 未结束的流 */
5
- export class UnexpectedEof extends Error {
6
- constructor() {
7
- super('Unexpected EOF');
8
- }
9
- }
5
+ const fromEntries = Object.fromEntries;
10
6
 
11
7
  /** decoder */
12
8
  export class Decoder {
13
9
  protected readonly view: DataView;
10
+ protected readonly data: Uint8Array;
14
11
  /** 当前读指针位置 */
15
12
  protected offset = 0;
16
- constructor(readonly data: Uint8Array) {
17
- this.view = new DataView(data.buffer, data.byteOffset, data.byteLength);
13
+ constructor(data: BinaryData) {
14
+ this.data = toUint8Array(data, true);
15
+ this.view = new DataView(this.data.buffer, this.data.byteOffset, this.data.byteLength);
18
16
  }
19
17
  /** 解码 */
20
18
  decode(): unknown {
21
- return this.read();
22
- }
23
-
24
- /** 检查是否有给定字节数的未读数据 */
25
- protected ensureData(byteLength: number): void {
26
- if (this.offset + byteLength > this.data.byteLength) {
27
- throw new UnexpectedEof();
28
- }
19
+ const marker = this.readMarker();
20
+ if (marker === undefined) return undefined;
21
+ return this.readData(marker);
29
22
  }
30
23
 
31
24
  /** 读取数据 */
32
25
  private read(): unknown {
33
- return this.readData(this.readMarker());
26
+ const marker = this.readMarker();
27
+ if (marker === undefined) {
28
+ throw new UnexpectedEof();
29
+ }
30
+ return this.readData(marker);
34
31
  }
35
32
 
36
33
  /** 读取 marker,跳过 noop */
37
- private readMarker(): number {
34
+ private readMarker(): number | undefined {
38
35
  let marker = constants.NO_OP;
39
36
  do {
40
- if (this.offset >= this.data.byteLength) break;
41
- marker = this.view.getUint8(this.offset++);
37
+ marker = this.data[this.offset++];
42
38
  } while (marker === constants.NO_OP);
43
39
  return marker;
44
40
  }
@@ -47,12 +43,126 @@ export class Decoder {
47
43
  private readData(marker: number): unknown {
48
44
  // 按照出现频率排序
49
45
  switch (marker) {
50
- case constants.STRING:
51
- return this.readStringData();
52
- case constants.ARRAY:
53
- return this.readArray();
54
- case constants.OBJECT:
55
- return this.readObject();
46
+ case constants.STRING: {
47
+ const length = this.readIntLength();
48
+ const begin = this.offset;
49
+ this.offset += length;
50
+ return decode(this.data, begin, this.offset);
51
+ }
52
+ case constants.OBJECT: {
53
+ const markers = this.readOptimizedFormatMarkers();
54
+ if (markers == null) {
55
+ // 直到 '}'
56
+ const object: Array<[string, unknown]> = [];
57
+ while (this.readMarker() !== constants.OBJECT_END) {
58
+ this.offset--;
59
+ object.push([this.readKey(), this.read()]);
60
+ }
61
+ return fromEntries(object);
62
+ }
63
+
64
+ const { count, type } = markers;
65
+ const object: Array<[string, unknown]> = [];
66
+ object.length = count;
67
+ for (let i = 0; i < count; i++) {
68
+ const key = this.readKey();
69
+ const t = type ?? this.readMarker();
70
+ if (t === undefined) throw new UnexpectedEof();
71
+ const value = this.readData(t);
72
+ object[i] = [key, value];
73
+ }
74
+ return fromEntries(object);
75
+ }
76
+ case constants.ARRAY: {
77
+ const markers = this.readOptimizedFormatMarkers();
78
+ if (markers == null) {
79
+ const array = [];
80
+ // 直到 ']'
81
+ while (this.readMarker() !== constants.ARRAY_END) {
82
+ this.offset--;
83
+ array.push(this.read());
84
+ }
85
+ return array;
86
+ }
87
+
88
+ const { count, type } = markers;
89
+ switch (type) {
90
+ case constants.UINT8:
91
+ try {
92
+ const buf = new Uint8Array(
93
+ this.data.buffer,
94
+ this.data.byteOffset + this.offset,
95
+ count,
96
+ ).slice();
97
+ this.offset += count;
98
+ return buf;
99
+ } catch {
100
+ throw new UnexpectedEof();
101
+ }
102
+ case constants.INT8:
103
+ try {
104
+ const buf = new Int8Array(
105
+ this.data.buffer,
106
+ this.data.byteOffset + this.offset,
107
+ count,
108
+ ).slice();
109
+ this.offset += count;
110
+ return buf;
111
+ } catch {
112
+ throw new UnexpectedEof();
113
+ }
114
+ case constants.INT16: {
115
+ const result = new Int16Array(count);
116
+ for (let i = 0; i < count; i++) {
117
+ result[i] = this.readInt16Data();
118
+ }
119
+ return result;
120
+ }
121
+ case constants.INT32: {
122
+ const result = new Int32Array(count);
123
+ for (let i = 0; i < count; i++) {
124
+ result[i] = this.readInt32Data();
125
+ }
126
+ return result;
127
+ }
128
+ case constants.FLOAT32: {
129
+ const result = new Float32Array(count);
130
+ for (let i = 0; i < count; i++) {
131
+ result[i] = this.readFloat32Data();
132
+ }
133
+ return result;
134
+ }
135
+ case constants.FLOAT64: {
136
+ const result = new Float64Array(count);
137
+ for (let i = 0; i < count; i++) {
138
+ result[i] = this.readFloat64Data();
139
+ }
140
+ return result;
141
+ }
142
+ case constants.INT64: {
143
+ const result = new BigInt64Array(count);
144
+ for (let i = 0; i < count; i++) {
145
+ result[i] = this.readInt64Data();
146
+ }
147
+ throw new Error('Unsupported type int64');
148
+ //return result;
149
+ }
150
+ case constants.NULL:
151
+ return Array.from({ length: count }).fill(null);
152
+ case constants.TRUE:
153
+ return Array.from({ length: count }).fill(true);
154
+ case constants.FALSE:
155
+ return Array.from({ length: count }).fill(false);
156
+ default:
157
+ break;
158
+ }
159
+ const array: unknown[] = [];
160
+ array.length = count;
161
+ for (let i = 0; i < count; i++) {
162
+ array[i] = type == null ? this.read() : this.readData(type);
163
+ }
164
+ return array;
165
+ }
56
166
  case constants.FLOAT64:
57
167
  return this.readFloat64Data();
58
168
  case constants.UINT8:
@@ -62,7 +172,7 @@ export class Decoder {
62
172
  case constants.FLOAT32:
63
173
  return this.readFloat32Data();
64
174
  case constants.CHAR:
65
- return this.readCharData();
175
+ return String.fromCharCode(this.readUint8Data());
66
176
  case constants.INT32:
67
177
  return this.readInt32Data();
68
178
  case constants.INT8:
@@ -73,12 +183,19 @@ export class Decoder {
73
183
  return true;
74
184
  case constants.FALSE:
75
185
  return false;
76
- case constants.NO_OP:
77
- return undefined;
78
186
  case constants.INT64:
79
187
  return this.readInt64Data();
80
- case constants.HIGH_PRECISION_NUMBER:
81
- return this.readHighPrecisionNumberData();
188
+ case constants.HIGH_PRECISION_NUMBER: {
189
+ const length = this.readIntLength();
190
+ try {
191
+ const _buffer = new Uint8Array(this.data.buffer, this.offset, length).slice();
192
+ this.offset += length;
193
+ // return buffer;
194
+ } catch {
195
+ throw new UnexpectedEof();
196
+ }
197
+ throw new Error('Unsupported type high precision number');
198
+ }
82
199
  }
83
200
  throw new Error(`Unexpected marker '${String.fromCharCode(marker)}'(${marker})`);
84
201
  }
@@ -86,6 +203,7 @@ export class Decoder {
86
203
  /** 读取一个大于 0 的整数 */
87
204
  private readIntLength(): number {
88
205
  const marker = this.readMarker();
206
+ if (marker === undefined) throw new UnexpectedEof();
89
207
  let length;
90
208
  switch (marker) {
91
209
  case constants.INT8:
@@ -112,78 +230,77 @@ export class Decoder {
112
230
  return length;
113
231
  }
114
232
 
115
- /** 字符串解码 */
116
- private readonly stringDecoder = new StringDecoder();
117
- /** readStringData */
118
- private readStringData(): string {
233
+ /** readKey */
234
+ private readKey(): string {
119
235
  const length = this.readIntLength();
120
- this.ensureData(length);
121
236
  const begin = this.offset;
122
237
  this.offset += length;
123
- return this.stringDecoder.decode(this.data, begin, this.offset);
124
- }
125
- /** readHighPrecisionNumberData */
126
- private readHighPrecisionNumberData(): never {
127
- const length = this.readIntLength();
128
- this.ensureData(length);
129
- throw new Error('Unsupported type high precision number');
130
- // const buffer = this.data.subarray(this.offset, this.offset + length);
131
- // this.offset += length;
132
- // return buffer.slice();
133
- }
134
- /** readStringData */
135
- private readCharData(): string {
136
- return String.fromCharCode(this.readUint8Data());
238
+ return decodeKey(this.data, begin, this.offset);
137
239
  }
138
240
  /** readInt8Data */
139
241
  private readInt8Data(): number {
140
- this.ensureData(1);
141
- const result = this.view.getInt8(this.offset);
142
- this.offset += 1;
143
- return result;
242
+ try {
243
+ return this.view.getInt8(this.offset++);
244
+ } catch {
245
+ throw new UnexpectedEof();
246
+ }
144
247
  }
145
248
  /** readUint8Data */
146
249
  private readUint8Data(): number {
147
- this.ensureData(1);
148
- const result = this.view.getUint8(this.offset);
149
- this.offset += 1;
150
- return result;
250
+ const num = this.data[this.offset++];
251
+ if (num === undefined) throw new UnexpectedEof();
252
+ return num;
151
253
  }
152
254
  /** readInt16Data */
153
255
  private readInt16Data(): number {
154
- this.ensureData(2);
155
- const result = this.view.getInt16(this.offset);
156
- this.offset += 2;
157
- return result;
256
+ try {
257
+ const result = this.view.getInt16(this.offset);
258
+ this.offset += 2;
259
+ return result;
260
+ } catch {
261
+ throw new UnexpectedEof();
262
+ }
158
263
  }
159
264
  /** readInt32Data */
160
265
  private readInt32Data(): number {
161
- this.ensureData(4);
162
- const result = this.view.getInt32(this.offset);
163
- this.offset += 4;
164
- return result;
266
+ try {
267
+ const result = this.view.getInt32(this.offset);
268
+ this.offset += 4;
269
+ return result;
270
+ } catch {
271
+ throw new UnexpectedEof();
272
+ }
165
273
  }
166
274
  /** readInt64Data */
167
275
  private readInt64Data(): never {
168
- this.ensureData(8);
276
+ try {
277
+ const _result = this.view.getBigInt64(this.offset);
278
+ this.offset += 8;
279
+ // return result;
280
+ } catch {
281
+ throw new UnexpectedEof();
282
+ }
169
283
  throw new Error('Unsupported type int64');
170
- // const result = this.view.getBigInt64(this.offset);
171
- // this.offset += 8;
172
- // return result;
173
284
  }
174
285
  /** readFloat32Data */
175
286
  private readFloat32Data(): number {
176
- this.ensureData(4);
177
- const result = this.view.getFloat32(this.offset);
178
- this.offset += 4;
179
- return result;
287
+ try {
288
+ const result = this.view.getFloat32(this.offset);
289
+ this.offset += 4;
290
+ return result;
291
+ } catch {
292
+ throw new UnexpectedEof();
293
+ }
180
294
  }
181
295
  /** readFloat64Data */
182
296
  private readFloat64Data(): number {
183
- this.ensureData(8);
184
- const result = this.view.getFloat64(this.offset);
185
- this.offset += 8;
186
- return result;
297
+ try {
298
+ const result = this.view.getFloat64(this.offset);
299
+ this.offset += 8;
300
+ return result;
301
+ } catch {
302
+ throw new UnexpectedEof();
303
+ }
187
304
  }
188
305
 
189
306
  /** 读取 Optimized Format 数据 */
@@ -207,86 +324,4 @@ export class Decoder {
207
324
  }
208
325
  return { type, count };
209
326
  }
210
-
211
- /** 读取数组 */
212
- private readArray(): unknown[] | ArrayBufferView {
213
- const markers = this.readOptimizedFormatMarkers();
214
- if (markers == null) {
215
- const array = [];
216
- // 直到 ']'
217
- while (this.readMarker() !== constants.ARRAY_END) {
218
- this.offset--;
219
- array.push(this.read());
220
- }
221
- return array;
222
- }
223
-
224
- const { count, type } = markers;
225
- switch (type) {
226
- case constants.UINT8:
227
- this.ensureData(count);
228
- this.offset += count;
229
- return new Uint8Array(this.data.buffer, this.data.byteOffset + this.offset - count, count).slice();
230
- case constants.INT8:
231
- this.ensureData(count);
232
- this.offset += count;
233
- return new Int8Array(this.data.buffer, this.data.byteOffset + this.offset - count, count).slice();
234
- case constants.INT16:
235
- this.ensureData(count * 2);
236
- return Int16Array.from({ length: count }, () => this.readInt16Data());
237
- case constants.INT32:
238
- this.ensureData(count * 4);
239
- return Int32Array.from({ length: count }, () => this.readInt32Data());
240
- case constants.FLOAT32:
241
- this.ensureData(count * 4);
242
- return Float32Array.from({ length: count }, () => this.readFloat32Data());
243
- case constants.FLOAT64: {
244
- this.ensureData(count * 8);
245
- const result = new Float64Array(count);
246
- for (let i = 0; i < count; i++) {
247
- result[i] = this.readFloat64Data();
248
- }
249
- return result;
250
- }
251
- case constants.NULL:
252
- return Array.from({ length: count }).fill(null);
253
- case constants.TRUE:
254
- return Array.from({ length: count }).fill(true);
255
- case constants.FALSE:
256
- return Array.from({ length: count }).fill(false);
257
- case constants.INT64:
258
- this.ensureData(count * 8);
259
- return BigInt64Array.from({ length: count }, () => this.readInt64Data());
260
- default:
261
- break;
262
- }
263
- const array: unknown[] = [];
264
- array.length = count;
265
- for (let i = 0; i < count; i++) {
266
- array[i] = type == null ? this.read() : this.readData(type);
267
- }
268
- return array;
269
- }
270
-
271
- /** 读对象 */
272
- private readObject(): Record<string, unknown> {
273
- const markers = this.readOptimizedFormatMarkers();
274
- if (markers == null) {
275
- // 直到 '}'
276
- const object: Array<[string, unknown]> = [];
277
- while (this.readMarker() !== constants.OBJECT_END) {
278
- this.offset--;
279
- object.push([this.readStringData(), this.read()]);
280
- }
281
- return Object.fromEntries(object);
282
- }
283
-
284
- const { count, type } = markers;
285
- const object: Array<[string, unknown]> = [];
286
- object.length = count;
287
- for (let i = 0; i < count; i++) {
288
- object[i] = [this.readStringData(), type == null ? this.read() : this.readData(type)];
289
- }
290
- return Object.fromEntries(object);
291
- }
292
327
  }