libshv-js 3.3.5 → 3.4.0
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 +131 -52
- package/src/zod.ts +27 -3
- package/test.ts +2 -0
package/src/cpon.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/* eslint-disable no-bitwise */
|
|
1
2
|
import {type RpcValue, type RpcValueType, type DateTime, type List, Decimal, Double, type IMap, type Int, type MetaMap, RpcValueWithMetaData, type ShvMap, UInt, withOffset, shvMapType, isShvMap, isIMap} from './rpcvalue';
|
|
2
3
|
import {PackContext, UnpackContext} from './cpcontext';
|
|
3
4
|
|
|
@@ -9,6 +10,7 @@ const hexify = (byte: number) => {
|
|
|
9
10
|
if (byte < 16) {
|
|
10
11
|
return 97 + byte - 10;
|
|
11
12
|
}
|
|
13
|
+
|
|
12
14
|
return '?'.codePointAt(0)!;
|
|
13
15
|
};
|
|
14
16
|
|
|
@@ -16,37 +18,41 @@ const unhex = (byte: number) => {
|
|
|
16
18
|
if (byte >= 48 && byte <= 57) { // 0-9
|
|
17
19
|
return byte - 48;
|
|
18
20
|
}
|
|
21
|
+
|
|
19
22
|
if (byte >= 65 && byte <= 70) { // A-F
|
|
20
23
|
return byte - 65 + 10;
|
|
21
24
|
}
|
|
25
|
+
|
|
22
26
|
if (byte >= 97 && byte <= 102) { // a-f
|
|
23
27
|
return byte - 97 + 10;
|
|
24
28
|
}
|
|
29
|
+
|
|
25
30
|
throw new TypeError('Invalid HEX digit: ' + byte);
|
|
26
31
|
};
|
|
27
32
|
|
|
28
33
|
const utf8ToString = (bytearray: ArrayBuffer) => {
|
|
29
|
-
const
|
|
34
|
+
const uint8Array = new Uint8Array(bytearray);
|
|
30
35
|
let str = '';
|
|
31
|
-
for (let i = 0; i <
|
|
32
|
-
const value =
|
|
36
|
+
for (let i = 0; i < uint8Array.length; i++) {
|
|
37
|
+
const value = uint8Array[i];
|
|
33
38
|
|
|
34
39
|
if (value < 0x80) {
|
|
35
40
|
str += String.fromCodePoint(value);
|
|
36
41
|
} else if (value > 0xBF && value < 0xE0) {
|
|
37
|
-
str += String.fromCodePoint(((value & 0x1F) << 6) | (
|
|
42
|
+
str += String.fromCodePoint(((value & 0x1F) << 6) | (uint8Array[i + 1] & 0x3F));
|
|
38
43
|
i += 1;
|
|
39
44
|
} else if (value > 0xDF && value < 0xF0) {
|
|
40
|
-
str += String.fromCodePoint(((value & 0x0F) << 12) | ((
|
|
45
|
+
str += String.fromCodePoint(((value & 0x0F) << 12) | ((uint8Array[i + 1] & 0x3F) << 6) | (uint8Array[i + 2] & 0x3F));
|
|
41
46
|
i += 2;
|
|
42
47
|
} else {
|
|
43
48
|
// surrogate pair
|
|
44
|
-
const
|
|
49
|
+
const charCode = (((value & 0x07) << 18) | ((uint8Array[i + 1] & 0x3F) << 12) | ((uint8Array[i + 2] & 0x3F) << 6) | (uint8Array[i + 3] & 0x3F)) - 0x01_00_00;
|
|
45
50
|
|
|
46
|
-
str += String.fromCodePoint((
|
|
51
|
+
str += String.fromCodePoint((charCode >> 10) | 0xD8_00, (charCode & 0x03_FF) | 0xDC_00);
|
|
47
52
|
i += 3;
|
|
48
53
|
}
|
|
49
54
|
}
|
|
55
|
+
|
|
50
56
|
return str;
|
|
51
57
|
};
|
|
52
58
|
|
|
@@ -64,8 +70,8 @@ class CponReader {
|
|
|
64
70
|
meta = this.readMetaMap();
|
|
65
71
|
}
|
|
66
72
|
|
|
67
|
-
const
|
|
68
|
-
const ret = meta !== undefined ? new RpcValueWithMetaData(
|
|
73
|
+
const implReturn = (x: RpcValueType) => {
|
|
74
|
+
const ret = meta !== undefined ? new RpcValueWithMetaData(meta, x) : x;
|
|
69
75
|
return ret;
|
|
70
76
|
};
|
|
71
77
|
|
|
@@ -74,19 +80,20 @@ class CponReader {
|
|
|
74
80
|
// console.log("CHAR:", b, String.fromCodePoint(b));
|
|
75
81
|
// [0-9+-]
|
|
76
82
|
if ((b >= 48 && b <= 57) || b === 43 || b === 45) {
|
|
77
|
-
return
|
|
83
|
+
return implReturn(this.readNumber());
|
|
78
84
|
}
|
|
79
85
|
|
|
80
86
|
if (b === '"'.codePointAt(0)) {
|
|
81
|
-
return
|
|
87
|
+
return implReturn(this.readCString());
|
|
82
88
|
}
|
|
83
89
|
|
|
84
90
|
if (b === 'b'.codePointAt(0)) {
|
|
85
91
|
this.ctx.getByte();
|
|
86
92
|
b = this.ctx.peekByte();
|
|
87
93
|
if (b === '"'.codePointAt(0)) {
|
|
88
|
-
return
|
|
94
|
+
return implReturn(this.readBlobEsc());
|
|
89
95
|
}
|
|
96
|
+
|
|
90
97
|
throw new TypeError('Invalid Blob prefix.');
|
|
91
98
|
}
|
|
92
99
|
|
|
@@ -94,25 +101,27 @@ class CponReader {
|
|
|
94
101
|
this.ctx.getByte();
|
|
95
102
|
b = this.ctx.peekByte();
|
|
96
103
|
if (b === '"'.codePointAt(0)) {
|
|
97
|
-
return
|
|
104
|
+
return implReturn(this.readBlobHex());
|
|
98
105
|
}
|
|
106
|
+
|
|
99
107
|
throw new TypeError('Invalid HEX Blob prefix.');
|
|
100
108
|
}
|
|
101
109
|
|
|
102
110
|
if (b === '['.codePointAt(0)) {
|
|
103
|
-
return
|
|
111
|
+
return implReturn(this.readList());
|
|
104
112
|
}
|
|
105
113
|
|
|
106
114
|
if (b === '{'.codePointAt(0)) {
|
|
107
|
-
return
|
|
115
|
+
return implReturn(this.readMap());
|
|
108
116
|
}
|
|
109
117
|
|
|
110
118
|
if (b === 'i'.codePointAt(0)) {
|
|
111
119
|
this.ctx.getByte();
|
|
112
120
|
b = this.ctx.peekByte();
|
|
113
121
|
if (b === '{'.codePointAt(0)) {
|
|
114
|
-
return
|
|
122
|
+
return implReturn(this.readIMap());
|
|
115
123
|
}
|
|
124
|
+
|
|
116
125
|
throw new TypeError('Invalid IMap prefix.');
|
|
117
126
|
}
|
|
118
127
|
|
|
@@ -120,24 +129,25 @@ class CponReader {
|
|
|
120
129
|
this.ctx.getByte();
|
|
121
130
|
b = this.ctx.peekByte();
|
|
122
131
|
if (b === '"'.codePointAt(0)) {
|
|
123
|
-
return
|
|
132
|
+
return implReturn(this.readDateTime());
|
|
124
133
|
}
|
|
134
|
+
|
|
125
135
|
throw new TypeError('Invalid DateTime prefix.');
|
|
126
136
|
}
|
|
127
137
|
|
|
128
138
|
if (b === 't'.codePointAt(0)) {
|
|
129
139
|
this.ctx.getBytes('true');
|
|
130
|
-
return
|
|
140
|
+
return implReturn(true);
|
|
131
141
|
}
|
|
132
142
|
|
|
133
143
|
if (b === 'f'.codePointAt(0)) {
|
|
134
144
|
this.ctx.getBytes('false');
|
|
135
|
-
return
|
|
145
|
+
return implReturn(false);
|
|
136
146
|
}
|
|
137
147
|
|
|
138
148
|
if (b === 'n'.codePointAt(0)) {
|
|
139
149
|
this.ctx.getBytes('null');
|
|
140
|
-
return
|
|
150
|
+
return implReturn(undefined);
|
|
141
151
|
}
|
|
142
152
|
|
|
143
153
|
throw new TypeError('Malformed Cpon input.');
|
|
@@ -150,6 +160,8 @@ class CponReader {
|
|
|
150
160
|
const LF = '\n'.codePointAt(0)!;
|
|
151
161
|
const KEY_DELIM = ':'.codePointAt(0)!;
|
|
152
162
|
const FIELD_DELIM = ','.codePointAt(0)!;
|
|
163
|
+
/* eslint-disable max-depth */
|
|
164
|
+
// eslint-disable-next-line no-constant-condition
|
|
153
165
|
while (true) {
|
|
154
166
|
let b = this.ctx.peekByte();
|
|
155
167
|
if (b < 1) {
|
|
@@ -163,6 +175,7 @@ class CponReader {
|
|
|
163
175
|
b = this.ctx.getByte();
|
|
164
176
|
if (b === STAR) {
|
|
165
177
|
// multiline_comment_entered;
|
|
178
|
+
// eslint-disable-next-line no-constant-condition
|
|
166
179
|
while (true) {
|
|
167
180
|
b = this.ctx.getByte();
|
|
168
181
|
if (b === STAR) {
|
|
@@ -174,6 +187,7 @@ class CponReader {
|
|
|
174
187
|
}
|
|
175
188
|
} else if (b === SLASH) {
|
|
176
189
|
// to end of line comment entered;
|
|
190
|
+
// eslint-disable-next-line no-constant-condition
|
|
177
191
|
while (true) {
|
|
178
192
|
b = this.ctx.getByte();
|
|
179
193
|
if (b === LF) {
|
|
@@ -183,16 +197,20 @@ class CponReader {
|
|
|
183
197
|
} else {
|
|
184
198
|
throw new TypeError('Malformed comment');
|
|
185
199
|
}
|
|
200
|
+
|
|
186
201
|
break;
|
|
187
202
|
}
|
|
203
|
+
|
|
188
204
|
case KEY_DELIM: {
|
|
189
205
|
this.ctx.getByte();
|
|
190
206
|
continue;
|
|
191
207
|
}
|
|
208
|
+
|
|
192
209
|
case FIELD_DELIM: {
|
|
193
210
|
this.ctx.getByte();
|
|
194
211
|
continue;
|
|
195
212
|
}
|
|
213
|
+
|
|
196
214
|
default:
|
|
197
215
|
return;
|
|
198
216
|
}
|
|
@@ -200,6 +218,7 @@ class CponReader {
|
|
|
200
218
|
this.ctx.getByte();
|
|
201
219
|
}
|
|
202
220
|
}
|
|
221
|
+
/* eslint-enable max-depth */
|
|
203
222
|
}
|
|
204
223
|
|
|
205
224
|
readDateTime() {
|
|
@@ -210,7 +229,7 @@ class CponReader {
|
|
|
210
229
|
let min = 0;
|
|
211
230
|
let sec = 0;
|
|
212
231
|
let msec = 0;
|
|
213
|
-
let
|
|
232
|
+
let utcOffset = 0;
|
|
214
233
|
|
|
215
234
|
this.ctx.getByte(); // eat '"'
|
|
216
235
|
let b = this.ctx.peekByte();
|
|
@@ -226,30 +245,35 @@ class CponReader {
|
|
|
226
245
|
if (b !== '-'.codePointAt(0)) {
|
|
227
246
|
throw new TypeError('Malformed year-month separator in DateTime');
|
|
228
247
|
}
|
|
248
|
+
|
|
229
249
|
month = Number(this.readInt());
|
|
230
250
|
|
|
231
251
|
b = this.ctx.getByte();
|
|
232
252
|
if (b !== '-'.codePointAt(0)) {
|
|
233
253
|
throw new TypeError('Malformed year-month separator in DateTime');
|
|
234
254
|
}
|
|
255
|
+
|
|
235
256
|
day = Number(this.readInt());
|
|
236
257
|
|
|
237
258
|
b = this.ctx.getByte();
|
|
238
259
|
if (b !== ' '.codePointAt(0) && b !== 'T'.codePointAt(0)) {
|
|
239
260
|
throw new TypeError('Malformed date-time separator in DateTime');
|
|
240
261
|
}
|
|
262
|
+
|
|
241
263
|
hour = Number(this.readInt());
|
|
242
264
|
|
|
243
265
|
b = this.ctx.getByte();
|
|
244
266
|
if (b !== ':'.codePointAt(0)) {
|
|
245
267
|
throw new TypeError('Malformed year-month separator in DateTime');
|
|
246
268
|
}
|
|
269
|
+
|
|
247
270
|
min = Number(this.readInt());
|
|
248
271
|
|
|
249
272
|
b = this.ctx.getByte();
|
|
250
273
|
if (b !== ':'.codePointAt(0)) {
|
|
251
274
|
throw new TypeError('Malformed year-month separator in DateTime');
|
|
252
275
|
}
|
|
276
|
+
|
|
253
277
|
sec = Number(this.readInt());
|
|
254
278
|
|
|
255
279
|
b = this.ctx.peekByte();
|
|
@@ -271,13 +295,15 @@ class CponReader {
|
|
|
271
295
|
if (!(n === 2 || n === 4)) {
|
|
272
296
|
throw new TypeError('Malformed TS offset in DateTime.');
|
|
273
297
|
}
|
|
298
|
+
|
|
274
299
|
if (n === 2) {
|
|
275
|
-
|
|
300
|
+
utcOffset = 60 * val;
|
|
276
301
|
} else if (n === 4) {
|
|
277
|
-
|
|
302
|
+
utcOffset = (60 * (Math.trunc(val / 100))) + (val % 100);
|
|
278
303
|
}
|
|
304
|
+
|
|
279
305
|
if (b === '-'.codePointAt(0)) {
|
|
280
|
-
|
|
306
|
+
utcOffset = -utcOffset;
|
|
281
307
|
}
|
|
282
308
|
}
|
|
283
309
|
|
|
@@ -287,14 +313,15 @@ class CponReader {
|
|
|
287
313
|
}
|
|
288
314
|
|
|
289
315
|
// let epoch_sec = CponReader.timegm(year, month, mday, hour, min, sec);
|
|
290
|
-
let
|
|
291
|
-
|
|
292
|
-
return withOffset(new Date(
|
|
316
|
+
let epochMsec = Date.UTC(year, month - 1, day, hour, min, sec, msec);
|
|
317
|
+
epochMsec -= utcOffset * 60_000;
|
|
318
|
+
return withOffset(new Date(epochMsec), utcOffset);
|
|
293
319
|
}
|
|
294
320
|
|
|
295
321
|
readCString() {
|
|
296
322
|
const pctx = new PackContext();
|
|
297
323
|
this.ctx.getByte(); // eat '"'
|
|
324
|
+
// eslint-disable-next-line no-constant-condition
|
|
298
325
|
while (true) {
|
|
299
326
|
let b = this.ctx.getByte();
|
|
300
327
|
if (b === '\\'.codePointAt(0)) {
|
|
@@ -335,12 +362,14 @@ class CponReader {
|
|
|
335
362
|
pctx.putByte(b);
|
|
336
363
|
}
|
|
337
364
|
}
|
|
365
|
+
|
|
338
366
|
return utf8ToString(pctx.buffer());
|
|
339
367
|
}
|
|
340
368
|
|
|
341
369
|
readBlobEsc() {
|
|
342
370
|
const pctx = new PackContext();
|
|
343
371
|
this.ctx.getByte(); // eat '"'
|
|
372
|
+
// eslint-disable-next-line no-constant-condition
|
|
344
373
|
while (true) {
|
|
345
374
|
let b = this.ctx.getByte();
|
|
346
375
|
if (b === '\\'.codePointAt(0)) {
|
|
@@ -376,12 +405,14 @@ class CponReader {
|
|
|
376
405
|
throw new TypeError('Escaped Blob characters must be lower than 128, code: ' + b);
|
|
377
406
|
}
|
|
378
407
|
}
|
|
408
|
+
|
|
379
409
|
return pctx.buffer();
|
|
380
410
|
}
|
|
381
411
|
|
|
382
412
|
readBlobHex() {
|
|
383
413
|
const pctx = new PackContext();
|
|
384
414
|
this.ctx.getByte(); // eat '"'
|
|
415
|
+
// eslint-disable-next-line no-constant-condition
|
|
385
416
|
while (true) {
|
|
386
417
|
const b = this.ctx.getByte();
|
|
387
418
|
if (b === '"'.codePointAt(0)) {
|
|
@@ -392,12 +423,14 @@ class CponReader {
|
|
|
392
423
|
pctx.putByte(b2);
|
|
393
424
|
}
|
|
394
425
|
}
|
|
426
|
+
|
|
395
427
|
return pctx.buffer();
|
|
396
428
|
}
|
|
397
429
|
|
|
398
430
|
readList() {
|
|
399
431
|
const lst = [];
|
|
400
432
|
this.ctx.getByte(); // eat '['
|
|
433
|
+
// eslint-disable-next-line no-constant-condition
|
|
401
434
|
while (true) {
|
|
402
435
|
this.skipWhitespace();
|
|
403
436
|
const b = this.ctx.peekByte();
|
|
@@ -405,9 +438,11 @@ class CponReader {
|
|
|
405
438
|
this.ctx.getByte();
|
|
406
439
|
break;
|
|
407
440
|
}
|
|
441
|
+
|
|
408
442
|
const item = this.read();
|
|
409
443
|
lst.push(item);
|
|
410
444
|
}
|
|
445
|
+
|
|
411
446
|
return lst;
|
|
412
447
|
}
|
|
413
448
|
|
|
@@ -433,10 +468,12 @@ class CponReader {
|
|
|
433
468
|
if (b < 0) {
|
|
434
469
|
break;
|
|
435
470
|
}
|
|
471
|
+
|
|
436
472
|
if (b === 43 || b === 45) { // '+','-'
|
|
437
473
|
if (n !== 0) {
|
|
438
474
|
break;
|
|
439
475
|
}
|
|
476
|
+
|
|
440
477
|
this.ctx.getByte();
|
|
441
478
|
if (b === 45) {
|
|
442
479
|
neg = 1;
|
|
@@ -445,9 +482,11 @@ class CponReader {
|
|
|
445
482
|
if (n === 1 && val !== 0) {
|
|
446
483
|
break;
|
|
447
484
|
}
|
|
485
|
+
|
|
448
486
|
if (n !== 1) {
|
|
449
487
|
break;
|
|
450
488
|
}
|
|
489
|
+
|
|
451
490
|
this.ctx.getByte();
|
|
452
491
|
base = 16;
|
|
453
492
|
} else if (b >= 48 && b <= 57) { // '0' - '9'
|
|
@@ -458,6 +497,7 @@ class CponReader {
|
|
|
458
497
|
if (base !== 16) {
|
|
459
498
|
break;
|
|
460
499
|
}
|
|
500
|
+
|
|
461
501
|
this.ctx.getByte();
|
|
462
502
|
val *= base;
|
|
463
503
|
val += b - 65 + 10;
|
|
@@ -465,6 +505,7 @@ class CponReader {
|
|
|
465
505
|
if (base !== 16) {
|
|
466
506
|
break;
|
|
467
507
|
}
|
|
508
|
+
|
|
468
509
|
this.ctx.getByte();
|
|
469
510
|
val *= base;
|
|
470
511
|
val += b - 97 + 10;
|
|
@@ -472,9 +513,11 @@ class CponReader {
|
|
|
472
513
|
break;
|
|
473
514
|
}
|
|
474
515
|
}
|
|
516
|
+
|
|
475
517
|
if (neg) {
|
|
476
518
|
val = -val;
|
|
477
519
|
}
|
|
520
|
+
|
|
478
521
|
return val;
|
|
479
522
|
}
|
|
480
523
|
|
|
@@ -482,72 +525,82 @@ class CponReader {
|
|
|
482
525
|
let mantisa = 0;
|
|
483
526
|
let exponent = 0;
|
|
484
527
|
let decimals = 0;
|
|
485
|
-
let
|
|
486
|
-
let
|
|
487
|
-
let
|
|
488
|
-
let
|
|
528
|
+
let decCnt = 0;
|
|
529
|
+
let isDecimal = false;
|
|
530
|
+
let isUint = false;
|
|
531
|
+
let isNeg = false;
|
|
489
532
|
|
|
490
533
|
let b = this.ctx.peekByte();
|
|
491
534
|
if (b === 43) {// '+'
|
|
492
|
-
|
|
535
|
+
isNeg = false;
|
|
493
536
|
b = this.ctx.getByte();
|
|
494
537
|
} else if (b === 45) {// '-'
|
|
495
|
-
|
|
538
|
+
isNeg = true;
|
|
496
539
|
b = this.ctx.getByte();
|
|
497
540
|
}
|
|
498
541
|
|
|
499
542
|
mantisa = Number(this.readInt());
|
|
500
543
|
b = this.ctx.peekByte();
|
|
501
544
|
(() => {
|
|
545
|
+
// eslint-disable-next-line no-constant-condition
|
|
502
546
|
while (true) {
|
|
503
547
|
switch (b) {
|
|
504
548
|
case 'u'.codePointAt(0): {
|
|
505
|
-
|
|
549
|
+
isUint = true;
|
|
506
550
|
this.ctx.getByte();
|
|
507
551
|
return;
|
|
508
552
|
}
|
|
553
|
+
|
|
509
554
|
case '.'.codePointAt(0): {
|
|
510
|
-
|
|
555
|
+
isDecimal = true;
|
|
511
556
|
this.ctx.getByte();
|
|
512
557
|
const ix1 = this.ctx.index;
|
|
513
558
|
decimals = Number(this.readInt());
|
|
514
559
|
// if(n < 0)
|
|
515
560
|
// UNPACK_ERROR(CCPCP_RC_MALFORMED_INPUT, "Malformed number decimal part.")
|
|
516
|
-
|
|
561
|
+
decCnt = this.ctx.index - ix1;
|
|
517
562
|
b = this.ctx.peekByte();
|
|
518
563
|
if (b >= 0) {
|
|
519
564
|
continue;
|
|
520
565
|
}
|
|
566
|
+
|
|
521
567
|
return;
|
|
522
568
|
}
|
|
569
|
+
|
|
523
570
|
case 'e'.codePointAt(0):
|
|
524
571
|
case 'E'.codePointAt(0): {
|
|
525
|
-
|
|
572
|
+
isDecimal = true;
|
|
526
573
|
this.ctx.getByte();
|
|
527
574
|
const ix1 = this.ctx.index;
|
|
528
575
|
exponent = Number(this.readInt());
|
|
529
576
|
if (ix1 === this.ctx.index) {
|
|
530
577
|
throw new TypeError('Malformed number exponential part.');
|
|
531
578
|
}
|
|
579
|
+
|
|
532
580
|
return;
|
|
533
581
|
}
|
|
582
|
+
|
|
534
583
|
default:
|
|
535
584
|
return;
|
|
536
585
|
}
|
|
537
586
|
}
|
|
538
587
|
})();
|
|
539
|
-
|
|
540
|
-
|
|
588
|
+
|
|
589
|
+
if (isDecimal) {
|
|
590
|
+
for (let i = 0; i < decCnt; ++i) {
|
|
541
591
|
mantisa *= 10;
|
|
542
592
|
}
|
|
593
|
+
|
|
543
594
|
mantisa += decimals;
|
|
544
|
-
mantisa =
|
|
545
|
-
return new Decimal(mantisa, exponent -
|
|
595
|
+
mantisa = isNeg ? -mantisa : mantisa;
|
|
596
|
+
return new Decimal(mantisa, exponent - decCnt);
|
|
546
597
|
}
|
|
547
|
-
|
|
598
|
+
|
|
599
|
+
if (isUint) {
|
|
548
600
|
return new UInt(mantisa);
|
|
549
601
|
}
|
|
550
|
-
|
|
602
|
+
|
|
603
|
+
return isNeg ? -mantisa : mantisa;
|
|
551
604
|
}
|
|
552
605
|
|
|
553
606
|
private implReadMap(map_type: 'map', terminator: number): ShvMap;
|
|
@@ -558,6 +611,7 @@ class CponReader {
|
|
|
558
611
|
[shvMapType]: map_type,
|
|
559
612
|
};
|
|
560
613
|
this.ctx.getByte(); // eat start
|
|
614
|
+
// eslint-disable-next-line no-constant-condition
|
|
561
615
|
while (true) {
|
|
562
616
|
this.skipWhitespace();
|
|
563
617
|
const b = this.ctx.peekByte();
|
|
@@ -565,6 +619,7 @@ class CponReader {
|
|
|
565
619
|
this.ctx.getByte();
|
|
566
620
|
break;
|
|
567
621
|
}
|
|
622
|
+
|
|
568
623
|
const key = this.read();
|
|
569
624
|
if (key instanceof RpcValueWithMetaData) {
|
|
570
625
|
throw new TypeError('Map/IMap/MetaMap key can\'t have its own MetaData');
|
|
@@ -585,6 +640,7 @@ class CponReader {
|
|
|
585
640
|
throw new TypeError('Malformed map, invalid key');
|
|
586
641
|
}
|
|
587
642
|
}
|
|
643
|
+
|
|
588
644
|
return map;
|
|
589
645
|
}
|
|
590
646
|
}
|
|
@@ -642,6 +698,7 @@ class CponWriter {
|
|
|
642
698
|
this.writeMap(rpc_val);
|
|
643
699
|
break;
|
|
644
700
|
}
|
|
701
|
+
|
|
645
702
|
break;
|
|
646
703
|
default:
|
|
647
704
|
console.log('Can\'t serialize rpc value', rpc_val);
|
|
@@ -679,6 +736,7 @@ class CponWriter {
|
|
|
679
736
|
this.ctx.writeCharCodeUtf8(charcode);
|
|
680
737
|
}
|
|
681
738
|
}
|
|
739
|
+
|
|
682
740
|
this.ctx.writeStringUtf8('"');
|
|
683
741
|
}
|
|
684
742
|
|
|
@@ -712,6 +770,7 @@ class CponWriter {
|
|
|
712
770
|
}
|
|
713
771
|
}
|
|
714
772
|
}
|
|
773
|
+
|
|
715
774
|
this.ctx.writeStringUtf8('"');
|
|
716
775
|
}
|
|
717
776
|
|
|
@@ -720,32 +779,37 @@ class CponWriter {
|
|
|
720
779
|
this.ctx.writeStringUtf8('d""');
|
|
721
780
|
return;
|
|
722
781
|
}
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
782
|
+
|
|
783
|
+
const epochMsec = dt.getTime();
|
|
784
|
+
let utcOffset = dt.utc_offset;
|
|
785
|
+
const localMsec = epochMsec + (60_000 * (utcOffset ?? 0));
|
|
786
|
+
let s = new Date(localMsec).toISOString();
|
|
787
|
+
const rtrim = (localMsec % 1000) ? 1 : 5;
|
|
728
788
|
this.ctx.writeStringUtf8('d"');
|
|
729
789
|
for (let i = 0; i < s.length - rtrim; i++) {
|
|
730
790
|
this.ctx.putByte(s.codePointAt(i)!);
|
|
731
791
|
}
|
|
732
|
-
|
|
792
|
+
|
|
793
|
+
if (utcOffset === undefined || utcOffset === 0) {
|
|
733
794
|
this.ctx.writeStringUtf8('Z');
|
|
734
795
|
} else {
|
|
735
|
-
if (
|
|
796
|
+
if (utcOffset < 0) {
|
|
736
797
|
this.ctx.writeStringUtf8('-');
|
|
737
|
-
|
|
798
|
+
utcOffset = -utcOffset;
|
|
738
799
|
} else {
|
|
739
800
|
this.ctx.writeStringUtf8('+');
|
|
740
801
|
}
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
802
|
+
|
|
803
|
+
s = (Math.trunc(utcOffset / 60)).toString().padStart(2, '0');
|
|
804
|
+
if (utcOffset % 60) {
|
|
805
|
+
s += (utcOffset % 60).toString().padStart(2, '0');
|
|
744
806
|
}
|
|
807
|
+
|
|
745
808
|
for (let i = 0; i < s.length; i++) {
|
|
746
809
|
this.ctx.putByte(s.codePointAt(i)!);
|
|
747
810
|
}
|
|
748
811
|
}
|
|
812
|
+
|
|
749
813
|
this.ctx.writeStringUtf8('"');
|
|
750
814
|
}
|
|
751
815
|
|
|
@@ -770,31 +834,33 @@ class CponWriter {
|
|
|
770
834
|
this.increaseIndentIfNotOneLiner(map);
|
|
771
835
|
this.doIndentIfNotOneliner(map);
|
|
772
836
|
let first = true;
|
|
773
|
-
for (const [key, value] of Object.entries(map)) {
|
|
837
|
+
for (const [key, value] of Object.entries<RpcValue>(map)) {
|
|
774
838
|
if (value === undefined) {
|
|
775
839
|
continue;
|
|
776
840
|
}
|
|
841
|
+
|
|
777
842
|
if (!first) {
|
|
778
843
|
this.ctx.putByte(','.codePointAt(0)!);
|
|
779
844
|
this.doIndentIfNotOneliner(map);
|
|
780
845
|
}
|
|
846
|
+
|
|
781
847
|
first = false;
|
|
782
848
|
|
|
783
849
|
if (map[shvMapType] === 'imap') {
|
|
784
|
-
const
|
|
785
|
-
if (Number.isNaN(
|
|
850
|
+
const intKey = Number(key);
|
|
851
|
+
if (Number.isNaN(intKey)) {
|
|
786
852
|
throw new TypeError('Invalid NaN IMap key');
|
|
787
853
|
}
|
|
788
854
|
|
|
789
|
-
this.writeInt(
|
|
855
|
+
this.writeInt(intKey);
|
|
790
856
|
} else if (map[shvMapType] === 'metamap') {
|
|
791
|
-
const
|
|
792
|
-
if (Number.isNaN(
|
|
857
|
+
const intKey = Number(key);
|
|
858
|
+
if (Number.isNaN(intKey)) {
|
|
793
859
|
this.ctx.putByte('"'.codePointAt(0)!);
|
|
794
860
|
this.ctx.writeStringUtf8(key.toString());
|
|
795
861
|
this.ctx.putByte('"'.codePointAt(0)!);
|
|
796
862
|
} else {
|
|
797
|
-
this.writeInt(
|
|
863
|
+
this.writeInt(intKey);
|
|
798
864
|
}
|
|
799
865
|
} else {
|
|
800
866
|
this.writeJSString(key.toString());
|
|
@@ -818,8 +884,10 @@ class CponWriter {
|
|
|
818
884
|
this.ctx.putByte(','.codePointAt(0)!);
|
|
819
885
|
this.doIndentIfNotOneliner(lst);
|
|
820
886
|
}
|
|
887
|
+
|
|
821
888
|
this.write(element);
|
|
822
889
|
}
|
|
890
|
+
|
|
823
891
|
this.decreaseIndentIfNotOneLiner(lst);
|
|
824
892
|
this.doIndentIfNotOneliner(lst);
|
|
825
893
|
this.ctx.putByte(']'.codePointAt(0)!);
|
|
@@ -841,6 +909,7 @@ class CponWriter {
|
|
|
841
909
|
if (!s.includes('.')) {
|
|
842
910
|
s += '.';
|
|
843
911
|
}
|
|
912
|
+
|
|
844
913
|
this.ctx.writeStringUtf8(s);
|
|
845
914
|
}
|
|
846
915
|
|
|
@@ -851,29 +920,33 @@ class CponWriter {
|
|
|
851
920
|
mantisa = -mantisa;
|
|
852
921
|
this.ctx.putByte('-'.codePointAt(0)!);
|
|
853
922
|
}
|
|
923
|
+
|
|
854
924
|
let str = mantisa.toString();
|
|
855
925
|
const n = str.length;
|
|
856
|
-
const
|
|
857
|
-
if (
|
|
858
|
-
const
|
|
859
|
-
str = str.slice(0,
|
|
860
|
-
} else if (
|
|
861
|
-
const
|
|
926
|
+
const decPlaces = -exponent;
|
|
927
|
+
if (decPlaces > 0 && decPlaces < n) {
|
|
928
|
+
const dotIx = n - decPlaces;
|
|
929
|
+
str = str.slice(0, dotIx) + '.' + str.slice(dotIx);
|
|
930
|
+
} else if (decPlaces > 0 && decPlaces <= 3) {
|
|
931
|
+
const extraZeroCnt = decPlaces - n;
|
|
862
932
|
let str0 = '0.';
|
|
863
|
-
for (let i = 0; i <
|
|
933
|
+
for (let i = 0; i < extraZeroCnt; ++i) {
|
|
864
934
|
str0 += '0';
|
|
865
935
|
}
|
|
936
|
+
|
|
866
937
|
str = str0 + str;
|
|
867
|
-
} else if (
|
|
938
|
+
} else if (decPlaces < 0 && n + exponent <= 9) {
|
|
868
939
|
for (let i = 0; i < exponent; ++i) {
|
|
869
940
|
str += '0';
|
|
870
941
|
}
|
|
942
|
+
|
|
871
943
|
str += '.';
|
|
872
|
-
} else if (
|
|
944
|
+
} else if (decPlaces === 0) {
|
|
873
945
|
str += '.';
|
|
874
946
|
} else {
|
|
875
947
|
str += 'e' + exponent;
|
|
876
948
|
}
|
|
949
|
+
|
|
877
950
|
for (let i = 0; i < str.length; ++i) {
|
|
878
951
|
this.ctx.putByte(str.codePointAt(i)!);
|
|
879
952
|
}
|
|
@@ -924,6 +997,6 @@ const fromCpon = (str: string | Uint8Array) => {
|
|
|
924
997
|
return rd.read();
|
|
925
998
|
};
|
|
926
999
|
|
|
927
|
-
const
|
|
1000
|
+
const CPON_PROTOCOL_TYPE = 2;
|
|
928
1001
|
|
|
929
|
-
export {utf8ToString, CponWriter, CponReader,
|
|
1002
|
+
export {utf8ToString, CponWriter, CponReader, CPON_PROTOCOL_TYPE, toCpon, fromCpon};
|