@cloudpss/ubjson 0.5.40 → 0.5.41
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/encoder.d.ts +2 -0
- package/dist/base/encoder.d.ts.map +1 -1
- package/dist/base/encoder.js +6 -1
- package/dist/base/encoder.js.map +1 -1
- package/dist/encoder.d.ts +2 -1
- package/dist/encoder.d.ts.map +1 -1
- package/dist/encoder.js +2 -1
- package/dist/encoder.js.map +1 -1
- package/dist/helper/decode-ae.d.ts +50 -0
- package/dist/helper/decode-ae.d.ts.map +1 -0
- package/dist/helper/decode-ae.js +584 -0
- package/dist/helper/decode-ae.js.map +1 -0
- package/dist/helper/decode.d.ts.map +1 -1
- package/dist/helper/decode.js +7 -5
- package/dist/helper/decode.js.map +1 -1
- package/dist/index.d.ts +4 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -4
- package/dist/index.js.map +1 -1
- package/dist/options.d.ts +6 -0
- package/dist/options.d.ts.map +1 -0
- package/dist/options.js +2 -0
- package/dist/options.js.map +1 -0
- package/dist/rxjs/decoder.d.ts.map +1 -1
- package/dist/rxjs/decoder.js +66 -40
- package/dist/rxjs/decoder.js.map +1 -1
- package/dist/rxjs/encoder.d.ts +2 -1
- package/dist/rxjs/encoder.d.ts.map +1 -1
- package/dist/rxjs/encoder.js +2 -2
- package/dist/rxjs/encoder.js.map +1 -1
- package/dist/rxjs/index.d.ts +1 -0
- package/dist/rxjs/index.d.ts.map +1 -1
- package/dist/stream/encoder.d.ts +3 -2
- package/dist/stream/encoder.d.ts.map +1 -1
- package/dist/stream/encoder.js +2 -2
- package/dist/stream/encoder.js.map +1 -1
- package/dist/stream/index.d.ts +5 -3
- package/dist/stream/index.d.ts.map +1 -1
- package/dist/stream/index.js +6 -6
- package/dist/stream/index.js.map +1 -1
- package/dist/stream-helper/encoder.d.ts +2 -1
- package/dist/stream-helper/encoder.d.ts.map +1 -1
- package/dist/stream-helper/encoder.js +2 -1
- package/dist/stream-helper/encoder.js.map +1 -1
- package/package.json +2 -2
- package/src/base/encoder.ts +6 -1
- package/src/encoder.ts +3 -1
- package/src/helper/decode-ae.ts +621 -0
- package/src/helper/decode.ts +6 -5
- package/src/index.ts +7 -4
- package/src/options.ts +5 -0
- package/src/rxjs/decoder.ts +66 -40
- package/src/rxjs/encoder.ts +3 -2
- package/src/rxjs/index.ts +1 -0
- package/src/stream/encoder.ts +4 -3
- package/src/stream/index.ts +8 -6
- package/src/stream-helper/encoder.ts +6 -1
- package/tests/.utils.js +1 -0
- package/tests/e2e/stream.js +13 -1
- package/tests/encode.js +1 -1
|
@@ -0,0 +1,621 @@
|
|
|
1
|
+
import { constants } from './constants.js';
|
|
2
|
+
import { unsupportedType } from './errors.js';
|
|
3
|
+
import { decode } from './string-decoder.js';
|
|
4
|
+
import { toUint8Array } from './utils.js';
|
|
5
|
+
const { defineProperty } = Object;
|
|
6
|
+
const { fromCharCode } = String;
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* 数据读取函数
|
|
10
|
+
* `yield` 返回需要的字节数,`return` 返回解析结果
|
|
11
|
+
*/
|
|
12
|
+
export type DecodeFuncAe<T = unknown> = Generator<number, T, void>;
|
|
13
|
+
|
|
14
|
+
/** 数据包装 */
|
|
15
|
+
export interface DecodeCursorAe {
|
|
16
|
+
/** 当前数据块 */
|
|
17
|
+
readonly view: DataView;
|
|
18
|
+
/** 当前数据块 */
|
|
19
|
+
readonly data: Uint8Array;
|
|
20
|
+
/** 当前数据大小 */
|
|
21
|
+
readonly size: number;
|
|
22
|
+
/** 当前读指针位置 */
|
|
23
|
+
offset: number;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** 创建数据包装 */
|
|
27
|
+
export function DecodeCursor(data: BinaryData): DecodeCursorAe {
|
|
28
|
+
const d = toUint8Array(data);
|
|
29
|
+
const v = new DataView(d.buffer, d.byteOffset, d.byteLength);
|
|
30
|
+
return {
|
|
31
|
+
data: d,
|
|
32
|
+
view: v,
|
|
33
|
+
size: v.byteLength,
|
|
34
|
+
offset: 0,
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* 读取第一个非 NOOP 的字节
|
|
40
|
+
*/
|
|
41
|
+
export function* readMarker(cursor: DecodeCursorAe): DecodeFuncAe<number> {
|
|
42
|
+
let marker: number;
|
|
43
|
+
do {
|
|
44
|
+
if (cursor.offset + 1 > cursor.size) {
|
|
45
|
+
yield cursor.offset - cursor.size + 1;
|
|
46
|
+
}
|
|
47
|
+
marker = cursor.data[cursor.offset++]!;
|
|
48
|
+
} while (marker === constants.NO_OP);
|
|
49
|
+
return marker;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/** 读取一个大于 0 的整数 */
|
|
53
|
+
export function* readLength(cursor: DecodeCursorAe): DecodeFuncAe<number> {
|
|
54
|
+
let marker: number;
|
|
55
|
+
do {
|
|
56
|
+
if (cursor.offset + 1 > cursor.size) {
|
|
57
|
+
yield cursor.offset - cursor.size + 1;
|
|
58
|
+
}
|
|
59
|
+
marker = cursor.data[cursor.offset++]!;
|
|
60
|
+
} while (marker === constants.NO_OP);
|
|
61
|
+
let length: number;
|
|
62
|
+
switch (marker) {
|
|
63
|
+
case constants.INT8:
|
|
64
|
+
if (cursor.offset + 1 > cursor.size) {
|
|
65
|
+
yield cursor.offset - cursor.size + 1;
|
|
66
|
+
}
|
|
67
|
+
length = cursor.view.getInt8(cursor.offset++);
|
|
68
|
+
break;
|
|
69
|
+
case constants.UINT8:
|
|
70
|
+
length = yield* readUint8Data(cursor);
|
|
71
|
+
break;
|
|
72
|
+
case constants.INT16:
|
|
73
|
+
length = yield* readInt16Data(cursor);
|
|
74
|
+
break;
|
|
75
|
+
case constants.INT32:
|
|
76
|
+
length = yield* readInt32Data(cursor);
|
|
77
|
+
break;
|
|
78
|
+
case constants.INT64: {
|
|
79
|
+
const l = yield* readInt64Data(cursor);
|
|
80
|
+
if (l < 0 || l > Number.MAX_SAFE_INTEGER) {
|
|
81
|
+
throw new Error('Invalid length');
|
|
82
|
+
}
|
|
83
|
+
length = Number(l);
|
|
84
|
+
break;
|
|
85
|
+
}
|
|
86
|
+
default:
|
|
87
|
+
throw new Error(`Unexpected marker '${fromCharCode(marker)}'(${marker}) for int length`);
|
|
88
|
+
}
|
|
89
|
+
if (length < 0) {
|
|
90
|
+
throw new Error('Invalid length');
|
|
91
|
+
}
|
|
92
|
+
return length;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/** readInt8Data */
|
|
96
|
+
export function* readInt8Data(cursor: DecodeCursorAe): DecodeFuncAe<number> {
|
|
97
|
+
if (cursor.offset + 1 > cursor.size) {
|
|
98
|
+
yield cursor.offset - cursor.size + 1;
|
|
99
|
+
}
|
|
100
|
+
return cursor.view.getInt8(cursor.offset++);
|
|
101
|
+
}
|
|
102
|
+
/** readUint8Data */
|
|
103
|
+
export function* readUint8Data(cursor: DecodeCursorAe): DecodeFuncAe<number> {
|
|
104
|
+
if (cursor.offset + 1 > cursor.size) {
|
|
105
|
+
yield cursor.offset - cursor.size + 1;
|
|
106
|
+
}
|
|
107
|
+
return cursor.data[cursor.offset++]!;
|
|
108
|
+
}
|
|
109
|
+
/** readInt16Data */
|
|
110
|
+
export function* readInt16Data(cursor: DecodeCursorAe): DecodeFuncAe<number> {
|
|
111
|
+
if (cursor.offset + 2 > cursor.size) {
|
|
112
|
+
yield cursor.offset - cursor.size + 2;
|
|
113
|
+
}
|
|
114
|
+
const value = cursor.view.getInt16(cursor.offset);
|
|
115
|
+
cursor.offset += 2;
|
|
116
|
+
return value;
|
|
117
|
+
}
|
|
118
|
+
/** readInt32Data */
|
|
119
|
+
export function* readInt32Data(cursor: DecodeCursorAe): DecodeFuncAe<number> {
|
|
120
|
+
if (cursor.offset + 4 > cursor.size) {
|
|
121
|
+
yield cursor.offset - cursor.size + 4;
|
|
122
|
+
}
|
|
123
|
+
const value = cursor.view.getInt32(cursor.offset);
|
|
124
|
+
cursor.offset += 4;
|
|
125
|
+
return value;
|
|
126
|
+
}
|
|
127
|
+
/** readInt64Data */
|
|
128
|
+
export function* readInt64Data(cursor: DecodeCursorAe): DecodeFuncAe<bigint> {
|
|
129
|
+
if (cursor.offset + 8 > cursor.size) {
|
|
130
|
+
yield cursor.offset - cursor.size + 8;
|
|
131
|
+
}
|
|
132
|
+
const value = cursor.view.getBigInt64(cursor.offset);
|
|
133
|
+
cursor.offset += 8;
|
|
134
|
+
return value;
|
|
135
|
+
}
|
|
136
|
+
/** readFloat32Data */
|
|
137
|
+
export function* readFloat32Data(cursor: DecodeCursorAe): DecodeFuncAe<number> {
|
|
138
|
+
if (cursor.offset + 4 > cursor.size) {
|
|
139
|
+
yield cursor.offset - cursor.size + 4;
|
|
140
|
+
}
|
|
141
|
+
const value = cursor.view.getFloat32(cursor.offset);
|
|
142
|
+
cursor.offset += 4;
|
|
143
|
+
return value;
|
|
144
|
+
}
|
|
145
|
+
/** readFloat64Data */
|
|
146
|
+
export function* readFloat64Data(cursor: DecodeCursorAe): DecodeFuncAe<number> {
|
|
147
|
+
if (cursor.offset + 8 > cursor.size) {
|
|
148
|
+
yield cursor.offset - cursor.size + 8;
|
|
149
|
+
}
|
|
150
|
+
const value = cursor.view.getFloat64(cursor.offset);
|
|
151
|
+
cursor.offset += 8;
|
|
152
|
+
return value;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/** 读取数据 */
|
|
156
|
+
export function* read(cursor: DecodeCursorAe): DecodeFuncAe<unknown> {
|
|
157
|
+
let marker: number;
|
|
158
|
+
do {
|
|
159
|
+
if (cursor.offset + 1 > cursor.size) {
|
|
160
|
+
yield cursor.offset - cursor.size + 1;
|
|
161
|
+
}
|
|
162
|
+
marker = cursor.data[cursor.offset++]!;
|
|
163
|
+
} while (marker === constants.NO_OP);
|
|
164
|
+
return yield* readData(cursor, marker);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/** 读取优化对象数据 */
|
|
168
|
+
function* readObjectOptimizedData(cursor: DecodeCursorAe, marker: OptimizedFormatMarkers): DecodeFuncAe<unknown> {
|
|
169
|
+
const { count, type } = marker;
|
|
170
|
+
const object: Record<string, unknown> = {};
|
|
171
|
+
for (let i = 0; i < count; i++) {
|
|
172
|
+
const key = yield* readKey(cursor);
|
|
173
|
+
const value = yield* readData(cursor, type ?? (yield* readMarker(cursor)));
|
|
174
|
+
if (key === '__proto__') {
|
|
175
|
+
defineProperty(object, key, { value, enumerable: true, configurable: true, writable: true });
|
|
176
|
+
}
|
|
177
|
+
object[key] = value;
|
|
178
|
+
}
|
|
179
|
+
return object;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/** 根据标签读取后续数据 */
|
|
183
|
+
export function* readData(cursor: DecodeCursorAe, marker: number): DecodeFuncAe<unknown> {
|
|
184
|
+
// 按照出现频率排序
|
|
185
|
+
switch (marker) {
|
|
186
|
+
case constants.STRING: {
|
|
187
|
+
let marker: number;
|
|
188
|
+
do {
|
|
189
|
+
if (cursor.offset + 1 > cursor.size) {
|
|
190
|
+
yield cursor.offset - cursor.size + 1;
|
|
191
|
+
}
|
|
192
|
+
marker = cursor.data[cursor.offset++]!;
|
|
193
|
+
} while (marker === constants.NO_OP);
|
|
194
|
+
let length: number;
|
|
195
|
+
switch (marker) {
|
|
196
|
+
case constants.INT8:
|
|
197
|
+
if (cursor.offset + 1 > cursor.size) {
|
|
198
|
+
yield cursor.offset - cursor.size + 1;
|
|
199
|
+
}
|
|
200
|
+
length = cursor.view.getInt8(cursor.offset++);
|
|
201
|
+
break;
|
|
202
|
+
case constants.UINT8:
|
|
203
|
+
length = yield* readUint8Data(cursor);
|
|
204
|
+
break;
|
|
205
|
+
case constants.INT16:
|
|
206
|
+
length = yield* readInt16Data(cursor);
|
|
207
|
+
break;
|
|
208
|
+
case constants.INT32:
|
|
209
|
+
length = yield* readInt32Data(cursor);
|
|
210
|
+
break;
|
|
211
|
+
case constants.INT64: {
|
|
212
|
+
const l = yield* readInt64Data(cursor);
|
|
213
|
+
if (l < 0 || l > Number.MAX_SAFE_INTEGER) {
|
|
214
|
+
throw new Error('Invalid length');
|
|
215
|
+
}
|
|
216
|
+
length = Number(l);
|
|
217
|
+
break;
|
|
218
|
+
}
|
|
219
|
+
default:
|
|
220
|
+
throw new Error(`Unexpected marker '${fromCharCode(marker)}'(${marker}) for int length`);
|
|
221
|
+
}
|
|
222
|
+
if (length < 0) {
|
|
223
|
+
throw new Error('Invalid length');
|
|
224
|
+
}
|
|
225
|
+
if (cursor.offset + length > cursor.size) {
|
|
226
|
+
yield cursor.offset - cursor.size + length;
|
|
227
|
+
}
|
|
228
|
+
const begin = cursor.offset;
|
|
229
|
+
const end = begin + length;
|
|
230
|
+
cursor.offset = end;
|
|
231
|
+
const { data } = cursor;
|
|
232
|
+
return decode(data, begin, end);
|
|
233
|
+
}
|
|
234
|
+
case constants.OBJECT: {
|
|
235
|
+
let type;
|
|
236
|
+
let count;
|
|
237
|
+
let marker: number;
|
|
238
|
+
do {
|
|
239
|
+
if (cursor.offset + 1 > cursor.size) {
|
|
240
|
+
yield cursor.offset - cursor.size + 1;
|
|
241
|
+
}
|
|
242
|
+
marker = cursor.data[cursor.offset++]!;
|
|
243
|
+
} while (marker === constants.NO_OP);
|
|
244
|
+
switch (marker) {
|
|
245
|
+
case constants.TYPE_MARKER: {
|
|
246
|
+
do {
|
|
247
|
+
if (cursor.offset + 1 > cursor.size) {
|
|
248
|
+
yield cursor.offset - cursor.size + 1;
|
|
249
|
+
}
|
|
250
|
+
type = cursor.data[cursor.offset++]!;
|
|
251
|
+
} while (type === constants.NO_OP);
|
|
252
|
+
let marker2;
|
|
253
|
+
do {
|
|
254
|
+
if (cursor.offset + 1 > cursor.size) {
|
|
255
|
+
yield cursor.offset - cursor.size + 1;
|
|
256
|
+
}
|
|
257
|
+
marker2 = cursor.data[cursor.offset++]!;
|
|
258
|
+
} while (marker2 === constants.NO_OP);
|
|
259
|
+
if (marker2 !== constants.COUNT_MARKER) {
|
|
260
|
+
throw new Error('Expected count marker');
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
/* fall through */
|
|
264
|
+
case constants.COUNT_MARKER: {
|
|
265
|
+
count = yield* readLength(cursor);
|
|
266
|
+
break;
|
|
267
|
+
}
|
|
268
|
+
default: {
|
|
269
|
+
// 不是 '$' 或 '#'
|
|
270
|
+
// 直到 '}'
|
|
271
|
+
const object: Record<string, unknown> = {};
|
|
272
|
+
for (;;) {
|
|
273
|
+
while (marker === constants.NO_OP) {
|
|
274
|
+
if (cursor.offset + 1 > cursor.size) {
|
|
275
|
+
yield cursor.offset - cursor.size + 1;
|
|
276
|
+
}
|
|
277
|
+
marker = cursor.data[cursor.offset++]!;
|
|
278
|
+
}
|
|
279
|
+
if (marker === constants.OBJECT_END) break;
|
|
280
|
+
let length: number;
|
|
281
|
+
switch (marker) {
|
|
282
|
+
case constants.INT8:
|
|
283
|
+
if (cursor.offset + 1 > cursor.size) {
|
|
284
|
+
yield cursor.offset - cursor.size + 1;
|
|
285
|
+
}
|
|
286
|
+
length = cursor.view.getInt8(cursor.offset++);
|
|
287
|
+
break;
|
|
288
|
+
case constants.UINT8:
|
|
289
|
+
length = yield* readUint8Data(cursor);
|
|
290
|
+
break;
|
|
291
|
+
case constants.INT16:
|
|
292
|
+
length = yield* readInt16Data(cursor);
|
|
293
|
+
break;
|
|
294
|
+
case constants.INT32:
|
|
295
|
+
length = yield* readInt32Data(cursor);
|
|
296
|
+
break;
|
|
297
|
+
case constants.INT64: {
|
|
298
|
+
const l = yield* readInt64Data(cursor);
|
|
299
|
+
if (l < 0 || l > Number.MAX_SAFE_INTEGER) {
|
|
300
|
+
throw new Error('Invalid length');
|
|
301
|
+
}
|
|
302
|
+
length = Number(l);
|
|
303
|
+
break;
|
|
304
|
+
}
|
|
305
|
+
default:
|
|
306
|
+
throw new Error(
|
|
307
|
+
`Unexpected marker '${fromCharCode(marker)}'(${marker}) for int length`,
|
|
308
|
+
);
|
|
309
|
+
}
|
|
310
|
+
if (length < 0) {
|
|
311
|
+
throw new Error('Invalid length');
|
|
312
|
+
}
|
|
313
|
+
if (cursor.offset + length > cursor.size) {
|
|
314
|
+
yield cursor.offset - cursor.size + length;
|
|
315
|
+
}
|
|
316
|
+
marker = constants.NO_OP;
|
|
317
|
+
const begin = cursor.offset;
|
|
318
|
+
const end = begin + length;
|
|
319
|
+
cursor.offset = end;
|
|
320
|
+
const { data } = cursor;
|
|
321
|
+
const key = decode(data, begin, end);
|
|
322
|
+
let valueMarker: number;
|
|
323
|
+
do {
|
|
324
|
+
if (cursor.offset + 1 > cursor.size) {
|
|
325
|
+
yield cursor.offset - cursor.size + 1;
|
|
326
|
+
}
|
|
327
|
+
valueMarker = cursor.data[cursor.offset++]!;
|
|
328
|
+
} while (valueMarker === constants.NO_OP);
|
|
329
|
+
const value = yield* readData(cursor, valueMarker);
|
|
330
|
+
if (key === '__proto__') {
|
|
331
|
+
defineProperty(object, key, {
|
|
332
|
+
value,
|
|
333
|
+
enumerable: true,
|
|
334
|
+
configurable: true,
|
|
335
|
+
writable: true,
|
|
336
|
+
});
|
|
337
|
+
}
|
|
338
|
+
object[key] = value;
|
|
339
|
+
}
|
|
340
|
+
return object;
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
return yield* readObjectOptimizedData(cursor, { type, count });
|
|
344
|
+
}
|
|
345
|
+
case constants.ARRAY: {
|
|
346
|
+
let type;
|
|
347
|
+
let count;
|
|
348
|
+
let marker: number;
|
|
349
|
+
do {
|
|
350
|
+
if (cursor.offset + 1 > cursor.size) {
|
|
351
|
+
yield cursor.offset - cursor.size + 1;
|
|
352
|
+
}
|
|
353
|
+
marker = cursor.data[cursor.offset++]!;
|
|
354
|
+
} while (marker === constants.NO_OP);
|
|
355
|
+
switch (marker) {
|
|
356
|
+
case constants.TYPE_MARKER: {
|
|
357
|
+
do {
|
|
358
|
+
if (cursor.offset + 1 > cursor.size) {
|
|
359
|
+
yield cursor.offset - cursor.size + 1;
|
|
360
|
+
}
|
|
361
|
+
type = cursor.data[cursor.offset++]!;
|
|
362
|
+
} while (type === constants.NO_OP);
|
|
363
|
+
let marker2;
|
|
364
|
+
do {
|
|
365
|
+
if (cursor.offset + 1 > cursor.size) {
|
|
366
|
+
yield cursor.offset - cursor.size + 1;
|
|
367
|
+
}
|
|
368
|
+
marker2 = cursor.data[cursor.offset++]!;
|
|
369
|
+
} while (marker2 === constants.NO_OP);
|
|
370
|
+
if (marker2 !== constants.COUNT_MARKER) {
|
|
371
|
+
throw new Error('Expected count marker');
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
/* fall through */
|
|
375
|
+
case constants.COUNT_MARKER: {
|
|
376
|
+
count = yield* readLength(cursor);
|
|
377
|
+
break;
|
|
378
|
+
}
|
|
379
|
+
default: {
|
|
380
|
+
// 不是 '$' 或 '#'
|
|
381
|
+
const array = [];
|
|
382
|
+
for (;;) {
|
|
383
|
+
while (marker === constants.NO_OP) {
|
|
384
|
+
if (cursor.offset + 1 > cursor.size) {
|
|
385
|
+
yield cursor.offset - cursor.size + 1;
|
|
386
|
+
}
|
|
387
|
+
marker = cursor.data[cursor.offset++]!;
|
|
388
|
+
}
|
|
389
|
+
// 直到 ']'
|
|
390
|
+
if (marker === constants.ARRAY_END) break;
|
|
391
|
+
array.push(yield* readData(cursor, marker));
|
|
392
|
+
marker = constants.NO_OP;
|
|
393
|
+
}
|
|
394
|
+
return array;
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
switch (type) {
|
|
398
|
+
case constants.UINT8: {
|
|
399
|
+
if (cursor.offset + count > cursor.size) {
|
|
400
|
+
yield cursor.offset - cursor.size + count;
|
|
401
|
+
}
|
|
402
|
+
const buf = new Uint8Array(
|
|
403
|
+
cursor.data.buffer,
|
|
404
|
+
cursor.data.byteOffset + cursor.offset,
|
|
405
|
+
count,
|
|
406
|
+
).slice();
|
|
407
|
+
cursor.offset += count;
|
|
408
|
+
return buf;
|
|
409
|
+
}
|
|
410
|
+
case constants.INT8: {
|
|
411
|
+
if (cursor.offset + count > cursor.size) {
|
|
412
|
+
yield cursor.offset - cursor.size + count;
|
|
413
|
+
}
|
|
414
|
+
const buf = new Int8Array(
|
|
415
|
+
cursor.data.buffer,
|
|
416
|
+
cursor.data.byteOffset + cursor.offset,
|
|
417
|
+
count,
|
|
418
|
+
).slice();
|
|
419
|
+
cursor.offset += count;
|
|
420
|
+
return buf;
|
|
421
|
+
}
|
|
422
|
+
case constants.INT16: {
|
|
423
|
+
if (cursor.offset + count * 2 > cursor.size) {
|
|
424
|
+
yield cursor.offset - cursor.size + count * 2;
|
|
425
|
+
}
|
|
426
|
+
const result = new Int16Array(count);
|
|
427
|
+
for (let i = 0; i < count; i++) {
|
|
428
|
+
result[i] = yield* readInt16Data(cursor);
|
|
429
|
+
}
|
|
430
|
+
return result;
|
|
431
|
+
}
|
|
432
|
+
case constants.INT32: {
|
|
433
|
+
if (cursor.offset + count * 4 > cursor.size) {
|
|
434
|
+
yield cursor.offset - cursor.size + count * 4;
|
|
435
|
+
}
|
|
436
|
+
const result = new Int32Array(count);
|
|
437
|
+
for (let i = 0; i < count; i++) {
|
|
438
|
+
result[i] = yield* readInt32Data(cursor);
|
|
439
|
+
}
|
|
440
|
+
return result;
|
|
441
|
+
}
|
|
442
|
+
case constants.FLOAT32: {
|
|
443
|
+
if (cursor.offset + count * 4 > cursor.size) {
|
|
444
|
+
yield cursor.offset - cursor.size + count * 4;
|
|
445
|
+
}
|
|
446
|
+
const result = new Float32Array(count);
|
|
447
|
+
for (let i = 0; i < count; i++) {
|
|
448
|
+
result[i] = yield* readFloat32Data(cursor);
|
|
449
|
+
}
|
|
450
|
+
return result;
|
|
451
|
+
}
|
|
452
|
+
case constants.FLOAT64: {
|
|
453
|
+
if (cursor.offset + count * 8 > cursor.size) {
|
|
454
|
+
yield cursor.offset - cursor.size + count * 8;
|
|
455
|
+
}
|
|
456
|
+
const result = new Float64Array(count);
|
|
457
|
+
for (let i = 0; i < count; i++) {
|
|
458
|
+
result[i] = yield* readFloat64Data(cursor);
|
|
459
|
+
}
|
|
460
|
+
return result;
|
|
461
|
+
}
|
|
462
|
+
case constants.INT64: {
|
|
463
|
+
if (cursor.offset + count * 8 > cursor.size) {
|
|
464
|
+
yield cursor.offset - cursor.size + count * 8;
|
|
465
|
+
}
|
|
466
|
+
const result = new BigInt64Array(count);
|
|
467
|
+
for (let i = 0; i < count; i++) {
|
|
468
|
+
result[i] = yield* readInt64Data(cursor);
|
|
469
|
+
}
|
|
470
|
+
return result;
|
|
471
|
+
}
|
|
472
|
+
case constants.NULL:
|
|
473
|
+
return Array.from({ length: count }).fill(null);
|
|
474
|
+
case constants.TRUE:
|
|
475
|
+
return Array.from({ length: count }).fill(true);
|
|
476
|
+
case constants.FALSE:
|
|
477
|
+
return Array.from({ length: count }).fill(false);
|
|
478
|
+
default:
|
|
479
|
+
break;
|
|
480
|
+
}
|
|
481
|
+
const array: unknown[] = [];
|
|
482
|
+
array.length = count;
|
|
483
|
+
for (let i = 0; i < count; i++) {
|
|
484
|
+
array[i] = type === undefined ? yield* read(cursor) : yield* readData(cursor, type);
|
|
485
|
+
}
|
|
486
|
+
return array;
|
|
487
|
+
}
|
|
488
|
+
case constants.FLOAT64: {
|
|
489
|
+
if (cursor.offset + 8 > cursor.size) {
|
|
490
|
+
yield cursor.offset - cursor.size + 8;
|
|
491
|
+
}
|
|
492
|
+
const value = cursor.view.getFloat64(cursor.offset);
|
|
493
|
+
cursor.offset += 8;
|
|
494
|
+
return value;
|
|
495
|
+
}
|
|
496
|
+
case constants.UINT8: {
|
|
497
|
+
if (cursor.offset + 1 > cursor.size) {
|
|
498
|
+
yield cursor.offset - cursor.size + 1;
|
|
499
|
+
}
|
|
500
|
+
return cursor.data[cursor.offset++]!;
|
|
501
|
+
}
|
|
502
|
+
case constants.INT16: {
|
|
503
|
+
if (cursor.offset + 2 > cursor.size) {
|
|
504
|
+
yield cursor.offset - cursor.size + 2;
|
|
505
|
+
}
|
|
506
|
+
const value = cursor.view.getInt16(cursor.offset);
|
|
507
|
+
cursor.offset += 2;
|
|
508
|
+
return value;
|
|
509
|
+
}
|
|
510
|
+
case constants.FLOAT32: {
|
|
511
|
+
if (cursor.offset + 4 > cursor.size) {
|
|
512
|
+
yield cursor.offset - cursor.size + 4;
|
|
513
|
+
}
|
|
514
|
+
const value = cursor.view.getFloat32(cursor.offset);
|
|
515
|
+
cursor.offset += 4;
|
|
516
|
+
return value;
|
|
517
|
+
}
|
|
518
|
+
case constants.CHAR: {
|
|
519
|
+
if (cursor.offset + 1 > cursor.size) {
|
|
520
|
+
yield cursor.offset - cursor.size + 1;
|
|
521
|
+
}
|
|
522
|
+
return fromCharCode(cursor.data[cursor.offset++]!);
|
|
523
|
+
}
|
|
524
|
+
case constants.INT32: {
|
|
525
|
+
if (cursor.offset + 4 > cursor.size) {
|
|
526
|
+
yield cursor.offset - cursor.size + 4;
|
|
527
|
+
}
|
|
528
|
+
const value = cursor.view.getInt32(cursor.offset);
|
|
529
|
+
cursor.offset += 4;
|
|
530
|
+
return value;
|
|
531
|
+
}
|
|
532
|
+
case constants.INT8: {
|
|
533
|
+
if (cursor.offset + 1 > cursor.size) {
|
|
534
|
+
yield cursor.offset - cursor.size + 1;
|
|
535
|
+
}
|
|
536
|
+
return cursor.view.getInt8(cursor.offset++);
|
|
537
|
+
}
|
|
538
|
+
case constants.NULL:
|
|
539
|
+
return null;
|
|
540
|
+
case constants.TRUE:
|
|
541
|
+
return true;
|
|
542
|
+
case constants.FALSE:
|
|
543
|
+
return false;
|
|
544
|
+
case constants.INT64: {
|
|
545
|
+
if (cursor.offset + 8 > cursor.size) {
|
|
546
|
+
yield cursor.offset - cursor.size + 8;
|
|
547
|
+
}
|
|
548
|
+
const value = cursor.view.getBigInt64(cursor.offset);
|
|
549
|
+
cursor.offset += 8;
|
|
550
|
+
if (value < Number.MIN_SAFE_INTEGER || value > Number.MAX_SAFE_INTEGER) {
|
|
551
|
+
return value;
|
|
552
|
+
}
|
|
553
|
+
return Number(value);
|
|
554
|
+
}
|
|
555
|
+
case constants.HIGH_PRECISION_NUMBER: {
|
|
556
|
+
const length = yield* readLength(cursor);
|
|
557
|
+
if (cursor.offset + length > cursor.size) {
|
|
558
|
+
yield cursor.offset - cursor.size + length;
|
|
559
|
+
}
|
|
560
|
+
const begin = cursor.offset;
|
|
561
|
+
const _buffer = new Uint8Array(cursor.data.buffer, begin, length).slice();
|
|
562
|
+
cursor.offset = begin + length;
|
|
563
|
+
// return _buffer
|
|
564
|
+
unsupportedType('high precision number');
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
throw new Error(`Unexpected marker '${fromCharCode(marker)}'(${marker})`);
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
/** readKey */
|
|
571
|
+
export function* readKey(cursor: DecodeCursorAe): DecodeFuncAe<string> {
|
|
572
|
+
let marker: number;
|
|
573
|
+
do {
|
|
574
|
+
if (cursor.offset + 1 > cursor.size) {
|
|
575
|
+
yield cursor.offset - cursor.size + 1;
|
|
576
|
+
}
|
|
577
|
+
marker = cursor.data[cursor.offset++]!;
|
|
578
|
+
} while (marker === constants.NO_OP);
|
|
579
|
+
let length: number;
|
|
580
|
+
switch (marker) {
|
|
581
|
+
case constants.INT8:
|
|
582
|
+
if (cursor.offset + 1 > cursor.size) {
|
|
583
|
+
yield cursor.offset - cursor.size + 1;
|
|
584
|
+
}
|
|
585
|
+
length = cursor.view.getInt8(cursor.offset++);
|
|
586
|
+
break;
|
|
587
|
+
case constants.UINT8:
|
|
588
|
+
length = yield* readUint8Data(cursor);
|
|
589
|
+
break;
|
|
590
|
+
case constants.INT16:
|
|
591
|
+
length = yield* readInt16Data(cursor);
|
|
592
|
+
break;
|
|
593
|
+
case constants.INT32:
|
|
594
|
+
length = yield* readInt32Data(cursor);
|
|
595
|
+
break;
|
|
596
|
+
case constants.INT64: {
|
|
597
|
+
const l = yield* readInt64Data(cursor);
|
|
598
|
+
if (l < 0 || l > Number.MAX_SAFE_INTEGER) {
|
|
599
|
+
throw new Error('Invalid length');
|
|
600
|
+
}
|
|
601
|
+
length = Number(l);
|
|
602
|
+
break;
|
|
603
|
+
}
|
|
604
|
+
default:
|
|
605
|
+
throw new Error(`Unexpected marker '${fromCharCode(marker)}'(${marker}) for int length`);
|
|
606
|
+
}
|
|
607
|
+
if (length < 0) {
|
|
608
|
+
throw new Error('Invalid length');
|
|
609
|
+
}
|
|
610
|
+
if (cursor.offset + length > cursor.size) {
|
|
611
|
+
yield cursor.offset - cursor.size + length;
|
|
612
|
+
}
|
|
613
|
+
const begin = cursor.offset;
|
|
614
|
+
const end = begin + length;
|
|
615
|
+
cursor.offset = end;
|
|
616
|
+
const { data } = cursor;
|
|
617
|
+
return decode(data, begin, end);
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
/** Optimized Format 数据 */
|
|
621
|
+
export type OptimizedFormatMarkers = { type?: number; count: number };
|
package/src/helper/decode.ts
CHANGED
|
@@ -81,7 +81,7 @@ export function readLength(cursor: DecodeCursor): number {
|
|
|
81
81
|
break;
|
|
82
82
|
}
|
|
83
83
|
default:
|
|
84
|
-
throw new Error(`Unexpected marker '${
|
|
84
|
+
throw new Error(`Unexpected marker '${fromCharCode(marker)}'(${marker}) for int length`);
|
|
85
85
|
}
|
|
86
86
|
if (length < 0) {
|
|
87
87
|
throw new Error('Invalid length');
|
|
@@ -210,10 +210,11 @@ export function readData(cursor: DecodeCursor, marker: number): unknown {
|
|
|
210
210
|
const markers = readOptimizedFormatMarkers(cursor);
|
|
211
211
|
if (markers == null) {
|
|
212
212
|
const array = [];
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
213
|
+
for (;;) {
|
|
214
|
+
const marker = readMarker(cursor);
|
|
215
|
+
// 直到 ']'
|
|
216
|
+
if (marker === constants.ARRAY_END) break;
|
|
217
|
+
array.push(readData(cursor, marker));
|
|
217
218
|
}
|
|
218
219
|
return array;
|
|
219
220
|
}
|
package/src/index.ts
CHANGED
|
@@ -1,15 +1,18 @@
|
|
|
1
1
|
import { getEncoder } from './encoder.js';
|
|
2
2
|
import { Decoder } from './decoder.js';
|
|
3
|
+
import type { EncodeOptions } from './options.js';
|
|
4
|
+
|
|
3
5
|
export { UnexpectedEofError as UnexpectedEof } from './helper/errors.js';
|
|
6
|
+
export type { EncodeOptions };
|
|
4
7
|
|
|
5
8
|
/** 编码为 UBJSON */
|
|
6
|
-
export function encode(value: unknown): Uint8Array {
|
|
7
|
-
return getEncoder().encode(value);
|
|
9
|
+
export function encode(value: unknown, options?: EncodeOptions): Uint8Array {
|
|
10
|
+
return getEncoder(options).encode(value);
|
|
8
11
|
}
|
|
9
12
|
|
|
10
13
|
/** 编码为 UBJSON */
|
|
11
|
-
export function encodeMany(value: Iterable<unknown
|
|
12
|
-
return getEncoder().encodeMany(value);
|
|
14
|
+
export function encodeMany(value: Iterable<unknown>, options?: EncodeOptions): Uint8Array {
|
|
15
|
+
return getEncoder(options).encodeMany(value);
|
|
13
16
|
}
|
|
14
17
|
|
|
15
18
|
/** 解码 UBJSON */
|