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