@cloudpss/ubjson 0.3.0-alpha.21

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/index.js ADDED
@@ -0,0 +1,3 @@
1
+ export { encode } from './encoder.js';
2
+ export { decode } from './decoder.js';
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACtC,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC"}
package/package.json ADDED
@@ -0,0 +1,33 @@
1
+ {
2
+ "name": "@cloudpss/ubjson",
3
+ "version": "0.3.0-alpha.21",
4
+ "author": "CloudPSS",
5
+ "license": "MIT",
6
+ "keywords": [
7
+ "ubjson",
8
+ "universal binary json",
9
+ "json",
10
+ "binary"
11
+ ],
12
+ "type": "module",
13
+ "main": "dist/index.js",
14
+ "module": "dist/index.js",
15
+ "types": "dist/index.d.ts",
16
+ "exports": {
17
+ "types": "./dist/index.d.ts",
18
+ "default": "./dist/index.js"
19
+ },
20
+ "scripts": {
21
+ "start": "yarn clean && tsc --watch",
22
+ "build": "yarn clean && tsc",
23
+ "prepublishOnly": "yarn build",
24
+ "clean": "rimraf dist",
25
+ "benchmark": "node ./benchmark",
26
+ "test": "c8 tape-es \"./test/*\""
27
+ },
28
+ "devDependencies": {
29
+ "c8": "^7.10.0",
30
+ "tape": "^5.2.2",
31
+ "tape-es": "^1.2.15"
32
+ }
33
+ }
@@ -0,0 +1,22 @@
1
+ export const NULL = 'Z'.charCodeAt(0);
2
+ export const NO_OP = 'N'.charCodeAt(0);
3
+ export const TRUE = 'T'.charCodeAt(0);
4
+ export const FALSE = 'F'.charCodeAt(0);
5
+ export const INT8 = 'i'.charCodeAt(0);
6
+ export const UINT8 = 'U'.charCodeAt(0);
7
+ export const INT16 = 'I'.charCodeAt(0);
8
+ export const INT32 = 'l'.charCodeAt(0);
9
+ export const INT64 = 'L'.charCodeAt(0);
10
+ export const FLOAT32 = 'd'.charCodeAt(0);
11
+ export const FLOAT64 = 'D'.charCodeAt(0);
12
+ export const HIGH_PRECISION_NUMBER = 'H'.charCodeAt(0);
13
+ export const CHAR = 'C'.charCodeAt(0);
14
+ export const STRING = 'S'.charCodeAt(0);
15
+
16
+ export const ARRAY = '['.charCodeAt(0);
17
+ export const ARRAY_END = ']'.charCodeAt(0);
18
+ export const OBJECT = '{'.charCodeAt(0);
19
+ export const OBJECT_END = '}'.charCodeAt(0);
20
+
21
+ export const TYPE_MARKER = '$'.charCodeAt(0);
22
+ export const COUNT_MARKER = '#'.charCodeAt(0);
package/src/decoder.ts ADDED
@@ -0,0 +1,278 @@
1
+ import * as constants from './constants.js';
2
+
3
+ const textDecoder = new TextDecoder();
4
+
5
+ /** decoder */
6
+ class Decoder {
7
+ private readonly view: DataView;
8
+ private offset = 0;
9
+ constructor(readonly data: Uint8Array) {
10
+ this.view = new DataView(data.buffer, data.byteOffset, data.byteLength);
11
+ }
12
+ /** 解码 */
13
+ decode(): unknown {
14
+ this.offset = 0;
15
+ return this.read();
16
+ }
17
+
18
+ /** 检查是否有给定字节数的未读数据 */
19
+ private ensureData(byteLength: number): void {
20
+ if (this.offset + byteLength > this.data.byteLength) {
21
+ throw new Error('Unexpected EOF');
22
+ }
23
+ }
24
+
25
+ /** 读取 marker,跳过 noop */
26
+ private readMarker(): number {
27
+ let marker = constants.NO_OP;
28
+ do {
29
+ if (this.offset >= this.data.byteLength) break;
30
+ marker = this.view.getUint8(this.offset++);
31
+ } while (marker === constants.NO_OP);
32
+ return marker;
33
+ }
34
+ /** 读取数据 */
35
+ private read(marker = this.readMarker()): unknown {
36
+ switch (marker) {
37
+ case constants.NO_OP:
38
+ return undefined;
39
+ case constants.NULL:
40
+ return null;
41
+ case constants.TRUE:
42
+ return true;
43
+ case constants.FALSE:
44
+ return false;
45
+ case constants.UINT8:
46
+ return this.readUint8Data();
47
+ case constants.INT8:
48
+ return this.readInt8Data();
49
+ case constants.INT16:
50
+ return this.readInt16Data();
51
+ case constants.INT32:
52
+ return this.readInt32Data();
53
+ case constants.INT64:
54
+ return this.readInt64Data();
55
+ case constants.FLOAT32:
56
+ return this.readFloat32Data();
57
+ case constants.FLOAT64:
58
+ return this.readFloat64Data();
59
+ case constants.HIGH_PRECISION_NUMBER:
60
+ return this.readHighPrecisionNumberData();
61
+ case constants.CHAR:
62
+ return this.readCharData();
63
+ case constants.STRING:
64
+ return this.readStringData();
65
+ case constants.ARRAY:
66
+ return this.readArray();
67
+ case constants.OBJECT:
68
+ return this.readObject();
69
+ }
70
+ throw new Error(`Unexpected marker '${String.fromCharCode(marker)}'(${marker})`);
71
+ }
72
+
73
+ /** 读取一个大于 0 的整数 */
74
+ private readIntLength(): number {
75
+ const marker = this.readMarker();
76
+ let length;
77
+ switch (marker) {
78
+ case constants.INT8:
79
+ length = this.readInt8Data();
80
+ break;
81
+ case constants.INT16:
82
+ length = this.readInt16Data();
83
+ break;
84
+ case constants.INT32:
85
+ length = this.readInt32Data();
86
+ break;
87
+ /* c8 ignore next 3 */
88
+ case constants.INT64:
89
+ length = this.readInt64Data();
90
+ break;
91
+ }
92
+ if (length === undefined) {
93
+ throw new Error(`Unexpected marker '${String.fromCharCode(marker)}'(${marker}) for int length`);
94
+ }
95
+ if (length < 0) throw new Error('Invalid length');
96
+ return length;
97
+ }
98
+ /** readStringData */
99
+ private readStringData(): string {
100
+ const length = this.readIntLength();
101
+ this.ensureData(length);
102
+ const buffer = this.data.subarray(this.offset, this.offset + length);
103
+ this.offset += length;
104
+ return textDecoder.decode(buffer);
105
+ }
106
+ /** readHighPrecisionNumberData */
107
+ private readHighPrecisionNumberData(): never {
108
+ const length = this.readIntLength();
109
+ this.ensureData(length);
110
+ throw new Error('Unsupported type high precision number');
111
+ // const buffer = this.data.subarray(this.offset, this.offset + length);
112
+ // this.offset += length;
113
+ // return buffer.slice();
114
+ }
115
+ /** readStringData */
116
+ private readCharData(): string {
117
+ return String.fromCharCode(this.readUint8Data());
118
+ }
119
+ /** readInt8Data */
120
+ private readInt8Data(): number {
121
+ this.ensureData(1);
122
+ const result = this.view.getInt8(this.offset);
123
+ this.offset += 1;
124
+ return result;
125
+ }
126
+ /** readUint8Data */
127
+ private readUint8Data(): number {
128
+ this.ensureData(1);
129
+ const result = this.view.getUint8(this.offset);
130
+ this.offset += 1;
131
+ return result;
132
+ }
133
+ /** readInt16Data */
134
+ private readInt16Data(): number {
135
+ this.ensureData(2);
136
+ const result = this.view.getInt16(this.offset);
137
+ this.offset += 2;
138
+ return result;
139
+ }
140
+ /** readInt32Data */
141
+ private readInt32Data(): number {
142
+ this.ensureData(4);
143
+ const result = this.view.getInt32(this.offset);
144
+ this.offset += 4;
145
+ return result;
146
+ }
147
+ /** readInt64Data */
148
+ private readInt64Data(): never {
149
+ this.ensureData(8);
150
+ throw new Error('Unsupported type int64');
151
+ // const result = this.view.getBigInt64(this.offset);
152
+ // this.offset += 8;
153
+ // return result;
154
+ }
155
+ /** readFloat32Data */
156
+ private readFloat32Data(): number {
157
+ this.ensureData(4);
158
+ const result = this.view.getFloat32(this.offset);
159
+ this.offset += 4;
160
+ return result;
161
+ }
162
+ /** readFloat64Data */
163
+ private readFloat64Data(): number {
164
+ this.ensureData(8);
165
+ const result = this.view.getFloat64(this.offset);
166
+ this.offset += 8;
167
+ return result;
168
+ }
169
+
170
+ /** 读取 Optimized Format 数据 */
171
+ private readOptimizedFormatMarkers(): { type?: number; count: number } | undefined {
172
+ let type;
173
+ let count;
174
+ switch (this.readMarker()) {
175
+ case constants.TYPE_MARKER:
176
+ type = this.readMarker();
177
+ if (this.readMarker() !== constants.COUNT_MARKER) {
178
+ throw new Error('Expected count marker');
179
+ }
180
+ /* fall through */
181
+ case constants.COUNT_MARKER:
182
+ count = this.readIntLength();
183
+ break;
184
+ default:
185
+ // 不是 '$' 或 '#',回溯
186
+ this.offset--;
187
+ return undefined;
188
+ }
189
+ return { type, count };
190
+ }
191
+
192
+ /** 读取数组 */
193
+ private readArray(): unknown[] | ArrayBufferView {
194
+ const markers = this.readOptimizedFormatMarkers();
195
+ if (markers == null) {
196
+ const array = [];
197
+ // 直到 ']'
198
+ while (this.readMarker() !== constants.ARRAY_END) {
199
+ this.offset--;
200
+ array.push(this.read());
201
+ }
202
+ return array;
203
+ }
204
+
205
+ const { count, type } = markers;
206
+ switch (type) {
207
+ case constants.NULL:
208
+ return new Array<null>(count).fill(null);
209
+ case constants.TRUE:
210
+ return new Array<true>(count).fill(true);
211
+ case constants.FALSE:
212
+ return new Array<false>(count).fill(false);
213
+ case constants.UINT8:
214
+ this.ensureData(count);
215
+ this.offset += count;
216
+ return new Uint8Array(this.data.buffer, this.data.byteOffset + this.offset - count, count).slice();
217
+ case constants.INT8:
218
+ this.ensureData(count);
219
+ this.offset += count;
220
+ return new Int8Array(this.data.buffer, this.data.byteOffset + this.offset - count, count).slice();
221
+ case constants.INT16:
222
+ this.ensureData(count * 2);
223
+ return Int16Array.from({ length: count }, () => this.readInt16Data());
224
+ case constants.INT32:
225
+ this.ensureData(count * 4);
226
+ return Int32Array.from({ length: count }, () => this.readInt32Data());
227
+ /* c8 ignore next 3 */
228
+ case constants.INT64:
229
+ this.ensureData(count * 8);
230
+ return BigInt64Array.from({ length: count }, () => this.readInt64Data());
231
+ case constants.FLOAT32:
232
+ this.ensureData(count * 4);
233
+ return Float32Array.from({ length: count }, () => this.readFloat32Data());
234
+ case constants.FLOAT64: {
235
+ this.ensureData(count * 8);
236
+ const result = new Float64Array(count);
237
+ for (let i = 0; i < count; i++) {
238
+ result[i] = this.readFloat64Data();
239
+ }
240
+ return result;
241
+ }
242
+ }
243
+ const array = new Array<unknown>(count);
244
+ for (let i = 0; i < count; i++) {
245
+ array[i] = this.read(type);
246
+ }
247
+ return array;
248
+ }
249
+
250
+ /** 读对象 */
251
+ private readObject(): Record<string, unknown> {
252
+ const markers = this.readOptimizedFormatMarkers();
253
+ if (markers == null) {
254
+ // 直到 '}'
255
+ const object: Array<[string, unknown]> = [];
256
+ while (this.readMarker() !== constants.OBJECT_END) {
257
+ this.offset--;
258
+ const key = this.readStringData();
259
+ object.push([key, this.read()]);
260
+ }
261
+ return Object.fromEntries(object);
262
+ }
263
+
264
+ const { count, type } = markers;
265
+ const object = new Array<[string, unknown]>(count);
266
+ for (let i = 0; i < count; i++) {
267
+ const key = this.readStringData();
268
+ object[i] = [key, this.read(type)];
269
+ }
270
+ return Object.fromEntries(object);
271
+ }
272
+ }
273
+
274
+ /** 解码 */
275
+ export function decode(value: Uint8Array): unknown {
276
+ const decoder = new Decoder(value);
277
+ return decoder.decode();
278
+ }
package/src/encoder.ts ADDED
@@ -0,0 +1,340 @@
1
+ /* eslint-disable @typescript-eslint/unbound-method */
2
+ import * as constants from './constants.js';
3
+
4
+ const INITIAL_SIZE = 1024 * 8;
5
+ const MAX_SIZE = 1024 * 1024 * 128;
6
+ const RESIZE_FACTOR = 4;
7
+ const RESIZE_FACTOR_2 = 2;
8
+
9
+ const textEncoder = new TextEncoder();
10
+
11
+ /* c8 ignore next 3 */
12
+ const hasOwn =
13
+ (Object as unknown as { /** hasOwn */ hasOwn(obj: object, property: string): boolean }).hasOwn ??
14
+ Object.prototype.hasOwnProperty.call.bind(Object.prototype.hasOwnProperty);
15
+
16
+ /** 编码至 ubjson */
17
+ class Encoder {
18
+ /** 当前写指针位置 */
19
+ private length = 0;
20
+ /** 数据 */
21
+ private buffer: Uint8Array;
22
+ /** buffer 的 DataView */
23
+ private view: DataView;
24
+
25
+ constructor() {
26
+ const buffer = new Uint8Array(INITIAL_SIZE);
27
+ this.buffer = buffer;
28
+ this.view = new DataView(buffer.buffer);
29
+ }
30
+
31
+ /**
32
+ * 确保 buffer 还有 capacity 的空闲空间
33
+ */
34
+ private ensureCapacity(capacity: number): void {
35
+ let nextCapacity = this.length + capacity;
36
+ // 无需扩容
37
+ if (this.buffer.byteLength >= nextCapacity) return;
38
+ /* c8 ignore next 3 */
39
+ if (nextCapacity > MAX_SIZE) {
40
+ throw new Error('Buffer has exceed max size');
41
+ }
42
+
43
+ if (nextCapacity < this.buffer.byteLength * RESIZE_FACTOR) {
44
+ nextCapacity = (this.buffer.byteLength * RESIZE_FACTOR) | 0;
45
+ } else {
46
+ nextCapacity = (this.buffer.byteLength / RESIZE_FACTOR_2 + nextCapacity) | 0;
47
+ }
48
+ /* c8 ignore next 3 */
49
+ if (nextCapacity > MAX_SIZE) {
50
+ nextCapacity = MAX_SIZE;
51
+ }
52
+
53
+ const newBuffer = new Uint8Array(nextCapacity);
54
+ newBuffer.set(this.buffer, 0);
55
+ this.buffer = newBuffer;
56
+ this.view = new DataView(newBuffer.buffer);
57
+ }
58
+ /** 获取写入结果 */
59
+ finish(): Uint8Array {
60
+ return this.buffer.slice(0, this.length);
61
+ }
62
+ /** 写入一个对象 */
63
+ write(value: unknown): void {
64
+ switch (typeof value) {
65
+ case 'undefined':
66
+ return this.writeNoOp();
67
+ case 'boolean':
68
+ return this.writeBoolean(value);
69
+ case 'number':
70
+ return this.writeNumber(value);
71
+ case 'string':
72
+ if (value.length === 1 && value.charCodeAt(0) < 255) {
73
+ // 1 byte string
74
+ return this.writeChar(value);
75
+ }
76
+ return this.writeString(value);
77
+ case 'object': {
78
+ if (value === null) {
79
+ return this.writeNull();
80
+ }
81
+ if (Array.isArray(value)) {
82
+ return this.writeArray(value);
83
+ }
84
+ if (ArrayBuffer.isView(value)) {
85
+ return this.writeTypedArray(value);
86
+ }
87
+ return this.writeObject(value as Record<string, unknown>);
88
+ }
89
+ }
90
+ throw new Error(`Unsupported type ${Object.prototype.toString.call(value)}`);
91
+ }
92
+ /** 写入 marker */
93
+ private writeMarker(marker: number): void {
94
+ this.ensureCapacity(1);
95
+ this.view.setUint8(this.length, marker);
96
+ this.length += 1;
97
+ }
98
+
99
+ /** 写入 marker */
100
+ private writeNull(): void {
101
+ this.writeMarker(constants.NULL);
102
+ }
103
+
104
+ /** writeNoOp */
105
+ private writeNoOp(): void {
106
+ this.writeMarker(constants.NO_OP);
107
+ }
108
+
109
+ /** writeBoolean */
110
+ private writeBoolean(value: boolean): void {
111
+ this.writeMarker(value ? constants.TRUE : constants.FALSE);
112
+ }
113
+
114
+ /** writeInt8 */
115
+ private writeInt8(value: number): void {
116
+ this.writeMarker(constants.INT8);
117
+ this.writeInt8Data(value);
118
+ }
119
+
120
+ /** writeInt8Data */
121
+ private writeInt8Data(value: number): void {
122
+ this.ensureCapacity(1);
123
+ this.view.setInt8(this.length, value);
124
+ this.length += 1;
125
+ }
126
+
127
+ /** writeUint8 */
128
+ private writeUint8(value: number): void {
129
+ this.writeMarker(constants.UINT8);
130
+ this.writeUint8Data(value);
131
+ }
132
+
133
+ /** writeUint8Data */
134
+ private writeUint8Data(value: number): void {
135
+ this.ensureCapacity(1);
136
+ this.view.setUint8(this.length, value);
137
+ this.length += 1;
138
+ }
139
+
140
+ /** writeInt16 */
141
+ private writeInt16(value: number): void {
142
+ this.writeMarker(constants.INT16);
143
+ this.writeInt16Data(value);
144
+ }
145
+
146
+ /** writeInt16Data */
147
+ private writeInt16Data(value: number): void {
148
+ this.ensureCapacity(2);
149
+ this.view.setInt16(this.length, value);
150
+ this.length += 2;
151
+ }
152
+
153
+ /** writeInt32 */
154
+ private writeInt32(value: number): void {
155
+ this.writeMarker(constants.INT32);
156
+ this.writeInt32Data(value);
157
+ }
158
+
159
+ /** writeInt32Data */
160
+ private writeInt32Data(value: number): void {
161
+ this.ensureCapacity(4);
162
+ this.view.setInt32(this.length, value);
163
+ this.length += 4;
164
+ }
165
+
166
+ /** writeFloat32 */
167
+ private writeFloat32(value: number): void {
168
+ this.writeMarker(constants.FLOAT32);
169
+ this.writeFloat32Data(value);
170
+ }
171
+
172
+ /** writeFloat32Data */
173
+ private writeFloat32Data(value: number): void {
174
+ this.ensureCapacity(4);
175
+ this.view.setFloat32(this.length, value);
176
+ this.length += 4;
177
+ }
178
+
179
+ /** writeFloat64 */
180
+ private writeFloat64(value: number): void {
181
+ this.writeMarker(constants.FLOAT64);
182
+ this.writeFloat64Data(value);
183
+ }
184
+
185
+ /** writeFloat64Data */
186
+ private writeFloat64Data(value: number): void {
187
+ this.ensureCapacity(8);
188
+ this.view.setFloat64(this.length, value);
189
+ this.length += 8;
190
+ }
191
+
192
+ /** writeChar */
193
+ private writeChar(value: string): void {
194
+ this.writeMarker(constants.CHAR);
195
+ this.writeCharData(value);
196
+ }
197
+
198
+ /** writeCharData */
199
+ private writeCharData(value: string): void {
200
+ this.ensureCapacity(1);
201
+ this.view.setUint8(this.length, value.charCodeAt(0));
202
+ this.length += 1;
203
+ }
204
+
205
+ /** writeString */
206
+ private writeString(value: string): void {
207
+ this.writeMarker(constants.STRING);
208
+ this.writeStringData(value);
209
+ }
210
+
211
+ /** writeStringData */
212
+ private writeStringData(value: string): void {
213
+ if (textEncoder.encodeInto != null) {
214
+ const maxUsage = value.length * 3;
215
+ const currentPos = this.length;
216
+ // 先写入最大大小
217
+ const lengthWriter = this.writeInt(maxUsage);
218
+ this.ensureCapacity(maxUsage);
219
+ // 写入文本数据
220
+ const { written } = textEncoder.encodeInto(value, this.buffer.subarray(this.length));
221
+ // 回溯,写入实际大小
222
+ this.length = currentPos;
223
+ lengthWriter.call(this, written as number);
224
+ // 移动指针到写入末尾
225
+ this.length += written as number;
226
+ return;
227
+ }
228
+ const data = textEncoder.encode(value);
229
+ this.writeInt(data.length);
230
+ this.ensureCapacity(data.length);
231
+ this.buffer.set(data, this.length);
232
+ this.length += data.length;
233
+ }
234
+
235
+ /**
236
+ * 写入整形数字,选取合适的大小
237
+ *
238
+ * @throws 无法在 int32 范围内表示
239
+ */
240
+ private writeInt(value: number): (this: this, value: number) => void {
241
+ value = value | 0;
242
+ if (value >= -128 && value <= 127) {
243
+ this.writeInt8(value);
244
+ return this.writeInt8;
245
+ }
246
+ if (value >= -32768 && value <= 32767) {
247
+ this.writeInt16(value);
248
+ return this.writeInt16;
249
+ }
250
+ if (value >= -2147483648 && value <= 2147483647) {
251
+ this.writeInt32(value);
252
+ return this.writeInt32;
253
+ }
254
+ /* c8 ignore next 2 */
255
+ throw new Error(`Unsupported int value ${value}: out of range`);
256
+ }
257
+
258
+ /** 写入数字,选取合适的大小 */
259
+ private writeNumber(value: number): void {
260
+ if (Number.isInteger(value) && value >= -2147483648 && value <= 2147483647) {
261
+ if (value >= 0 && value <= 255) return this.writeUint8(value);
262
+ this.writeInt(value);
263
+ return;
264
+ }
265
+ if (!Number.isFinite(value) || Math.fround(value) === value) {
266
+ return this.writeFloat32(value);
267
+ }
268
+ return this.writeFloat64(value);
269
+ }
270
+
271
+ /** writeObject */
272
+ private writeObject(value: Record<string, unknown>): void {
273
+ this.writeMarker(constants.OBJECT);
274
+ for (const key in value) {
275
+ if (!hasOwn(value, key)) continue;
276
+ const element = value[key];
277
+ if (element === undefined) continue;
278
+ this.writeStringData(key);
279
+ this.write(element);
280
+ }
281
+ this.writeMarker(constants.OBJECT_END);
282
+ }
283
+
284
+ /** writeArray */
285
+ private writeArray(value: unknown[]): void {
286
+ this.writeMarker(constants.ARRAY);
287
+ for (const v of value) {
288
+ if (v == null) this.writeNull();
289
+ else this.write(v);
290
+ }
291
+ this.writeMarker(constants.ARRAY_END);
292
+ }
293
+
294
+ /** writeArray */
295
+ private writeTypedArray(value: ArrayBufferView): void {
296
+ this.writeMarker(constants.ARRAY);
297
+ this.writeMarker(constants.TYPE_MARKER);
298
+ if (value instanceof Uint8Array || value instanceof Int8Array) {
299
+ // fast path for typed arrays with `BYTES_PER_ELEMENT` of 1
300
+ this.writeMarker(value instanceof Uint8Array ? constants.UINT8 : constants.INT8);
301
+ this.writeMarker(constants.COUNT_MARKER);
302
+ this.writeInt(value.length);
303
+ this.ensureCapacity(value.byteLength);
304
+ this.buffer.set(value, this.length);
305
+ this.length += value.byteLength;
306
+ return;
307
+ }
308
+ let setValue;
309
+ if (value instanceof Int16Array) {
310
+ this.writeMarker(constants.INT16);
311
+ setValue = this.view.setInt16;
312
+ } else if (value instanceof Int32Array) {
313
+ this.writeMarker(constants.INT32);
314
+ setValue = this.view.setInt32;
315
+ } else if (value instanceof Float32Array) {
316
+ this.writeMarker(constants.FLOAT32);
317
+ setValue = this.view.setFloat32;
318
+ } else if (value instanceof Float64Array) {
319
+ this.writeMarker(constants.FLOAT64);
320
+ setValue = this.view.setFloat64;
321
+ } else {
322
+ throw new Error(`Unsupported typed array type ${Object.prototype.toString.call(value)}`);
323
+ }
324
+ this.writeMarker(constants.COUNT_MARKER);
325
+ this.writeInt(value.length);
326
+ this.ensureCapacity(value.byteLength);
327
+ // 不要在前面 bind,this.ensureCapacity 有可能导致 this.view 指向新的对象
328
+ for (const v of value) {
329
+ setValue.call(this.view, this.length, v);
330
+ this.length += value.BYTES_PER_ELEMENT;
331
+ }
332
+ }
333
+ }
334
+
335
+ /** 编码 */
336
+ export function encode(value: unknown): Uint8Array {
337
+ const encoder = new Encoder();
338
+ encoder.write(value);
339
+ return encoder.finish();
340
+ }
package/src/index.ts ADDED
@@ -0,0 +1,2 @@
1
+ export { encode } from './encoder.js';
2
+ export { decode } from './decoder.js';