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