cbor-x 1.3.2 → 1.3.3
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/decode.d.ts +1 -0
- package/decode.js +1167 -1160
- package/dist/index.js +1041 -1034
- package/dist/index.min.js +15 -14
- package/dist/node.cjs +1085 -1078
- package/dist/test.js +683 -683
- package/package.json +77 -76
package/dist/index.js
CHANGED
|
@@ -4,1040 +4,1047 @@
|
|
|
4
4
|
(global = global || self, factory(global.CBOR = {}));
|
|
5
5
|
}(this, (function (exports) { 'use strict';
|
|
6
6
|
|
|
7
|
-
let decoder;
|
|
8
|
-
try {
|
|
9
|
-
decoder = new TextDecoder();
|
|
10
|
-
} catch(error) {}
|
|
11
|
-
let src;
|
|
12
|
-
let srcEnd;
|
|
13
|
-
let position = 0;
|
|
14
|
-
const LEGACY_RECORD_INLINE_ID = 105;
|
|
15
|
-
const RECORD_DEFINITIONS_ID = 0xdffe;
|
|
16
|
-
const RECORD_INLINE_ID = 0xdfff; // temporary first-come first-serve tag // proposed tag: 0x7265 // 're'
|
|
17
|
-
const BUNDLED_STRINGS_ID = 0xdff9;
|
|
18
|
-
const PACKED_REFERENCE_TAG_ID = 6;
|
|
19
|
-
const STOP_CODE = {};
|
|
20
|
-
let currentDecoder = {};
|
|
21
|
-
let currentStructures;
|
|
22
|
-
let srcString;
|
|
23
|
-
let srcStringStart = 0;
|
|
24
|
-
let srcStringEnd = 0;
|
|
25
|
-
let bundledStrings;
|
|
26
|
-
let referenceMap;
|
|
27
|
-
let currentExtensions = [];
|
|
28
|
-
let currentExtensionRanges = [];
|
|
29
|
-
let packedValues;
|
|
30
|
-
let dataView;
|
|
31
|
-
let restoreMapsAsObject;
|
|
32
|
-
let defaultOptions = {
|
|
33
|
-
useRecords: false,
|
|
34
|
-
mapsAsObjects: true
|
|
35
|
-
};
|
|
36
|
-
let sequentialMode = false;
|
|
37
|
-
|
|
38
|
-
class Decoder {
|
|
39
|
-
constructor(options) {
|
|
40
|
-
if (options) {
|
|
41
|
-
if ((options.keyMap || options._keyMap) && !options.useRecords) {
|
|
42
|
-
options.useRecords = false;
|
|
43
|
-
options.mapsAsObjects = true;
|
|
44
|
-
}
|
|
45
|
-
if (options.useRecords === false && options.mapsAsObjects === undefined)
|
|
46
|
-
options.mapsAsObjects = true;
|
|
47
|
-
if (options.getStructures)
|
|
48
|
-
options.getShared = options.getStructures;
|
|
49
|
-
if (options.getShared && !options.structures)
|
|
50
|
-
(options.structures = []).uninitialized = true; // this is what we use to denote an uninitialized structures
|
|
51
|
-
if (options.keyMap) {
|
|
52
|
-
this.mapKey = new Map();
|
|
53
|
-
for (let [k,v] of Object.entries(options.keyMap)) this.mapKey.set(v,k);
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
Object.assign(this, options);
|
|
57
|
-
}
|
|
58
|
-
/*
|
|
59
|
-
decodeKey(key) {
|
|
60
|
-
return this.keyMap
|
|
61
|
-
? Object.keys(this.keyMap)[Object.values(this.keyMap).indexOf(key)] || key
|
|
62
|
-
: key
|
|
63
|
-
}
|
|
64
|
-
*/
|
|
65
|
-
decodeKey(key) {
|
|
66
|
-
return this.keyMap ? this.mapKey.get(key) || key : key
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
encodeKey(key) {
|
|
70
|
-
return this.keyMap && this.keyMap.hasOwnProperty(key) ? this.keyMap[key] : key
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
encodeKeys(rec) {
|
|
74
|
-
if (!this._keyMap) return rec
|
|
75
|
-
let map = new Map();
|
|
76
|
-
for (let [k,v] of Object.entries(rec)) map.set((this._keyMap.hasOwnProperty(k) ? this._keyMap[k] : k), v);
|
|
77
|
-
return map
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
decodeKeys(map) {
|
|
81
|
-
if (!this._keyMap || map.constructor.name != 'Map') return map
|
|
82
|
-
if (!this._mapKey) {
|
|
83
|
-
this._mapKey = new Map();
|
|
84
|
-
for (let [k,v] of Object.entries(this._keyMap)) this._mapKey.set(v,k);
|
|
85
|
-
}
|
|
86
|
-
let res = {};
|
|
87
|
-
//map.forEach((v,k) => res[Object.keys(this._keyMap)[Object.values(this._keyMap).indexOf(k)] || k] = v)
|
|
88
|
-
map.forEach((v,k) => res[this._mapKey.has(k) ? this._mapKey.get(k) : k] = v);
|
|
89
|
-
return res
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
mapDecode(source, end) {
|
|
93
|
-
|
|
94
|
-
let res = this.decode(source);
|
|
95
|
-
if (this._keyMap) {
|
|
96
|
-
//Experiemntal support for Optimised KeyMap decoding
|
|
97
|
-
switch (res.constructor.name) {
|
|
98
|
-
case 'Array': return res.map(r => this.decodeKeys(r))
|
|
99
|
-
//case 'Map': return this.decodeKeys(res)
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
return res
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
decode(source, end) {
|
|
106
|
-
if (src) {
|
|
107
|
-
// re-entrant execution, save the state and restore it after we do this decode
|
|
108
|
-
return saveState(() => {
|
|
109
|
-
clearSource();
|
|
110
|
-
return this ? this.decode(source, end) : Decoder.prototype.decode.call(defaultOptions, source, end)
|
|
111
|
-
})
|
|
112
|
-
}
|
|
113
|
-
srcEnd = end > -1 ? end : source.length;
|
|
114
|
-
position = 0;
|
|
115
|
-
srcStringEnd = 0;
|
|
116
|
-
srcString = null;
|
|
117
|
-
bundledStrings = null;
|
|
118
|
-
src = source;
|
|
119
|
-
// this provides cached access to the data view for a buffer if it is getting reused, which is a recommend
|
|
120
|
-
// technique for getting data from a database where it can be copied into an existing buffer instead of creating
|
|
121
|
-
// new ones
|
|
122
|
-
try {
|
|
123
|
-
dataView = source.dataView || (source.dataView = new DataView(source.buffer, source.byteOffset, source.byteLength));
|
|
124
|
-
} catch(error) {
|
|
125
|
-
// if it doesn't have a buffer, maybe it is the wrong type of object
|
|
126
|
-
src = null;
|
|
127
|
-
if (source instanceof Uint8Array)
|
|
128
|
-
throw error
|
|
129
|
-
throw new Error('Source must be a Uint8Array or Buffer but was a ' + ((source && typeof source == 'object') ? source.constructor.name : typeof source))
|
|
130
|
-
}
|
|
131
|
-
if (this instanceof Decoder) {
|
|
132
|
-
currentDecoder = this;
|
|
133
|
-
packedValues = this.sharedValues &&
|
|
134
|
-
(this.pack ? new Array(this.maxPrivatePackedValues || 16).concat(this.sharedValues) :
|
|
135
|
-
this.sharedValues);
|
|
136
|
-
if (this.structures) {
|
|
137
|
-
currentStructures = this.structures;
|
|
138
|
-
return checkedRead()
|
|
139
|
-
} else if (!currentStructures || currentStructures.length > 0) {
|
|
140
|
-
currentStructures = [];
|
|
141
|
-
}
|
|
142
|
-
} else {
|
|
143
|
-
currentDecoder = defaultOptions;
|
|
144
|
-
if (!currentStructures || currentStructures.length > 0)
|
|
145
|
-
currentStructures = [];
|
|
146
|
-
packedValues = null;
|
|
147
|
-
}
|
|
148
|
-
return checkedRead()
|
|
149
|
-
}
|
|
150
|
-
decodeMultiple(source, forEach) {
|
|
151
|
-
let values, lastPosition = 0;
|
|
152
|
-
try {
|
|
153
|
-
let size = source.length;
|
|
154
|
-
sequentialMode = true;
|
|
155
|
-
let value = this ? this.decode(source, size) : defaultDecoder.decode(source, size);
|
|
156
|
-
if (forEach) {
|
|
157
|
-
if (forEach(value) === false) {
|
|
158
|
-
return
|
|
159
|
-
}
|
|
160
|
-
while(position < size) {
|
|
161
|
-
lastPosition = position;
|
|
162
|
-
if (forEach(checkedRead()) === false) {
|
|
163
|
-
return
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
else {
|
|
168
|
-
values = [ value ];
|
|
169
|
-
while(position < size) {
|
|
170
|
-
lastPosition = position;
|
|
171
|
-
values.push(checkedRead());
|
|
172
|
-
}
|
|
173
|
-
return values
|
|
174
|
-
}
|
|
175
|
-
} catch(error) {
|
|
176
|
-
error.lastPosition = lastPosition;
|
|
177
|
-
error.values = values;
|
|
178
|
-
throw error
|
|
179
|
-
} finally {
|
|
180
|
-
sequentialMode = false;
|
|
181
|
-
clearSource();
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
function checkedRead() {
|
|
186
|
-
try {
|
|
187
|
-
let result = read();
|
|
188
|
-
if (bundledStrings)
|
|
189
|
-
position
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
break
|
|
232
|
-
case
|
|
233
|
-
if (majorType == 7) {
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
case
|
|
278
|
-
let
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
let
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
let
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
return read()
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
case
|
|
429
|
-
length =
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
if
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
this.
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
//
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
const
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
units.
|
|
511
|
-
}
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
return
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
return
|
|
553
|
-
}
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
let
|
|
557
|
-
if ((
|
|
558
|
-
position -=
|
|
559
|
-
return
|
|
560
|
-
}
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
return fromCharCode(a, b, c, d
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
return
|
|
589
|
-
}
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
let
|
|
593
|
-
if ((
|
|
594
|
-
position -=
|
|
595
|
-
return
|
|
596
|
-
}
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
let
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
return fromCharCode(a, b, c, d, e, f, g, h
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
return
|
|
624
|
-
}
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
let
|
|
628
|
-
if ((
|
|
629
|
-
position -=
|
|
630
|
-
return
|
|
631
|
-
}
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
let
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
return fromCharCode(a, b, c, d, e, f, g, h, i, j, k, l
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
return
|
|
659
|
-
}
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
let
|
|
663
|
-
if ((
|
|
664
|
-
position -=
|
|
665
|
-
return
|
|
666
|
-
}
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
}
|
|
680
|
-
|
|
681
|
-
function
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
}
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
structure
|
|
749
|
-
let
|
|
750
|
-
if (
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
currentExtensions[
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
if (
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
return
|
|
860
|
-
}
|
|
861
|
-
function
|
|
862
|
-
if (
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
if (tag ==
|
|
892
|
-
return
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
}
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
let
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
case
|
|
958
|
-
token =
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
let
|
|
994
|
-
let
|
|
995
|
-
let
|
|
996
|
-
let
|
|
997
|
-
let
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
const
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
7
|
+
let decoder;
|
|
8
|
+
try {
|
|
9
|
+
decoder = new TextDecoder();
|
|
10
|
+
} catch(error) {}
|
|
11
|
+
let src;
|
|
12
|
+
let srcEnd;
|
|
13
|
+
let position = 0;
|
|
14
|
+
const LEGACY_RECORD_INLINE_ID = 105;
|
|
15
|
+
const RECORD_DEFINITIONS_ID = 0xdffe;
|
|
16
|
+
const RECORD_INLINE_ID = 0xdfff; // temporary first-come first-serve tag // proposed tag: 0x7265 // 're'
|
|
17
|
+
const BUNDLED_STRINGS_ID = 0xdff9;
|
|
18
|
+
const PACKED_REFERENCE_TAG_ID = 6;
|
|
19
|
+
const STOP_CODE = {};
|
|
20
|
+
let currentDecoder = {};
|
|
21
|
+
let currentStructures;
|
|
22
|
+
let srcString;
|
|
23
|
+
let srcStringStart = 0;
|
|
24
|
+
let srcStringEnd = 0;
|
|
25
|
+
let bundledStrings;
|
|
26
|
+
let referenceMap;
|
|
27
|
+
let currentExtensions = [];
|
|
28
|
+
let currentExtensionRanges = [];
|
|
29
|
+
let packedValues;
|
|
30
|
+
let dataView;
|
|
31
|
+
let restoreMapsAsObject;
|
|
32
|
+
let defaultOptions = {
|
|
33
|
+
useRecords: false,
|
|
34
|
+
mapsAsObjects: true
|
|
35
|
+
};
|
|
36
|
+
let sequentialMode = false;
|
|
37
|
+
|
|
38
|
+
class Decoder {
|
|
39
|
+
constructor(options) {
|
|
40
|
+
if (options) {
|
|
41
|
+
if ((options.keyMap || options._keyMap) && !options.useRecords) {
|
|
42
|
+
options.useRecords = false;
|
|
43
|
+
options.mapsAsObjects = true;
|
|
44
|
+
}
|
|
45
|
+
if (options.useRecords === false && options.mapsAsObjects === undefined)
|
|
46
|
+
options.mapsAsObjects = true;
|
|
47
|
+
if (options.getStructures)
|
|
48
|
+
options.getShared = options.getStructures;
|
|
49
|
+
if (options.getShared && !options.structures)
|
|
50
|
+
(options.structures = []).uninitialized = true; // this is what we use to denote an uninitialized structures
|
|
51
|
+
if (options.keyMap) {
|
|
52
|
+
this.mapKey = new Map();
|
|
53
|
+
for (let [k,v] of Object.entries(options.keyMap)) this.mapKey.set(v,k);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
Object.assign(this, options);
|
|
57
|
+
}
|
|
58
|
+
/*
|
|
59
|
+
decodeKey(key) {
|
|
60
|
+
return this.keyMap
|
|
61
|
+
? Object.keys(this.keyMap)[Object.values(this.keyMap).indexOf(key)] || key
|
|
62
|
+
: key
|
|
63
|
+
}
|
|
64
|
+
*/
|
|
65
|
+
decodeKey(key) {
|
|
66
|
+
return this.keyMap ? this.mapKey.get(key) || key : key
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
encodeKey(key) {
|
|
70
|
+
return this.keyMap && this.keyMap.hasOwnProperty(key) ? this.keyMap[key] : key
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
encodeKeys(rec) {
|
|
74
|
+
if (!this._keyMap) return rec
|
|
75
|
+
let map = new Map();
|
|
76
|
+
for (let [k,v] of Object.entries(rec)) map.set((this._keyMap.hasOwnProperty(k) ? this._keyMap[k] : k), v);
|
|
77
|
+
return map
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
decodeKeys(map) {
|
|
81
|
+
if (!this._keyMap || map.constructor.name != 'Map') return map
|
|
82
|
+
if (!this._mapKey) {
|
|
83
|
+
this._mapKey = new Map();
|
|
84
|
+
for (let [k,v] of Object.entries(this._keyMap)) this._mapKey.set(v,k);
|
|
85
|
+
}
|
|
86
|
+
let res = {};
|
|
87
|
+
//map.forEach((v,k) => res[Object.keys(this._keyMap)[Object.values(this._keyMap).indexOf(k)] || k] = v)
|
|
88
|
+
map.forEach((v,k) => res[this._mapKey.has(k) ? this._mapKey.get(k) : k] = v);
|
|
89
|
+
return res
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
mapDecode(source, end) {
|
|
93
|
+
|
|
94
|
+
let res = this.decode(source);
|
|
95
|
+
if (this._keyMap) {
|
|
96
|
+
//Experiemntal support for Optimised KeyMap decoding
|
|
97
|
+
switch (res.constructor.name) {
|
|
98
|
+
case 'Array': return res.map(r => this.decodeKeys(r))
|
|
99
|
+
//case 'Map': return this.decodeKeys(res)
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return res
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
decode(source, end) {
|
|
106
|
+
if (src) {
|
|
107
|
+
// re-entrant execution, save the state and restore it after we do this decode
|
|
108
|
+
return saveState(() => {
|
|
109
|
+
clearSource();
|
|
110
|
+
return this ? this.decode(source, end) : Decoder.prototype.decode.call(defaultOptions, source, end)
|
|
111
|
+
})
|
|
112
|
+
}
|
|
113
|
+
srcEnd = end > -1 ? end : source.length;
|
|
114
|
+
position = 0;
|
|
115
|
+
srcStringEnd = 0;
|
|
116
|
+
srcString = null;
|
|
117
|
+
bundledStrings = null;
|
|
118
|
+
src = source;
|
|
119
|
+
// this provides cached access to the data view for a buffer if it is getting reused, which is a recommend
|
|
120
|
+
// technique for getting data from a database where it can be copied into an existing buffer instead of creating
|
|
121
|
+
// new ones
|
|
122
|
+
try {
|
|
123
|
+
dataView = source.dataView || (source.dataView = new DataView(source.buffer, source.byteOffset, source.byteLength));
|
|
124
|
+
} catch(error) {
|
|
125
|
+
// if it doesn't have a buffer, maybe it is the wrong type of object
|
|
126
|
+
src = null;
|
|
127
|
+
if (source instanceof Uint8Array)
|
|
128
|
+
throw error
|
|
129
|
+
throw new Error('Source must be a Uint8Array or Buffer but was a ' + ((source && typeof source == 'object') ? source.constructor.name : typeof source))
|
|
130
|
+
}
|
|
131
|
+
if (this instanceof Decoder) {
|
|
132
|
+
currentDecoder = this;
|
|
133
|
+
packedValues = this.sharedValues &&
|
|
134
|
+
(this.pack ? new Array(this.maxPrivatePackedValues || 16).concat(this.sharedValues) :
|
|
135
|
+
this.sharedValues);
|
|
136
|
+
if (this.structures) {
|
|
137
|
+
currentStructures = this.structures;
|
|
138
|
+
return checkedRead()
|
|
139
|
+
} else if (!currentStructures || currentStructures.length > 0) {
|
|
140
|
+
currentStructures = [];
|
|
141
|
+
}
|
|
142
|
+
} else {
|
|
143
|
+
currentDecoder = defaultOptions;
|
|
144
|
+
if (!currentStructures || currentStructures.length > 0)
|
|
145
|
+
currentStructures = [];
|
|
146
|
+
packedValues = null;
|
|
147
|
+
}
|
|
148
|
+
return checkedRead()
|
|
149
|
+
}
|
|
150
|
+
decodeMultiple(source, forEach) {
|
|
151
|
+
let values, lastPosition = 0;
|
|
152
|
+
try {
|
|
153
|
+
let size = source.length;
|
|
154
|
+
sequentialMode = true;
|
|
155
|
+
let value = this ? this.decode(source, size) : defaultDecoder.decode(source, size);
|
|
156
|
+
if (forEach) {
|
|
157
|
+
if (forEach(value) === false) {
|
|
158
|
+
return
|
|
159
|
+
}
|
|
160
|
+
while(position < size) {
|
|
161
|
+
lastPosition = position;
|
|
162
|
+
if (forEach(checkedRead()) === false) {
|
|
163
|
+
return
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
else {
|
|
168
|
+
values = [ value ];
|
|
169
|
+
while(position < size) {
|
|
170
|
+
lastPosition = position;
|
|
171
|
+
values.push(checkedRead());
|
|
172
|
+
}
|
|
173
|
+
return values
|
|
174
|
+
}
|
|
175
|
+
} catch(error) {
|
|
176
|
+
error.lastPosition = lastPosition;
|
|
177
|
+
error.values = values;
|
|
178
|
+
throw error
|
|
179
|
+
} finally {
|
|
180
|
+
sequentialMode = false;
|
|
181
|
+
clearSource();
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
function checkedRead() {
|
|
186
|
+
try {
|
|
187
|
+
let result = read();
|
|
188
|
+
if (bundledStrings) {
|
|
189
|
+
if (position >= bundledStrings.postBundlePosition) {
|
|
190
|
+
let error = new Error('Unexpected bundle position');
|
|
191
|
+
error.incomplete = true;
|
|
192
|
+
throw error
|
|
193
|
+
}
|
|
194
|
+
// bundled strings to skip past
|
|
195
|
+
position = bundledStrings.postBundlePosition;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
if (position == srcEnd) {
|
|
199
|
+
// finished reading this source, cleanup references
|
|
200
|
+
currentStructures = null;
|
|
201
|
+
src = null;
|
|
202
|
+
if (referenceMap)
|
|
203
|
+
referenceMap = null;
|
|
204
|
+
} else if (position > srcEnd) {
|
|
205
|
+
// over read
|
|
206
|
+
let error = new Error('Unexpected end of CBOR data');
|
|
207
|
+
error.incomplete = true;
|
|
208
|
+
throw error
|
|
209
|
+
} else if (!sequentialMode) {
|
|
210
|
+
throw new Error('Data read, but end of buffer not reached')
|
|
211
|
+
}
|
|
212
|
+
// else more to read, but we are reading sequentially, so don't clear source yet
|
|
213
|
+
return result
|
|
214
|
+
} catch(error) {
|
|
215
|
+
clearSource();
|
|
216
|
+
if (error instanceof RangeError || error.message.startsWith('Unexpected end of buffer')) {
|
|
217
|
+
error.incomplete = true;
|
|
218
|
+
}
|
|
219
|
+
throw error
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
function read() {
|
|
224
|
+
let token = src[position++];
|
|
225
|
+
let majorType = token >> 5;
|
|
226
|
+
token = token & 0x1f;
|
|
227
|
+
if (token > 0x17) {
|
|
228
|
+
switch (token) {
|
|
229
|
+
case 0x18:
|
|
230
|
+
token = src[position++];
|
|
231
|
+
break
|
|
232
|
+
case 0x19:
|
|
233
|
+
if (majorType == 7) {
|
|
234
|
+
return getFloat16()
|
|
235
|
+
}
|
|
236
|
+
token = dataView.getUint16(position);
|
|
237
|
+
position += 2;
|
|
238
|
+
break
|
|
239
|
+
case 0x1a:
|
|
240
|
+
if (majorType == 7) {
|
|
241
|
+
let value = dataView.getFloat32(position);
|
|
242
|
+
if (currentDecoder.useFloat32 > 2) {
|
|
243
|
+
// this does rounding of numbers that were encoded in 32-bit float to nearest significant decimal digit that could be preserved
|
|
244
|
+
let multiplier = mult10[((src[position] & 0x7f) << 1) | (src[position + 1] >> 7)];
|
|
245
|
+
position += 4;
|
|
246
|
+
return ((multiplier * value + (value > 0 ? 0.5 : -0.5)) >> 0) / multiplier
|
|
247
|
+
}
|
|
248
|
+
position += 4;
|
|
249
|
+
return value
|
|
250
|
+
}
|
|
251
|
+
token = dataView.getUint32(position);
|
|
252
|
+
position += 4;
|
|
253
|
+
break
|
|
254
|
+
case 0x1b:
|
|
255
|
+
if (majorType == 7) {
|
|
256
|
+
let value = dataView.getFloat64(position);
|
|
257
|
+
position += 8;
|
|
258
|
+
return value
|
|
259
|
+
}
|
|
260
|
+
if (majorType > 1) {
|
|
261
|
+
if (dataView.getUint32(position) > 0)
|
|
262
|
+
throw new Error('JavaScript does not support arrays, maps, or strings with length over 4294967295')
|
|
263
|
+
token = dataView.getUint32(position + 4);
|
|
264
|
+
} else if (currentDecoder.int64AsNumber) {
|
|
265
|
+
token = dataView.getUint32(position) * 0x100000000;
|
|
266
|
+
token += dataView.getUint32(position + 4);
|
|
267
|
+
} else
|
|
268
|
+
token = dataView.getBigUint64(position);
|
|
269
|
+
position += 8;
|
|
270
|
+
break
|
|
271
|
+
case 0x1f:
|
|
272
|
+
// indefinite length
|
|
273
|
+
switch(majorType) {
|
|
274
|
+
case 2: // byte string
|
|
275
|
+
case 3: // text string
|
|
276
|
+
throw new Error('Indefinite length not supported for byte or text strings')
|
|
277
|
+
case 4: // array
|
|
278
|
+
let array = [];
|
|
279
|
+
let value, i = 0;
|
|
280
|
+
while ((value = read()) != STOP_CODE) {
|
|
281
|
+
array[i++] = value;
|
|
282
|
+
}
|
|
283
|
+
return majorType == 4 ? array : majorType == 3 ? array.join('') : Buffer.concat(array)
|
|
284
|
+
case 5: // map
|
|
285
|
+
let key;
|
|
286
|
+
if (currentDecoder.mapsAsObjects) {
|
|
287
|
+
let object = {};
|
|
288
|
+
if (currentDecoder.keyMap) while((key = read()) != STOP_CODE) object[currentDecoder.decodeKey(key)] = read();
|
|
289
|
+
else while ((key = read()) != STOP_CODE) object[key] = read();
|
|
290
|
+
return object
|
|
291
|
+
} else {
|
|
292
|
+
if (restoreMapsAsObject) {
|
|
293
|
+
currentDecoder.mapsAsObjects = true;
|
|
294
|
+
restoreMapsAsObject = false;
|
|
295
|
+
}
|
|
296
|
+
let map = new Map();
|
|
297
|
+
if (currentDecoder.keyMap) while((key = read()) != STOP_CODE) map.set(currentDecoder.decodeKey(key), read());
|
|
298
|
+
else while ((key = read()) != STOP_CODE) map.set(key, read());
|
|
299
|
+
return map
|
|
300
|
+
}
|
|
301
|
+
case 7:
|
|
302
|
+
return STOP_CODE
|
|
303
|
+
default:
|
|
304
|
+
throw new Error('Invalid major type for indefinite length ' + majorType)
|
|
305
|
+
}
|
|
306
|
+
default:
|
|
307
|
+
throw new Error('Unknown token ' + token)
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
switch (majorType) {
|
|
311
|
+
case 0: // positive int
|
|
312
|
+
return token
|
|
313
|
+
case 1: // negative int
|
|
314
|
+
return ~token
|
|
315
|
+
case 2: // buffer
|
|
316
|
+
return readBin(token)
|
|
317
|
+
case 3: // string
|
|
318
|
+
if (srcStringEnd >= position) {
|
|
319
|
+
return srcString.slice(position - srcStringStart, (position += token) - srcStringStart)
|
|
320
|
+
}
|
|
321
|
+
if (srcStringEnd == 0 && srcEnd < 140 && token < 32) {
|
|
322
|
+
// for small blocks, avoiding the overhead of the extract call is helpful
|
|
323
|
+
let string = token < 16 ? shortStringInJS(token) : longStringInJS(token);
|
|
324
|
+
if (string != null)
|
|
325
|
+
return string
|
|
326
|
+
}
|
|
327
|
+
return readFixedString(token)
|
|
328
|
+
case 4: // array
|
|
329
|
+
let array = new Array(token);
|
|
330
|
+
//if (currentDecoder.keyMap) for (let i = 0; i < token; i++) array[i] = currentDecoder.decodeKey(read())
|
|
331
|
+
//else
|
|
332
|
+
for (let i = 0; i < token; i++) array[i] = read();
|
|
333
|
+
return array
|
|
334
|
+
case 5: // map
|
|
335
|
+
if (currentDecoder.mapsAsObjects) {
|
|
336
|
+
let object = {};
|
|
337
|
+
if (currentDecoder.keyMap) for (let i = 0; i < token; i++) object[currentDecoder.decodeKey(read())] = read();
|
|
338
|
+
else for (let i = 0; i < token; i++) object[read()] = read();
|
|
339
|
+
return object
|
|
340
|
+
} else {
|
|
341
|
+
if (restoreMapsAsObject) {
|
|
342
|
+
currentDecoder.mapsAsObjects = true;
|
|
343
|
+
restoreMapsAsObject = false;
|
|
344
|
+
}
|
|
345
|
+
let map = new Map();
|
|
346
|
+
if (currentDecoder.keyMap) for (let i = 0; i < token; i++) map.set(currentDecoder.decodeKey(read()),read());
|
|
347
|
+
else for (let i = 0; i < token; i++) map.set(read(), read());
|
|
348
|
+
return map
|
|
349
|
+
}
|
|
350
|
+
case 6: // extension
|
|
351
|
+
if (token >= BUNDLED_STRINGS_ID) {
|
|
352
|
+
let structure = currentStructures[token & 0x1fff]; // check record structures first
|
|
353
|
+
// At some point we may provide an option for dynamic tag assignment with a range like token >= 8 && (token < 16 || (token > 0x80 && token < 0xc0) || (token > 0x130 && token < 0x4000))
|
|
354
|
+
if (structure) {
|
|
355
|
+
if (!structure.read) structure.read = createStructureReader(structure);
|
|
356
|
+
return structure.read()
|
|
357
|
+
}
|
|
358
|
+
if (token < 0x10000) {
|
|
359
|
+
if (token == RECORD_INLINE_ID) // we do a special check for this so that we can keep the currentExtensions as densely stored array (v8 stores arrays densely under about 3000 elements)
|
|
360
|
+
return recordDefinition(read())
|
|
361
|
+
else if (token == RECORD_DEFINITIONS_ID) {
|
|
362
|
+
let length = readJustLength();
|
|
363
|
+
let id = read();
|
|
364
|
+
for (let i = 2; i < length; i++) {
|
|
365
|
+
recordDefinition([id++, read()]);
|
|
366
|
+
}
|
|
367
|
+
return read()
|
|
368
|
+
} else if (token == BUNDLED_STRINGS_ID) {
|
|
369
|
+
return readBundleExt()
|
|
370
|
+
}
|
|
371
|
+
if (currentDecoder.getShared) {
|
|
372
|
+
loadShared();
|
|
373
|
+
structure = currentStructures[token & 0x1fff];
|
|
374
|
+
if (structure) {
|
|
375
|
+
if (!structure.read)
|
|
376
|
+
structure.read = createStructureReader(structure);
|
|
377
|
+
return structure.read()
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
let extension = currentExtensions[token];
|
|
383
|
+
if (extension) {
|
|
384
|
+
if (extension.handlesRead)
|
|
385
|
+
return extension(read)
|
|
386
|
+
else
|
|
387
|
+
return extension(read())
|
|
388
|
+
} else {
|
|
389
|
+
let input = read();
|
|
390
|
+
for (let i = 0; i < currentExtensionRanges.length; i++) {
|
|
391
|
+
let value = currentExtensionRanges[i](token, input);
|
|
392
|
+
if (value !== undefined)
|
|
393
|
+
return value
|
|
394
|
+
}
|
|
395
|
+
return new Tag(input, token)
|
|
396
|
+
}
|
|
397
|
+
case 7: // fixed value
|
|
398
|
+
switch (token) {
|
|
399
|
+
case 0x14: return false
|
|
400
|
+
case 0x15: return true
|
|
401
|
+
case 0x16: return null
|
|
402
|
+
case 0x17: return; // undefined
|
|
403
|
+
case 0x1f:
|
|
404
|
+
default:
|
|
405
|
+
let packedValue = (packedValues || getPackedValues())[token];
|
|
406
|
+
if (packedValue !== undefined)
|
|
407
|
+
return packedValue
|
|
408
|
+
throw new Error('Unknown token ' + token)
|
|
409
|
+
}
|
|
410
|
+
default: // negative int
|
|
411
|
+
if (isNaN(token)) {
|
|
412
|
+
let error = new Error('Unexpected end of CBOR data');
|
|
413
|
+
error.incomplete = true;
|
|
414
|
+
throw error
|
|
415
|
+
}
|
|
416
|
+
throw new Error('Unknown CBOR token ' + token)
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
const validName = /^[a-zA-Z_$][a-zA-Z\d_$]*$/;
|
|
420
|
+
function createStructureReader(structure) {
|
|
421
|
+
function readObject() {
|
|
422
|
+
// get the array size from the header
|
|
423
|
+
let length = src[position++];
|
|
424
|
+
//let majorType = token >> 5
|
|
425
|
+
length = length & 0x1f;
|
|
426
|
+
if (length > 0x17) {
|
|
427
|
+
switch (length) {
|
|
428
|
+
case 0x18:
|
|
429
|
+
length = src[position++];
|
|
430
|
+
break
|
|
431
|
+
case 0x19:
|
|
432
|
+
length = dataView.getUint16(position);
|
|
433
|
+
position += 2;
|
|
434
|
+
break
|
|
435
|
+
case 0x1a:
|
|
436
|
+
length = dataView.getUint32(position);
|
|
437
|
+
position += 4;
|
|
438
|
+
break
|
|
439
|
+
default:
|
|
440
|
+
throw new Error('Expected array header, but got ' + src[position - 1])
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
// This initial function is quick to instantiate, but runs slower. After several iterations pay the cost to build the faster function
|
|
444
|
+
let compiledReader = this.compiledReader; // first look to see if we have the fast compiled function
|
|
445
|
+
while(compiledReader) {
|
|
446
|
+
// we have a fast compiled object literal reader
|
|
447
|
+
if (compiledReader.propertyCount === length)
|
|
448
|
+
return compiledReader(read) // with the right length, so we use it
|
|
449
|
+
compiledReader = compiledReader.next; // see if there is another reader with the right length
|
|
450
|
+
}
|
|
451
|
+
if (this.slowReads++ >= 3) { // create a fast compiled reader
|
|
452
|
+
let array = this.length == length ? this : this.slice(0, length);
|
|
453
|
+
compiledReader = currentDecoder.keyMap
|
|
454
|
+
? new Function('r', 'return {' + array.map(k => currentDecoder.decodeKey(k)).map(k => validName.test(k) ? k + ':r()' : ('[' + JSON.stringify(k) + ']:r()')).join(',') + '}')
|
|
455
|
+
: new Function('r', 'return {' + array.map(key => validName.test(key) ? key + ':r()' : ('[' + JSON.stringify(key) + ']:r()')).join(',') + '}');
|
|
456
|
+
if (this.compiledReader)
|
|
457
|
+
compiledReader.next = this.compiledReader; // if there is an existing one, we store multiple readers as a linked list because it is usually pretty rare to have multiple readers (of different length) for the same structure
|
|
458
|
+
compiledReader.propertyCount = length;
|
|
459
|
+
this.compiledReader = compiledReader;
|
|
460
|
+
return compiledReader(read)
|
|
461
|
+
}
|
|
462
|
+
let object = {};
|
|
463
|
+
if (currentDecoder.keyMap) for (let i = 0; i < length; i++) object[currentDecoder.decodeKey(this[i])] = read();
|
|
464
|
+
else for (let i = 0; i < length; i++) object[this[i]] = read();
|
|
465
|
+
return object
|
|
466
|
+
}
|
|
467
|
+
structure.slowReads = 0;
|
|
468
|
+
return readObject
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
let readFixedString = readStringJS;
|
|
472
|
+
|
|
473
|
+
let isNativeAccelerationEnabled = false;
|
|
474
|
+
function readStringJS(length) {
|
|
475
|
+
let result;
|
|
476
|
+
if (length < 16) {
|
|
477
|
+
if (result = shortStringInJS(length))
|
|
478
|
+
return result
|
|
479
|
+
}
|
|
480
|
+
if (length > 64 && decoder)
|
|
481
|
+
return decoder.decode(src.subarray(position, position += length))
|
|
482
|
+
const end = position + length;
|
|
483
|
+
const units = [];
|
|
484
|
+
result = '';
|
|
485
|
+
while (position < end) {
|
|
486
|
+
const byte1 = src[position++];
|
|
487
|
+
if ((byte1 & 0x80) === 0) {
|
|
488
|
+
// 1 byte
|
|
489
|
+
units.push(byte1);
|
|
490
|
+
} else if ((byte1 & 0xe0) === 0xc0) {
|
|
491
|
+
// 2 bytes
|
|
492
|
+
const byte2 = src[position++] & 0x3f;
|
|
493
|
+
units.push(((byte1 & 0x1f) << 6) | byte2);
|
|
494
|
+
} else if ((byte1 & 0xf0) === 0xe0) {
|
|
495
|
+
// 3 bytes
|
|
496
|
+
const byte2 = src[position++] & 0x3f;
|
|
497
|
+
const byte3 = src[position++] & 0x3f;
|
|
498
|
+
units.push(((byte1 & 0x1f) << 12) | (byte2 << 6) | byte3);
|
|
499
|
+
} else if ((byte1 & 0xf8) === 0xf0) {
|
|
500
|
+
// 4 bytes
|
|
501
|
+
const byte2 = src[position++] & 0x3f;
|
|
502
|
+
const byte3 = src[position++] & 0x3f;
|
|
503
|
+
const byte4 = src[position++] & 0x3f;
|
|
504
|
+
let unit = ((byte1 & 0x07) << 0x12) | (byte2 << 0x0c) | (byte3 << 0x06) | byte4;
|
|
505
|
+
if (unit > 0xffff) {
|
|
506
|
+
unit -= 0x10000;
|
|
507
|
+
units.push(((unit >>> 10) & 0x3ff) | 0xd800);
|
|
508
|
+
unit = 0xdc00 | (unit & 0x3ff);
|
|
509
|
+
}
|
|
510
|
+
units.push(unit);
|
|
511
|
+
} else {
|
|
512
|
+
units.push(byte1);
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
if (units.length >= 0x1000) {
|
|
516
|
+
result += fromCharCode.apply(String, units);
|
|
517
|
+
units.length = 0;
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
if (units.length > 0) {
|
|
522
|
+
result += fromCharCode.apply(String, units);
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
return result
|
|
526
|
+
}
|
|
527
|
+
let fromCharCode = String.fromCharCode;
|
|
528
|
+
function longStringInJS(length) {
|
|
529
|
+
let start = position;
|
|
530
|
+
let bytes = new Array(length);
|
|
531
|
+
for (let i = 0; i < length; i++) {
|
|
532
|
+
const byte = src[position++];
|
|
533
|
+
if ((byte & 0x80) > 0) {
|
|
534
|
+
position = start;
|
|
535
|
+
return
|
|
536
|
+
}
|
|
537
|
+
bytes[i] = byte;
|
|
538
|
+
}
|
|
539
|
+
return fromCharCode.apply(String, bytes)
|
|
540
|
+
}
|
|
541
|
+
function shortStringInJS(length) {
|
|
542
|
+
if (length < 4) {
|
|
543
|
+
if (length < 2) {
|
|
544
|
+
if (length === 0)
|
|
545
|
+
return ''
|
|
546
|
+
else {
|
|
547
|
+
let a = src[position++];
|
|
548
|
+
if ((a & 0x80) > 1) {
|
|
549
|
+
position -= 1;
|
|
550
|
+
return
|
|
551
|
+
}
|
|
552
|
+
return fromCharCode(a)
|
|
553
|
+
}
|
|
554
|
+
} else {
|
|
555
|
+
let a = src[position++];
|
|
556
|
+
let b = src[position++];
|
|
557
|
+
if ((a & 0x80) > 0 || (b & 0x80) > 0) {
|
|
558
|
+
position -= 2;
|
|
559
|
+
return
|
|
560
|
+
}
|
|
561
|
+
if (length < 3)
|
|
562
|
+
return fromCharCode(a, b)
|
|
563
|
+
let c = src[position++];
|
|
564
|
+
if ((c & 0x80) > 0) {
|
|
565
|
+
position -= 3;
|
|
566
|
+
return
|
|
567
|
+
}
|
|
568
|
+
return fromCharCode(a, b, c)
|
|
569
|
+
}
|
|
570
|
+
} else {
|
|
571
|
+
let a = src[position++];
|
|
572
|
+
let b = src[position++];
|
|
573
|
+
let c = src[position++];
|
|
574
|
+
let d = src[position++];
|
|
575
|
+
if ((a & 0x80) > 0 || (b & 0x80) > 0 || (c & 0x80) > 0 || (d & 0x80) > 0) {
|
|
576
|
+
position -= 4;
|
|
577
|
+
return
|
|
578
|
+
}
|
|
579
|
+
if (length < 6) {
|
|
580
|
+
if (length === 4)
|
|
581
|
+
return fromCharCode(a, b, c, d)
|
|
582
|
+
else {
|
|
583
|
+
let e = src[position++];
|
|
584
|
+
if ((e & 0x80) > 0) {
|
|
585
|
+
position -= 5;
|
|
586
|
+
return
|
|
587
|
+
}
|
|
588
|
+
return fromCharCode(a, b, c, d, e)
|
|
589
|
+
}
|
|
590
|
+
} else if (length < 8) {
|
|
591
|
+
let e = src[position++];
|
|
592
|
+
let f = src[position++];
|
|
593
|
+
if ((e & 0x80) > 0 || (f & 0x80) > 0) {
|
|
594
|
+
position -= 6;
|
|
595
|
+
return
|
|
596
|
+
}
|
|
597
|
+
if (length < 7)
|
|
598
|
+
return fromCharCode(a, b, c, d, e, f)
|
|
599
|
+
let g = src[position++];
|
|
600
|
+
if ((g & 0x80) > 0) {
|
|
601
|
+
position -= 7;
|
|
602
|
+
return
|
|
603
|
+
}
|
|
604
|
+
return fromCharCode(a, b, c, d, e, f, g)
|
|
605
|
+
} else {
|
|
606
|
+
let e = src[position++];
|
|
607
|
+
let f = src[position++];
|
|
608
|
+
let g = src[position++];
|
|
609
|
+
let h = src[position++];
|
|
610
|
+
if ((e & 0x80) > 0 || (f & 0x80) > 0 || (g & 0x80) > 0 || (h & 0x80) > 0) {
|
|
611
|
+
position -= 8;
|
|
612
|
+
return
|
|
613
|
+
}
|
|
614
|
+
if (length < 10) {
|
|
615
|
+
if (length === 8)
|
|
616
|
+
return fromCharCode(a, b, c, d, e, f, g, h)
|
|
617
|
+
else {
|
|
618
|
+
let i = src[position++];
|
|
619
|
+
if ((i & 0x80) > 0) {
|
|
620
|
+
position -= 9;
|
|
621
|
+
return
|
|
622
|
+
}
|
|
623
|
+
return fromCharCode(a, b, c, d, e, f, g, h, i)
|
|
624
|
+
}
|
|
625
|
+
} else if (length < 12) {
|
|
626
|
+
let i = src[position++];
|
|
627
|
+
let j = src[position++];
|
|
628
|
+
if ((i & 0x80) > 0 || (j & 0x80) > 0) {
|
|
629
|
+
position -= 10;
|
|
630
|
+
return
|
|
631
|
+
}
|
|
632
|
+
if (length < 11)
|
|
633
|
+
return fromCharCode(a, b, c, d, e, f, g, h, i, j)
|
|
634
|
+
let k = src[position++];
|
|
635
|
+
if ((k & 0x80) > 0) {
|
|
636
|
+
position -= 11;
|
|
637
|
+
return
|
|
638
|
+
}
|
|
639
|
+
return fromCharCode(a, b, c, d, e, f, g, h, i, j, k)
|
|
640
|
+
} else {
|
|
641
|
+
let i = src[position++];
|
|
642
|
+
let j = src[position++];
|
|
643
|
+
let k = src[position++];
|
|
644
|
+
let l = src[position++];
|
|
645
|
+
if ((i & 0x80) > 0 || (j & 0x80) > 0 || (k & 0x80) > 0 || (l & 0x80) > 0) {
|
|
646
|
+
position -= 12;
|
|
647
|
+
return
|
|
648
|
+
}
|
|
649
|
+
if (length < 14) {
|
|
650
|
+
if (length === 12)
|
|
651
|
+
return fromCharCode(a, b, c, d, e, f, g, h, i, j, k, l)
|
|
652
|
+
else {
|
|
653
|
+
let m = src[position++];
|
|
654
|
+
if ((m & 0x80) > 0) {
|
|
655
|
+
position -= 13;
|
|
656
|
+
return
|
|
657
|
+
}
|
|
658
|
+
return fromCharCode(a, b, c, d, e, f, g, h, i, j, k, l, m)
|
|
659
|
+
}
|
|
660
|
+
} else {
|
|
661
|
+
let m = src[position++];
|
|
662
|
+
let n = src[position++];
|
|
663
|
+
if ((m & 0x80) > 0 || (n & 0x80) > 0) {
|
|
664
|
+
position -= 14;
|
|
665
|
+
return
|
|
666
|
+
}
|
|
667
|
+
if (length < 15)
|
|
668
|
+
return fromCharCode(a, b, c, d, e, f, g, h, i, j, k, l, m, n)
|
|
669
|
+
let o = src[position++];
|
|
670
|
+
if ((o & 0x80) > 0) {
|
|
671
|
+
position -= 15;
|
|
672
|
+
return
|
|
673
|
+
}
|
|
674
|
+
return fromCharCode(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o)
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
function readBin(length) {
|
|
682
|
+
return currentDecoder.copyBuffers ?
|
|
683
|
+
// specifically use the copying slice (not the node one)
|
|
684
|
+
Uint8Array.prototype.slice.call(src, position, position += length) :
|
|
685
|
+
src.subarray(position, position += length)
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
function getFloat16() {
|
|
689
|
+
let byte0 = src[position++];
|
|
690
|
+
let byte1 = src[position++];
|
|
691
|
+
let half = (byte0 << 8) + byte1;
|
|
692
|
+
let exp = (half >> 10) & 0x1f;
|
|
693
|
+
let mant = half & 0x3ff;
|
|
694
|
+
let val;
|
|
695
|
+
if (exp == 0) val = Math.exp(mant, -24);
|
|
696
|
+
else if (exp != 31) val = Math.exp(mant + 1024, exp - 25);
|
|
697
|
+
else val = mant == 0 ? Infinity : NaN;
|
|
698
|
+
return half & 0x8000 ? -val : val
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
let keyCache = new Array(4096);
|
|
702
|
+
|
|
703
|
+
class Tag {
|
|
704
|
+
constructor(value, tag) {
|
|
705
|
+
this.value = value;
|
|
706
|
+
this.tag = tag;
|
|
707
|
+
}
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
let glbl = typeof self == 'object' ? self : global;
|
|
711
|
+
|
|
712
|
+
currentExtensions[0] = (dateString) => {
|
|
713
|
+
// string date extension
|
|
714
|
+
return new Date(dateString)
|
|
715
|
+
};
|
|
716
|
+
|
|
717
|
+
currentExtensions[1] = (epochSec) => {
|
|
718
|
+
// numeric date extension
|
|
719
|
+
return new Date(Math.round(epochSec * 1000))
|
|
720
|
+
};
|
|
721
|
+
|
|
722
|
+
currentExtensions[2] = (buffer) => {
|
|
723
|
+
// bigint extension
|
|
724
|
+
let value = BigInt(0);
|
|
725
|
+
for (let i = 0, l = buffer.byteLength; i < l; i++) {
|
|
726
|
+
value = BigInt(buffer[i]) + value << BigInt(8);
|
|
727
|
+
}
|
|
728
|
+
return value
|
|
729
|
+
};
|
|
730
|
+
|
|
731
|
+
currentExtensions[3] = (buffer) => {
|
|
732
|
+
// negative bigint extension
|
|
733
|
+
return BigInt(-1) - currentExtensions[2](buffer)
|
|
734
|
+
};
|
|
735
|
+
currentExtensions[4] = (fraction) => {
|
|
736
|
+
// best to reparse to maintain accuracy
|
|
737
|
+
return +(fraction[1] + 'e' + fraction[0])
|
|
738
|
+
};
|
|
739
|
+
|
|
740
|
+
currentExtensions[5] = (fraction) => {
|
|
741
|
+
// probably not sufficiently accurate
|
|
742
|
+
return fraction[1] * Math.exp(fraction[0] * Math.log(2))
|
|
743
|
+
};
|
|
744
|
+
|
|
745
|
+
// the registration of the record definition extension
|
|
746
|
+
const recordDefinition = (definition) => {
|
|
747
|
+
let id = definition[0] - 0xe000;
|
|
748
|
+
let structure = definition[1];
|
|
749
|
+
let existingStructure = currentStructures[id];
|
|
750
|
+
if (existingStructure && existingStructure.isShared) {
|
|
751
|
+
(currentStructures.restoreStructures || (currentStructures.restoreStructures = []))[id] = existingStructure;
|
|
752
|
+
}
|
|
753
|
+
currentStructures[id] = structure;
|
|
754
|
+
|
|
755
|
+
structure.read = createStructureReader(structure);
|
|
756
|
+
let object = {};
|
|
757
|
+
if (currentDecoder.keyMap) for (let i = 2,l = definition.length; i < l; i++) {
|
|
758
|
+
let key = currentDecoder.decodeKey(structure[i - 2]);
|
|
759
|
+
object[key] = definition[i];
|
|
760
|
+
}
|
|
761
|
+
else for (let i = 2,l = definition.length; i < l; i++) {
|
|
762
|
+
let key = structure[i - 2];
|
|
763
|
+
object[key] = definition[i];
|
|
764
|
+
}
|
|
765
|
+
return object
|
|
766
|
+
};
|
|
767
|
+
currentExtensions[LEGACY_RECORD_INLINE_ID] = recordDefinition;
|
|
768
|
+
currentExtensions[14] = (value) => {
|
|
769
|
+
if (bundledStrings)
|
|
770
|
+
return bundledStrings[0].slice(bundledStrings.position0, bundledStrings.position0 += value)
|
|
771
|
+
return new Tag(value, 14)
|
|
772
|
+
};
|
|
773
|
+
currentExtensions[15] = (value) => {
|
|
774
|
+
if (bundledStrings)
|
|
775
|
+
return bundledStrings[1].slice(bundledStrings.position1, bundledStrings.position1 += value)
|
|
776
|
+
return new Tag(value, 15)
|
|
777
|
+
};
|
|
778
|
+
|
|
779
|
+
currentExtensions[27] = (data) => { // http://cbor.schmorp.de/generic-object
|
|
780
|
+
return (glbl[data[0]] || Error)(data[1], data[2])
|
|
781
|
+
};
|
|
782
|
+
const packedTable = (read) => {
|
|
783
|
+
if (src[position++] != 0x84)
|
|
784
|
+
throw new Error('Packed values structure must be followed by a 4 element array')
|
|
785
|
+
let newPackedValues = read(); // packed values
|
|
786
|
+
packedValues = packedValues ? newPackedValues.concat(packedValues.slice(newPackedValues.length)) : newPackedValues;
|
|
787
|
+
packedValues.prefixes = read();
|
|
788
|
+
packedValues.suffixes = read();
|
|
789
|
+
return read() // read the rump
|
|
790
|
+
};
|
|
791
|
+
packedTable.handlesRead = true;
|
|
792
|
+
currentExtensions[51] = packedTable;
|
|
793
|
+
|
|
794
|
+
currentExtensions[PACKED_REFERENCE_TAG_ID] = (data) => { // packed reference
|
|
795
|
+
if (!packedValues) {
|
|
796
|
+
if (currentDecoder.getShared)
|
|
797
|
+
loadShared();
|
|
798
|
+
else
|
|
799
|
+
return new Tag(data, PACKED_REFERENCE_TAG_ID)
|
|
800
|
+
}
|
|
801
|
+
if (typeof data == 'number')
|
|
802
|
+
return packedValues[16 + (data >= 0 ? 2 * data : (-2 * data - 1))]
|
|
803
|
+
throw new Error('No support for non-integer packed references yet')
|
|
804
|
+
};
|
|
805
|
+
currentExtensions[25] = (id) => {
|
|
806
|
+
return stringRefs[id]
|
|
807
|
+
};
|
|
808
|
+
currentExtensions[256] = (read) => {
|
|
809
|
+
stringRefs = [];
|
|
810
|
+
try {
|
|
811
|
+
return read()
|
|
812
|
+
} finally {
|
|
813
|
+
stringRefs = null;
|
|
814
|
+
}
|
|
815
|
+
};
|
|
816
|
+
currentExtensions[256].handlesRead = true;
|
|
817
|
+
|
|
818
|
+
currentExtensions[28] = (read) => {
|
|
819
|
+
// shareable http://cbor.schmorp.de/value-sharing (for structured clones)
|
|
820
|
+
if (!referenceMap) {
|
|
821
|
+
referenceMap = new Map();
|
|
822
|
+
referenceMap.id = 0;
|
|
823
|
+
}
|
|
824
|
+
let id = referenceMap.id++;
|
|
825
|
+
let token = src[position];
|
|
826
|
+
let target;
|
|
827
|
+
// TODO: handle Maps, Sets, and other types that can cycle; this is complicated, because you potentially need to read
|
|
828
|
+
// ahead past references to record structure definitions
|
|
829
|
+
if ((token >> 5) == 4)
|
|
830
|
+
target = [];
|
|
831
|
+
else
|
|
832
|
+
target = {};
|
|
833
|
+
|
|
834
|
+
let refEntry = { target }; // a placeholder object
|
|
835
|
+
referenceMap.set(id, refEntry);
|
|
836
|
+
let targetProperties = read(); // read the next value as the target object to id
|
|
837
|
+
if (refEntry.used) // there is a cycle, so we have to assign properties to original target
|
|
838
|
+
return Object.assign(target, targetProperties)
|
|
839
|
+
refEntry.target = targetProperties; // the placeholder wasn't used, replace with the deserialized one
|
|
840
|
+
return targetProperties // no cycle, can just use the returned read object
|
|
841
|
+
};
|
|
842
|
+
currentExtensions[28].handlesRead = true;
|
|
843
|
+
|
|
844
|
+
currentExtensions[29] = (id) => {
|
|
845
|
+
// sharedref http://cbor.schmorp.de/value-sharing (for structured clones)
|
|
846
|
+
let refEntry = referenceMap.get(id);
|
|
847
|
+
refEntry.used = true;
|
|
848
|
+
return refEntry.target
|
|
849
|
+
};
|
|
850
|
+
|
|
851
|
+
currentExtensions[258] = (array) => new Set(array); // https://github.com/input-output-hk/cbor-sets-spec/blob/master/CBOR_SETS.md
|
|
852
|
+
(currentExtensions[259] = (read) => {
|
|
853
|
+
// https://github.com/shanewholloway/js-cbor-codec/blob/master/docs/CBOR-259-spec
|
|
854
|
+
// for decoding as a standard Map
|
|
855
|
+
if (currentDecoder.mapsAsObjects) {
|
|
856
|
+
currentDecoder.mapsAsObjects = false;
|
|
857
|
+
restoreMapsAsObject = true;
|
|
858
|
+
}
|
|
859
|
+
return read()
|
|
860
|
+
}).handlesRead = true;
|
|
861
|
+
function combine(a, b) {
|
|
862
|
+
if (typeof a === 'string')
|
|
863
|
+
return a + b
|
|
864
|
+
if (a instanceof Array)
|
|
865
|
+
return a.concat(b)
|
|
866
|
+
return Object.assign({}, a, b)
|
|
867
|
+
}
|
|
868
|
+
function getPackedValues() {
|
|
869
|
+
if (!packedValues) {
|
|
870
|
+
if (currentDecoder.getShared)
|
|
871
|
+
loadShared();
|
|
872
|
+
else
|
|
873
|
+
throw new Error('No packed values available')
|
|
874
|
+
}
|
|
875
|
+
return packedValues
|
|
876
|
+
}
|
|
877
|
+
const SHARED_DATA_TAG_ID = 0x53687264; // ascii 'Shrd'
|
|
878
|
+
currentExtensionRanges.push((tag, input) => {
|
|
879
|
+
if (tag >= 225 && tag <= 255)
|
|
880
|
+
return combine(getPackedValues().prefixes[tag - 224], input)
|
|
881
|
+
if (tag >= 28704 && tag <= 32767)
|
|
882
|
+
return combine(getPackedValues().prefixes[tag - 28672], input)
|
|
883
|
+
if (tag >= 1879052288 && tag <= 2147483647)
|
|
884
|
+
return combine(getPackedValues().prefixes[tag - 1879048192], input)
|
|
885
|
+
if (tag >= 216 && tag <= 223)
|
|
886
|
+
return combine(input, getPackedValues().suffixes[tag - 216])
|
|
887
|
+
if (tag >= 27647 && tag <= 28671)
|
|
888
|
+
return combine(input, getPackedValues().suffixes[tag - 27639])
|
|
889
|
+
if (tag >= 1811940352 && tag <= 1879048191)
|
|
890
|
+
return combine(input, getPackedValues().suffixes[tag - 1811939328])
|
|
891
|
+
if (tag == SHARED_DATA_TAG_ID) {// we do a special check for this so that we can keep the currentExtensions as densely stored array (v8 stores arrays densely under about 3000 elements)
|
|
892
|
+
return {
|
|
893
|
+
packedValues: packedValues,
|
|
894
|
+
structures: currentStructures.slice(0),
|
|
895
|
+
version: input,
|
|
896
|
+
}
|
|
897
|
+
}
|
|
898
|
+
if (tag == 55799) // self-descriptive CBOR tag, just return input value
|
|
899
|
+
return input
|
|
900
|
+
});
|
|
901
|
+
|
|
902
|
+
const isLittleEndianMachine = new Uint8Array(new Uint16Array([1]).buffer)[0] == 1;
|
|
903
|
+
const typedArrays = ['Uint8', 'Uint8Clamped', 'Uint16', 'Uint32', 'BigUint64','Int8', 'Int16', 'Int32', 'BigInt64', 'Float32', 'Float64'];
|
|
904
|
+
const typedArrayTags = [64, 68, 69, 70, 71, 72, 77, 78, 79, 85, 86];
|
|
905
|
+
for (let i = 0; i < typedArrays.length; i++) {
|
|
906
|
+
registerTypedArray(typedArrays[i], typedArrayTags[i]);
|
|
907
|
+
}
|
|
908
|
+
function registerTypedArray(typedArrayId, tag, littleEndian) {
|
|
909
|
+
let TypedArray = glbl[typedArrayId + 'Array'];
|
|
910
|
+
let bytesPerElement = TypedArray.BYTES_PER_ELEMENT;
|
|
911
|
+
for (let littleEndian = 0; littleEndian < 2; littleEndian++) {
|
|
912
|
+
if (!littleEndian && bytesPerElement == 1)
|
|
913
|
+
continue
|
|
914
|
+
let sizeShift = bytesPerElement == 2 ? 1 : bytesPerElement == 4 ? 2 : 3;
|
|
915
|
+
currentExtensions[littleEndian ? tag : (tag - 4)] = (bytesPerElement == 1 || littleEndian == isLittleEndianMachine) ? (buffer) => {
|
|
916
|
+
if (!TypedArray)
|
|
917
|
+
throw new Error('Could not find typed array for code ' + tag)
|
|
918
|
+
// we have to always slice/copy here to get a new ArrayBuffer that is word/byte aligned
|
|
919
|
+
return new TypedArray(Uint8Array.prototype.slice.call(buffer, 0).buffer)
|
|
920
|
+
} : buffer => {
|
|
921
|
+
if (!TypedArray)
|
|
922
|
+
throw new Error('Could not find typed array for code ' + tag)
|
|
923
|
+
let dv = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);
|
|
924
|
+
let elements = buffer.length >> sizeShift;
|
|
925
|
+
let ta = new TypedArray(elements);
|
|
926
|
+
let method = dv['get' + typedArrayId];
|
|
927
|
+
for (let i = 0; i < elements; i++) {
|
|
928
|
+
ta[i] = method.call(dv, i << sizeShift, littleEndian);
|
|
929
|
+
}
|
|
930
|
+
return ta
|
|
931
|
+
};
|
|
932
|
+
}
|
|
933
|
+
}
|
|
934
|
+
|
|
935
|
+
function readBundleExt() {
|
|
936
|
+
let length = readJustLength();
|
|
937
|
+
let bundlePosition = position + read();
|
|
938
|
+
for (let i = 2; i < length; i++) {
|
|
939
|
+
// skip past bundles that were already read
|
|
940
|
+
let bundleLength = readJustLength(); // this will increment position, so must add to position afterwards
|
|
941
|
+
position += bundleLength;
|
|
942
|
+
}
|
|
943
|
+
let dataPosition = position;
|
|
944
|
+
position = bundlePosition;
|
|
945
|
+
bundledStrings = [readStringJS(readJustLength()), readStringJS(readJustLength())];
|
|
946
|
+
bundledStrings.position0 = 0;
|
|
947
|
+
bundledStrings.position1 = 0;
|
|
948
|
+
bundledStrings.postBundlePosition = position;
|
|
949
|
+
position = dataPosition;
|
|
950
|
+
return read()
|
|
951
|
+
}
|
|
952
|
+
|
|
953
|
+
function readJustLength() {
|
|
954
|
+
let token = src[position++] & 0x1f;
|
|
955
|
+
if (token > 0x17) {
|
|
956
|
+
switch (token) {
|
|
957
|
+
case 0x18:
|
|
958
|
+
token = src[position++];
|
|
959
|
+
break
|
|
960
|
+
case 0x19:
|
|
961
|
+
token = dataView.getUint16(position);
|
|
962
|
+
position += 2;
|
|
963
|
+
break
|
|
964
|
+
case 0x1a:
|
|
965
|
+
token = dataView.getUint32(position);
|
|
966
|
+
position += 4;
|
|
967
|
+
break
|
|
968
|
+
}
|
|
969
|
+
}
|
|
970
|
+
return token
|
|
971
|
+
}
|
|
972
|
+
|
|
973
|
+
function loadShared() {
|
|
974
|
+
if (currentDecoder.getShared) {
|
|
975
|
+
let sharedData = saveState(() => {
|
|
976
|
+
// save the state in case getShared modifies our buffer
|
|
977
|
+
src = null;
|
|
978
|
+
return currentDecoder.getShared()
|
|
979
|
+
}) || {};
|
|
980
|
+
let updatedStructures = sharedData.structures || [];
|
|
981
|
+
currentDecoder.sharedVersion = sharedData.version;
|
|
982
|
+
packedValues = currentDecoder.sharedValues = sharedData.packedValues;
|
|
983
|
+
if (currentStructures === true)
|
|
984
|
+
currentDecoder.structures = currentStructures = updatedStructures;
|
|
985
|
+
else
|
|
986
|
+
currentStructures.splice.apply(currentStructures, [0, updatedStructures.length].concat(updatedStructures));
|
|
987
|
+
}
|
|
988
|
+
}
|
|
989
|
+
|
|
990
|
+
function saveState(callback) {
|
|
991
|
+
let savedSrcEnd = srcEnd;
|
|
992
|
+
let savedPosition = position;
|
|
993
|
+
let savedSrcStringStart = srcStringStart;
|
|
994
|
+
let savedSrcStringEnd = srcStringEnd;
|
|
995
|
+
let savedSrcString = srcString;
|
|
996
|
+
let savedReferenceMap = referenceMap;
|
|
997
|
+
let savedBundledStrings = bundledStrings;
|
|
998
|
+
|
|
999
|
+
// TODO: We may need to revisit this if we do more external calls to user code (since it could be slow)
|
|
1000
|
+
let savedSrc = new Uint8Array(src.slice(0, srcEnd)); // we copy the data in case it changes while external data is processed
|
|
1001
|
+
let savedStructures = currentStructures;
|
|
1002
|
+
let savedDecoder = currentDecoder;
|
|
1003
|
+
let savedSequentialMode = sequentialMode;
|
|
1004
|
+
let value = callback();
|
|
1005
|
+
srcEnd = savedSrcEnd;
|
|
1006
|
+
position = savedPosition;
|
|
1007
|
+
srcStringStart = savedSrcStringStart;
|
|
1008
|
+
srcStringEnd = savedSrcStringEnd;
|
|
1009
|
+
srcString = savedSrcString;
|
|
1010
|
+
referenceMap = savedReferenceMap;
|
|
1011
|
+
bundledStrings = savedBundledStrings;
|
|
1012
|
+
src = savedSrc;
|
|
1013
|
+
sequentialMode = savedSequentialMode;
|
|
1014
|
+
currentStructures = savedStructures;
|
|
1015
|
+
currentDecoder = savedDecoder;
|
|
1016
|
+
dataView = new DataView(src.buffer, src.byteOffset, src.byteLength);
|
|
1017
|
+
return value
|
|
1018
|
+
}
|
|
1019
|
+
function clearSource() {
|
|
1020
|
+
src = null;
|
|
1021
|
+
referenceMap = null;
|
|
1022
|
+
currentStructures = null;
|
|
1023
|
+
}
|
|
1024
|
+
|
|
1025
|
+
function addExtension(extension) {
|
|
1026
|
+
currentExtensions[extension.tag] = extension.decode;
|
|
1027
|
+
}
|
|
1028
|
+
|
|
1029
|
+
const mult10 = new Array(147); // this is a table matching binary exponents to the multiplier to determine significant digit rounding
|
|
1030
|
+
for (let i = 0; i < 256; i++) {
|
|
1031
|
+
mult10[i] = +('1e' + Math.floor(45.15 - i * 0.30103));
|
|
1032
|
+
}
|
|
1033
|
+
let defaultDecoder = new Decoder({ useRecords: false });
|
|
1034
|
+
const decode = defaultDecoder.decode;
|
|
1035
|
+
const decodeMultiple = defaultDecoder.decodeMultiple;
|
|
1036
|
+
const FLOAT32_OPTIONS = {
|
|
1037
|
+
NEVER: 0,
|
|
1038
|
+
ALWAYS: 1,
|
|
1039
|
+
DECIMAL_ROUND: 3,
|
|
1040
|
+
DECIMAL_FIT: 4
|
|
1041
|
+
};
|
|
1042
|
+
let f32Array = new Float32Array(1);
|
|
1043
|
+
let u8Array = new Uint8Array(f32Array.buffer, 0, 4);
|
|
1044
|
+
function roundFloat32(float32Number) {
|
|
1045
|
+
f32Array[0] = float32Number;
|
|
1046
|
+
let multiplier = mult10[((u8Array[3] & 0x7f) << 1) | (u8Array[2] >> 7)];
|
|
1047
|
+
return ((multiplier * float32Number + (float32Number > 0 ? 0.5 : -0.5)) >> 0) / multiplier
|
|
1041
1048
|
}
|
|
1042
1049
|
|
|
1043
1050
|
let textEncoder;
|