libshv-js 3.3.6 → 3.4.1
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/.github/workflows/check-version-bump.yml +22 -0
- package/.github/workflows/lint.yml +2 -2
- package/.xo-config.json +22 -14
- package/package.json +3 -3
- package/src/chainpack.ts +124 -76
- package/src/cpcontext.ts +9 -4
- package/src/cpon.ts +145 -72
- package/src/rpcmessage.ts +57 -176
- package/src/rpcvalue.ts +11 -8
- package/src/ws-client.ts +114 -51
- package/src/zod.ts +30 -3
- package/test.ts +2 -0
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# vim: sw=2
|
|
2
|
+
name: Misc
|
|
3
|
+
|
|
4
|
+
concurrency:
|
|
5
|
+
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
|
6
|
+
cancel-in-progress: true
|
|
7
|
+
|
|
8
|
+
on:
|
|
9
|
+
push:
|
|
10
|
+
branches: [ "main" ]
|
|
11
|
+
pull_request:
|
|
12
|
+
branches: [ "main" ]
|
|
13
|
+
|
|
14
|
+
jobs:
|
|
15
|
+
check-version-bump:
|
|
16
|
+
name: Check version bump
|
|
17
|
+
runs-on: ubuntu-22.04
|
|
18
|
+
steps:
|
|
19
|
+
- uses: actions/checkout@v3
|
|
20
|
+
- name: Check if version bumped
|
|
21
|
+
uses: del-systems/check-if-version-bumped@v2.0.3
|
|
22
|
+
|
package/.xo-config.json
CHANGED
|
@@ -1,22 +1,27 @@
|
|
|
1
1
|
{
|
|
2
2
|
"space": 4,
|
|
3
3
|
"rules": {
|
|
4
|
-
"@typescript-eslint/
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
4
|
+
"@typescript-eslint/naming-convention": ["error",
|
|
5
|
+
{
|
|
6
|
+
"selector": "variable",
|
|
7
|
+
"format": ["camelCase"]
|
|
8
|
+
},
|
|
9
|
+
{
|
|
10
|
+
"format": ["camelCase", "UPPER_CASE"],
|
|
11
|
+
"selector": "variable",
|
|
12
|
+
"modifiers": ["const"]
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
"format": ["PascalCase"],
|
|
16
|
+
"selector": "variable",
|
|
17
|
+
"modifiers": ["const"],
|
|
18
|
+
"filter": "Ctor$|Validation$|Zod$"
|
|
19
|
+
}
|
|
20
|
+
],
|
|
10
21
|
"@typescript-eslint/prefer-promise-reject-errors": "off",
|
|
11
22
|
"@typescript-eslint/promise-function-async": "off",
|
|
23
|
+
"@typescript-eslint/triple-slash-reference": "off",
|
|
12
24
|
"capitalized-comments": "off",
|
|
13
|
-
"max-depth": "off",
|
|
14
|
-
"@typescript-eslint/padding-line-between-statements": "off",
|
|
15
|
-
"no-constant-condition": ["error", {
|
|
16
|
-
"checkLoops": false
|
|
17
|
-
}],
|
|
18
|
-
"complexity": "off",
|
|
19
|
-
"no-bitwise": "off",
|
|
20
25
|
"object-curly-newline": ["error", {
|
|
21
26
|
"ImportDeclaration": "never"
|
|
22
27
|
}],
|
|
@@ -24,10 +29,13 @@
|
|
|
24
29
|
"promise-function-async": "off",
|
|
25
30
|
"default-case": "off",
|
|
26
31
|
"import/extensions": "off",
|
|
32
|
+
"import/no-unassigned-import": "off",
|
|
33
|
+
"no-warning-comments": "off",
|
|
27
34
|
"prefer-promise-reject-errors": "off",
|
|
28
|
-
"eslint-disable-next-line prefer-promise-reject-errors": "off",
|
|
29
35
|
"unicorn/explicit-length-check": "off",
|
|
36
|
+
"unicorn/filename-case": "off",
|
|
30
37
|
"unicorn/no-negated-condition": "off",
|
|
38
|
+
"unicorn/prefer-top-level-await": "off",
|
|
31
39
|
"unicorn/switch-case-braces": "off",
|
|
32
40
|
"unicorn/prevent-abbreviations": "off"
|
|
33
41
|
}
|
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "libshv-js",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.4.1",
|
|
4
4
|
"description": "Typescript implementation of libshv",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"test": "echo \"Error: no test specified\" && exit 1",
|
|
7
|
-
"lint": "xo --reporter unix src/* --extension=vue",
|
|
8
|
-
"fix": "
|
|
7
|
+
"lint": "xo --reporter unix test.ts src/* --extension=vue",
|
|
8
|
+
"fix": "npm run lint -- --fix"
|
|
9
9
|
},
|
|
10
10
|
"author": "Elektroline",
|
|
11
11
|
"repository": {
|
package/src/chainpack.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/* eslint-disable no-bitwise */
|
|
1
2
|
import {utf8ToString} from './cpon';
|
|
2
3
|
import {type RpcValue, type RpcValueType, type DateTime, Decimal, Double, type IMap, type Int, type MetaMap, RpcValueWithMetaData, type ShvMap, UInt, withOffset, shvMapType} from './rpcvalue';
|
|
3
4
|
import {UnpackContext, PackContext} from './cpcontext';
|
|
@@ -26,21 +27,21 @@ enum PackingSchema {
|
|
|
26
27
|
const SHV_EPOCH_MSEC = 1_517_529_600_000;
|
|
27
28
|
const INVALID_MIN_OFFSET_FROM_UTC = (-64 * 15);
|
|
28
29
|
|
|
29
|
-
const
|
|
30
|
+
const divInt = (n: bigint, d: bigint) => {
|
|
30
31
|
const r = n % d;
|
|
31
32
|
return [(n - r) / d, r] as const;
|
|
32
33
|
};
|
|
33
34
|
|
|
34
|
-
const
|
|
35
|
-
let
|
|
35
|
+
const uint8ArrayBoBigint = (bytes: Uint8Array, type: 'Int' | 'UInt') => {
|
|
36
|
+
let isNeg = false;
|
|
36
37
|
|
|
37
38
|
if (type === 'Int') {
|
|
38
39
|
if (bytes.length < 5) {
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
bytes[0] &= ~
|
|
40
|
+
const signMask = 0x80 >> bytes.length;
|
|
41
|
+
isNeg = Boolean(bytes[0] & signMask);
|
|
42
|
+
bytes[0] &= ~signMask;
|
|
42
43
|
} else {
|
|
43
|
-
|
|
44
|
+
isNeg = Boolean(bytes[1] & 128);
|
|
44
45
|
bytes[1] &= ~128;
|
|
45
46
|
}
|
|
46
47
|
}
|
|
@@ -50,36 +51,34 @@ const uint8_array_to_bigint = (bytes: Uint8Array, type: 'Int' | 'UInt') => {
|
|
|
50
51
|
ret = (ret * BigInt(256)) + BigInt(byte);
|
|
51
52
|
}
|
|
52
53
|
|
|
53
|
-
if (
|
|
54
|
+
if (isNeg) {
|
|
54
55
|
ret = -ret;
|
|
55
56
|
}
|
|
56
57
|
|
|
57
58
|
return ret;
|
|
58
59
|
};
|
|
59
60
|
|
|
60
|
-
const
|
|
61
|
+
const numberToUint8Array = (num: bigint) => {
|
|
61
62
|
let bytes = new Uint8Array(8);
|
|
62
63
|
let len = 0;
|
|
63
|
-
|
|
64
|
-
const res =
|
|
64
|
+
do {
|
|
65
|
+
const res = divInt(num, 256n);
|
|
65
66
|
num = res[0];
|
|
66
67
|
bytes[len++] = Number(res[1]);
|
|
67
|
-
|
|
68
|
-
break;
|
|
69
|
-
}
|
|
70
|
-
}
|
|
68
|
+
} while (num !== 0n);
|
|
71
69
|
|
|
72
70
|
bytes = bytes.subarray(0, len);
|
|
73
71
|
bytes.reverse();
|
|
74
72
|
return bytes;
|
|
75
73
|
};
|
|
76
74
|
|
|
77
|
-
const
|
|
75
|
+
const significantBitsCount = (num: bigint) => {
|
|
78
76
|
let ret = 0;
|
|
79
77
|
while (num > 0) {
|
|
80
78
|
ret++;
|
|
81
79
|
num >>= 1n;
|
|
82
80
|
}
|
|
81
|
+
|
|
83
82
|
return ret;
|
|
84
83
|
};
|
|
85
84
|
|
|
@@ -90,6 +89,7 @@ class ChainPackReader {
|
|
|
90
89
|
this.ctx = data instanceof UnpackContext ? data : new UnpackContext(data);
|
|
91
90
|
}
|
|
92
91
|
|
|
92
|
+
/* eslint-disable complexity */
|
|
93
93
|
read(): RpcValue {
|
|
94
94
|
let meta: MetaMap | undefined;
|
|
95
95
|
let codePointAt = this.ctx.getByte() as PackingSchema;
|
|
@@ -99,103 +99,124 @@ class ChainPackReader {
|
|
|
99
99
|
codePointAt = this.ctx.getByte();
|
|
100
100
|
}
|
|
101
101
|
|
|
102
|
-
const
|
|
103
|
-
const ret = meta !== undefined ? new RpcValueWithMetaData(
|
|
102
|
+
const implReturn = (x: RpcValueType) => {
|
|
103
|
+
const ret = meta !== undefined ? new RpcValueWithMetaData(meta, x) : x;
|
|
104
104
|
return ret;
|
|
105
105
|
};
|
|
106
106
|
|
|
107
107
|
if (codePointAt < PackingSchema.Null) {
|
|
108
108
|
if (codePointAt >= PackingSchema.IntThreshold) {
|
|
109
|
-
return
|
|
109
|
+
return implReturn(codePointAt - 64);
|
|
110
110
|
}
|
|
111
|
-
|
|
111
|
+
|
|
112
|
+
return implReturn(new UInt(codePointAt));
|
|
112
113
|
}
|
|
114
|
+
|
|
113
115
|
switch (codePointAt) {
|
|
114
116
|
case PackingSchema.Null: {
|
|
115
|
-
return
|
|
117
|
+
return implReturn(undefined);
|
|
116
118
|
}
|
|
119
|
+
|
|
117
120
|
case PackingSchema.True: {
|
|
118
|
-
return
|
|
121
|
+
return implReturn(true);
|
|
119
122
|
}
|
|
123
|
+
|
|
120
124
|
case PackingSchema.False: {
|
|
121
|
-
return
|
|
125
|
+
return implReturn(false);
|
|
122
126
|
}
|
|
127
|
+
|
|
123
128
|
case PackingSchema.Int: {
|
|
124
|
-
return
|
|
129
|
+
return implReturn(this.readIntData());
|
|
125
130
|
}
|
|
131
|
+
|
|
126
132
|
case PackingSchema.UInt: {
|
|
127
|
-
return
|
|
133
|
+
return implReturn(new UInt(this.readUIntData()));
|
|
128
134
|
}
|
|
135
|
+
|
|
129
136
|
case PackingSchema.Double: {
|
|
130
137
|
const data = new Uint8Array(8);
|
|
131
138
|
for (let i = 0; i < 8; i++) {
|
|
132
139
|
data[i] = this.ctx.getByte();
|
|
133
140
|
}
|
|
134
|
-
|
|
141
|
+
|
|
142
|
+
return implReturn(new Double(new DataView(data.buffer).getFloat64(0, true))); // little endian
|
|
135
143
|
}
|
|
144
|
+
|
|
136
145
|
case PackingSchema.Decimal: {
|
|
137
146
|
const mant = this.readIntData();
|
|
138
147
|
const exp = this.readIntData();
|
|
139
|
-
return
|
|
148
|
+
return implReturn(new Decimal(mant, exp));
|
|
140
149
|
}
|
|
150
|
+
|
|
141
151
|
case PackingSchema.DateTime: {
|
|
142
152
|
let bi = this.readUIntDataHelper('UInt');
|
|
143
|
-
const
|
|
144
|
-
const
|
|
153
|
+
const hasTzOffset = bi & 1n;
|
|
154
|
+
const hasNotMsec = bi & 2n;
|
|
145
155
|
bi >>= 2n;
|
|
146
156
|
|
|
147
157
|
let offset = 0;
|
|
148
|
-
if (
|
|
158
|
+
if (hasTzOffset) {
|
|
149
159
|
offset = Number(bi & 0x7Fn);
|
|
150
160
|
if (offset & 0x40) {
|
|
151
161
|
// sign extension
|
|
152
162
|
offset -= 128;
|
|
153
163
|
}
|
|
164
|
+
|
|
154
165
|
bi >>= 7n;
|
|
155
166
|
}
|
|
156
167
|
|
|
157
168
|
offset *= 15;
|
|
158
169
|
|
|
159
170
|
if (offset === INVALID_MIN_OFFSET_FROM_UTC) {
|
|
160
|
-
return
|
|
171
|
+
return implReturn(undefined);
|
|
161
172
|
}
|
|
162
173
|
|
|
163
174
|
let msec = Number(bi);
|
|
164
|
-
if (
|
|
175
|
+
if (hasNotMsec) {
|
|
165
176
|
msec *= 1000;
|
|
166
177
|
}
|
|
178
|
+
|
|
167
179
|
msec += SHV_EPOCH_MSEC;
|
|
168
180
|
msec -= offset * 60_000;
|
|
169
181
|
return withOffset(new Date(msec), offset);
|
|
170
182
|
}
|
|
183
|
+
|
|
171
184
|
case PackingSchema.Map: {
|
|
172
|
-
return
|
|
185
|
+
return implReturn(this.readMap());
|
|
173
186
|
}
|
|
187
|
+
|
|
174
188
|
case PackingSchema.IMap: {
|
|
175
|
-
return
|
|
189
|
+
return implReturn(this.readIMap());
|
|
176
190
|
}
|
|
191
|
+
|
|
177
192
|
case PackingSchema.List: {
|
|
178
|
-
return
|
|
193
|
+
return implReturn(this.readList());
|
|
179
194
|
}
|
|
195
|
+
|
|
180
196
|
case PackingSchema.Blob: {
|
|
181
|
-
const
|
|
182
|
-
const arr = new Uint8Array(
|
|
183
|
-
for (let i = 0; i <
|
|
197
|
+
const strLen = this.readUIntData();
|
|
198
|
+
const arr = new Uint8Array(strLen);
|
|
199
|
+
for (let i = 0; i < strLen; i++) {
|
|
184
200
|
arr[i] = this.ctx.getByte();
|
|
185
201
|
}
|
|
186
|
-
|
|
202
|
+
|
|
203
|
+
return implReturn(arr.buffer);
|
|
187
204
|
}
|
|
205
|
+
|
|
188
206
|
case PackingSchema.String: {
|
|
189
|
-
const
|
|
190
|
-
const arr = new Uint8Array(
|
|
191
|
-
for (let i = 0; i <
|
|
207
|
+
const strLen = this.readUIntData();
|
|
208
|
+
const arr = new Uint8Array(strLen);
|
|
209
|
+
for (let i = 0; i < strLen; i++) {
|
|
192
210
|
arr[i] = this.ctx.getByte();
|
|
193
211
|
}
|
|
194
|
-
|
|
212
|
+
|
|
213
|
+
return implReturn(utf8ToString(arr.buffer));
|
|
195
214
|
}
|
|
215
|
+
|
|
196
216
|
case PackingSchema.CString: {
|
|
197
217
|
// variation of CponReader.readCString()
|
|
198
218
|
const pctx = new PackContext();
|
|
219
|
+
// eslint-disable-next-line no-constant-condition
|
|
199
220
|
while (true) {
|
|
200
221
|
let b = this.ctx.getByte();
|
|
201
222
|
if (b === '\\'.codePointAt(0)) {
|
|
@@ -218,50 +239,58 @@ class ChainPackReader {
|
|
|
218
239
|
pctx.putByte(b);
|
|
219
240
|
}
|
|
220
241
|
}
|
|
221
|
-
|
|
242
|
+
|
|
243
|
+
return implReturn(utf8ToString(pctx.buffer()));
|
|
222
244
|
}
|
|
245
|
+
|
|
223
246
|
default:
|
|
224
247
|
throw new TypeError('ChainPack - Invalid type info: ' + codePointAt);
|
|
225
248
|
}
|
|
226
249
|
}
|
|
250
|
+
/* eslint-enable complexity */
|
|
227
251
|
|
|
228
252
|
readUIntDataHelper(type: 'Int' | 'UInt') {
|
|
229
253
|
let num = 0;
|
|
230
254
|
const head = this.ctx.getByte();
|
|
231
|
-
let
|
|
255
|
+
let bytesToReadCnt;
|
|
232
256
|
switch (0) {
|
|
233
257
|
case head & 128: {
|
|
234
|
-
|
|
258
|
+
bytesToReadCnt = 0;
|
|
235
259
|
num = head & 127;
|
|
236
260
|
break;
|
|
237
261
|
}
|
|
262
|
+
|
|
238
263
|
case head & 64: {
|
|
239
|
-
|
|
264
|
+
bytesToReadCnt = 1;
|
|
240
265
|
num = head & 63;
|
|
241
266
|
break;
|
|
242
267
|
}
|
|
268
|
+
|
|
243
269
|
case head & 32: {
|
|
244
|
-
|
|
270
|
+
bytesToReadCnt = 2;
|
|
245
271
|
num = head & 31;
|
|
246
272
|
break;
|
|
247
273
|
}
|
|
274
|
+
|
|
248
275
|
case head & 16: {
|
|
249
|
-
|
|
276
|
+
bytesToReadCnt = 3;
|
|
250
277
|
num = head & 15;
|
|
251
278
|
break;
|
|
252
279
|
}
|
|
280
|
+
|
|
253
281
|
default: {
|
|
254
|
-
|
|
282
|
+
bytesToReadCnt = (head & 0xF) + 4;
|
|
255
283
|
}
|
|
256
284
|
}
|
|
257
|
-
|
|
285
|
+
|
|
286
|
+
const bytes = new Uint8Array(bytesToReadCnt + 1);
|
|
258
287
|
bytes[0] = num;
|
|
259
|
-
for (let i = 0; i <
|
|
288
|
+
for (let i = 0; i < bytesToReadCnt; i++) {
|
|
260
289
|
const r = this.ctx.getByte();
|
|
261
290
|
bytes[i + 1] = r;
|
|
262
291
|
}
|
|
263
292
|
|
|
264
|
-
return
|
|
293
|
+
return uint8ArrayBoBigint(bytes, type);
|
|
265
294
|
}
|
|
266
295
|
|
|
267
296
|
readIntData() {
|
|
@@ -269,9 +298,11 @@ class ChainPackReader {
|
|
|
269
298
|
if (val <= Number.MIN_SAFE_INTEGER) {
|
|
270
299
|
return Number.MIN_SAFE_INTEGER;
|
|
271
300
|
}
|
|
301
|
+
|
|
272
302
|
if (val >= Number.MAX_SAFE_INTEGER) {
|
|
273
303
|
return Number.MAX_SAFE_INTEGER;
|
|
274
304
|
}
|
|
305
|
+
|
|
275
306
|
return Number(val);
|
|
276
307
|
}
|
|
277
308
|
|
|
@@ -280,19 +311,23 @@ class ChainPackReader {
|
|
|
280
311
|
if (val >= Number.MAX_SAFE_INTEGER) {
|
|
281
312
|
return Number.MAX_SAFE_INTEGER;
|
|
282
313
|
}
|
|
314
|
+
|
|
283
315
|
return Number(val);
|
|
284
316
|
}
|
|
285
317
|
|
|
286
318
|
readList() {
|
|
287
319
|
const lst = [];
|
|
320
|
+
// eslint-disable-next-line no-constant-condition
|
|
288
321
|
while (true) {
|
|
289
322
|
const b = this.ctx.peekByte();
|
|
290
323
|
if (b as PackingSchema === PackingSchema.Term) {
|
|
291
324
|
this.ctx.getByte();
|
|
292
325
|
break;
|
|
293
326
|
}
|
|
327
|
+
|
|
294
328
|
lst.push(this.read());
|
|
295
329
|
}
|
|
330
|
+
|
|
296
331
|
return lst;
|
|
297
332
|
}
|
|
298
333
|
|
|
@@ -315,12 +350,14 @@ class ChainPackReader {
|
|
|
315
350
|
const map: ShvMap | IMap | MetaMap = {
|
|
316
351
|
[shvMapType]: map_type,
|
|
317
352
|
};
|
|
353
|
+
// eslint-disable-next-line no-constant-condition
|
|
318
354
|
while (true) {
|
|
319
355
|
const b = this.ctx.peekByte();
|
|
320
356
|
if (b as PackingSchema === PackingSchema.Term) {
|
|
321
357
|
this.ctx.getByte();
|
|
322
358
|
break;
|
|
323
359
|
}
|
|
360
|
+
|
|
324
361
|
const key = this.read();
|
|
325
362
|
const val = this.read();
|
|
326
363
|
if (map[shvMapType] === 'metamap' && typeof key === 'string') {
|
|
@@ -335,6 +372,7 @@ class ChainPackReader {
|
|
|
335
372
|
throw new TypeError('Malformed map, invalid key');
|
|
336
373
|
}
|
|
337
374
|
}
|
|
375
|
+
|
|
338
376
|
return map;
|
|
339
377
|
}
|
|
340
378
|
}
|
|
@@ -351,6 +389,7 @@ class ChainPackWriter {
|
|
|
351
389
|
this.writeMeta(rpc_val.meta);
|
|
352
390
|
rpc_val = rpc_val.value;
|
|
353
391
|
}
|
|
392
|
+
|
|
354
393
|
switch (true) {
|
|
355
394
|
case rpc_val === undefined:
|
|
356
395
|
this.ctx.putByte(PackingSchema.Null);
|
|
@@ -390,6 +429,7 @@ class ChainPackWriter {
|
|
|
390
429
|
this.writeMap(rpc_val);
|
|
391
430
|
break;
|
|
392
431
|
}
|
|
432
|
+
|
|
393
433
|
break;
|
|
394
434
|
default:
|
|
395
435
|
console.log('Can\'t serialize', rpc_val);
|
|
@@ -398,49 +438,55 @@ class ChainPackWriter {
|
|
|
398
438
|
}
|
|
399
439
|
|
|
400
440
|
writeUIntDataHelper(num: bigint, type: 'Int' | 'UInt') {
|
|
401
|
-
const
|
|
402
|
-
if (
|
|
441
|
+
const isNegative = num < 0;
|
|
442
|
+
if (isNegative) {
|
|
403
443
|
num = -num;
|
|
404
444
|
}
|
|
405
|
-
const significant_bits = significant_bits_count(num) + (/* one more needed for sign bit */ type === 'Int' ? 1 : 0);
|
|
406
|
-
const bytes_needed = significant_bits <= 28 ? Math.trunc((significant_bits - 1) / 7) + 1 : Math.trunc((significant_bits - 1) / 8) + 2;
|
|
407
445
|
|
|
408
|
-
|
|
446
|
+
const significantBits = significantBitsCount(num) + (/* one more needed for sign bit */ type === 'Int' ? 1 : 0);
|
|
447
|
+
const bytesNeeded = significantBits <= 28 ? Math.trunc((significantBits - 1) / 7) + 1 : Math.trunc((significantBits - 1) / 8) + 2;
|
|
448
|
+
|
|
449
|
+
switch (bytesNeeded) {
|
|
409
450
|
case 0:
|
|
410
451
|
throw new Error(`Failed to count bytes needed for ${num}`);
|
|
411
452
|
case 1:
|
|
412
|
-
if (
|
|
453
|
+
if (isNegative) {
|
|
413
454
|
num |= 0b0100_0000n;
|
|
414
455
|
}
|
|
456
|
+
|
|
415
457
|
break;
|
|
416
458
|
case 2:
|
|
417
459
|
num |= 0b1000_0000n << 8n;
|
|
418
|
-
if (
|
|
460
|
+
if (isNegative) {
|
|
419
461
|
num |= 0b0010_0000n << 8n;
|
|
420
462
|
}
|
|
463
|
+
|
|
421
464
|
break;
|
|
422
465
|
case 3:
|
|
423
466
|
num |= 0b1100_0000n << 16n;
|
|
424
|
-
if (
|
|
467
|
+
if (isNegative) {
|
|
425
468
|
num |= 0b0001_0000n << 16n;
|
|
426
469
|
}
|
|
470
|
+
|
|
427
471
|
break;
|
|
428
472
|
case 4:
|
|
429
473
|
num |= 0b1110_0000n << 24n;
|
|
430
|
-
if (
|
|
474
|
+
if (isNegative) {
|
|
431
475
|
num |= 0b0000_1000n << 24n;
|
|
432
476
|
}
|
|
477
|
+
|
|
433
478
|
break;
|
|
434
479
|
default:
|
|
435
|
-
num |= 0b1111_0000n << BigInt((
|
|
436
|
-
num |= BigInt(
|
|
437
|
-
if (
|
|
438
|
-
num |= 0b1000_0000n << BigInt((
|
|
480
|
+
num |= 0b1111_0000n << BigInt((bytesNeeded - 1) * 8);
|
|
481
|
+
num |= BigInt(bytesNeeded - 4 /* n is offset by 4 */ - 1 /* for the control byte */) << BigInt((bytesNeeded - 1) * 8);
|
|
482
|
+
if (isNegative) {
|
|
483
|
+
num |= 0b1000_0000n << BigInt((bytesNeeded - 2) * 8);
|
|
439
484
|
}
|
|
485
|
+
|
|
440
486
|
break;
|
|
441
487
|
}
|
|
442
488
|
|
|
443
|
-
const bytes =
|
|
489
|
+
const bytes = numberToUint8Array(num);
|
|
444
490
|
for (const byte of bytes) {
|
|
445
491
|
this.ctx.putByte(byte);
|
|
446
492
|
}
|
|
@@ -537,6 +583,7 @@ class ChainPackWriter {
|
|
|
537
583
|
for (const element of lst) {
|
|
538
584
|
this.write(element);
|
|
539
585
|
}
|
|
586
|
+
|
|
540
587
|
this.ctx.putByte(PackingSchema.Term);
|
|
541
588
|
}
|
|
542
589
|
|
|
@@ -556,28 +603,29 @@ class ChainPackWriter {
|
|
|
556
603
|
}
|
|
557
604
|
|
|
558
605
|
writeMapContent(map: MetaMap | ShvMap | IMap) {
|
|
559
|
-
for (const [key, value] of Object.entries(map)) {
|
|
606
|
+
for (const [key, value] of Object.entries<RpcValue>(map)) {
|
|
560
607
|
if (value === undefined) {
|
|
561
608
|
continue;
|
|
562
609
|
}
|
|
563
610
|
|
|
564
611
|
if (map[shvMapType] === 'imap') {
|
|
565
|
-
const
|
|
566
|
-
if (Number.isNaN(
|
|
612
|
+
const intKey = Number(key);
|
|
613
|
+
if (Number.isNaN(intKey)) {
|
|
567
614
|
throw new TypeError('Invalid NaN IMap key');
|
|
568
615
|
}
|
|
569
616
|
|
|
570
|
-
this.writeInt(
|
|
617
|
+
this.writeInt(intKey);
|
|
571
618
|
} else if (map[shvMapType] === 'metamap') {
|
|
572
|
-
const
|
|
573
|
-
if (Number.isNaN(
|
|
619
|
+
const intKey = Number(key);
|
|
620
|
+
if (Number.isNaN(intKey)) {
|
|
574
621
|
this.writeJSString(key.toString());
|
|
575
622
|
} else {
|
|
576
|
-
this.writeInt(
|
|
623
|
+
this.writeInt(intKey);
|
|
577
624
|
}
|
|
578
625
|
} else {
|
|
579
626
|
this.writeJSString(key.toString());
|
|
580
627
|
}
|
|
628
|
+
|
|
581
629
|
this.write(value);
|
|
582
630
|
}
|
|
583
631
|
|
|
@@ -596,6 +644,6 @@ const fromChainPack = (buffer: ArrayBuffer) => {
|
|
|
596
644
|
return reader.read();
|
|
597
645
|
};
|
|
598
646
|
|
|
599
|
-
const
|
|
647
|
+
const CHAINPACK_PROTOCOL_TYPE = 1;
|
|
600
648
|
|
|
601
|
-
export {toChainPack, fromChainPack, ChainPackReader, ChainPackWriter,
|
|
649
|
+
export {toChainPack, fromChainPack, ChainPackReader, ChainPackWriter, CHAINPACK_PROTOCOL_TYPE};
|
package/src/cpcontext.ts
CHANGED
|
@@ -11,6 +11,7 @@ class UnpackContext {
|
|
|
11
11
|
if (this.index >= this.data.length) {
|
|
12
12
|
throw new RangeError('unexpected end of data');
|
|
13
13
|
}
|
|
14
|
+
|
|
14
15
|
return this.data[this.index++];
|
|
15
16
|
}
|
|
16
17
|
|
|
@@ -18,6 +19,7 @@ class UnpackContext {
|
|
|
18
19
|
if (this.index >= this.data.length) {
|
|
19
20
|
return -1;
|
|
20
21
|
}
|
|
22
|
+
|
|
21
23
|
return this.data[this.index];
|
|
22
24
|
}
|
|
23
25
|
|
|
@@ -35,10 +37,10 @@ const transfer = (source: ArrayBuffer, length: number) => {
|
|
|
35
37
|
return source.slice(0, length);
|
|
36
38
|
}
|
|
37
39
|
|
|
38
|
-
const
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
return
|
|
40
|
+
const sourceView = new Uint8Array(source);
|
|
41
|
+
const destView = new Uint8Array(new ArrayBuffer(length));
|
|
42
|
+
destView.set(sourceView);
|
|
43
|
+
return destView.buffer;
|
|
42
44
|
};
|
|
43
45
|
|
|
44
46
|
class PackContext {
|
|
@@ -52,6 +54,7 @@ class PackContext {
|
|
|
52
54
|
const buffer = transfer(this.data.buffer, this.data.length + PackContext.CHUNK_LEN);
|
|
53
55
|
this.data = new Uint8Array(buffer);
|
|
54
56
|
}
|
|
57
|
+
|
|
55
58
|
this.data[this.length++] = b;
|
|
56
59
|
}
|
|
57
60
|
|
|
@@ -63,6 +66,7 @@ class PackContext {
|
|
|
63
66
|
}
|
|
64
67
|
|
|
65
68
|
writeCharCodeUtf8(charcode: number) {
|
|
69
|
+
/* eslint-disable no-bitwise */
|
|
66
70
|
if (charcode < 0x80) {
|
|
67
71
|
this.putByte(charcode);
|
|
68
72
|
} else if (charcode < 0x8_00) {
|
|
@@ -73,6 +77,7 @@ class PackContext {
|
|
|
73
77
|
this.putByte(0x80 | ((charcode >> 6) & 0x3F));
|
|
74
78
|
this.putByte(0x80 | (charcode & 0x3F));
|
|
75
79
|
}
|
|
80
|
+
/* eslint-enable no-bitwise */
|
|
76
81
|
}
|
|
77
82
|
|
|
78
83
|
buffer() {
|