msgpackr 1.6.1 → 1.6.2

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/unpack.js CHANGED
@@ -1,1053 +1,1061 @@
1
- "use strict"
2
- var decoder
3
- try {
4
- decoder = new TextDecoder()
5
- } catch(error) {}
6
- var src
7
- var srcEnd
8
- var position = 0
9
- var alreadySet
10
- const EMPTY_ARRAY = []
11
- var strings = EMPTY_ARRAY
12
- var stringPosition = 0
13
- var currentUnpackr = {}
14
- var currentStructures
15
- var srcString
16
- var srcStringStart = 0
17
- var srcStringEnd = 0
18
- var bundledStrings
19
- var referenceMap
20
- var currentExtensions = []
21
- var dataView
22
- var defaultOptions = {
23
- useRecords: false,
24
- mapsAsObjects: true
25
- }
26
- export class C1Type {}
27
- export const C1 = new C1Type()
28
- C1.name = 'MessagePack 0xC1'
29
- var sequentialMode = false
30
- var inlineObjectReadThreshold = 2
31
- try {
32
- new Function('')
33
- } catch(error) {
34
- // if eval variants are not supported, do not create inline object readers ever
35
- inlineObjectReadThreshold = Infinity
36
- }
37
-
38
- export class Unpackr {
39
- constructor(options) {
40
- if (options) {
41
- if (options.useRecords === false && options.mapsAsObjects === undefined)
42
- options.mapsAsObjects = true
43
- if (options.structures)
44
- options.structures.sharedLength = options.structures.length
45
- else if (options.getStructures) {
46
- (options.structures = []).uninitialized = true // this is what we use to denote an uninitialized structures
47
- options.structures.sharedLength = 0
48
- }
49
- }
50
- Object.assign(this, options)
51
- }
52
- unpack(source, end) {
53
- if (src) {
54
- // re-entrant execution, save the state and restore it after we do this unpack
55
- return saveState(() => {
56
- clearSource()
57
- return this ? this.unpack(source, end) : Unpackr.prototype.unpack.call(defaultOptions, source, end)
58
- })
59
- }
60
- srcEnd = end > -1 ? end : source.length
61
- position = 0
62
- stringPosition = 0
63
- srcStringEnd = 0
64
- srcString = null
65
- strings = EMPTY_ARRAY
66
- bundledStrings = null
67
- src = source
68
- // this provides cached access to the data view for a buffer if it is getting reused, which is a recommend
69
- // technique for getting data from a database where it can be copied into an existing buffer instead of creating
70
- // new ones
71
- try {
72
- dataView = source.dataView || (source.dataView = new DataView(source.buffer, source.byteOffset, source.byteLength))
73
- } catch(error) {
74
- // if it doesn't have a buffer, maybe it is the wrong type of object
75
- src = null
76
- if (source instanceof Uint8Array)
77
- throw error
78
- throw new Error('Source must be a Uint8Array or Buffer but was a ' + ((source && typeof source == 'object') ? source.constructor.name : typeof source))
79
- }
80
- if (this instanceof Unpackr) {
81
- currentUnpackr = this
82
- if (this.structures) {
83
- currentStructures = this.structures
84
- return checkedRead()
85
- } else if (!currentStructures || currentStructures.length > 0) {
86
- currentStructures = []
87
- }
88
- } else {
89
- currentUnpackr = defaultOptions
90
- if (!currentStructures || currentStructures.length > 0)
91
- currentStructures = []
92
- }
93
- return checkedRead()
94
- }
95
- unpackMultiple(source, forEach) {
96
- let values, lastPosition = 0
97
- try {
98
- sequentialMode = true
99
- let size = source.length
100
- let value = this ? this.unpack(source, size) : defaultUnpackr.unpack(source, size)
101
- if (forEach) {
102
- forEach(value)
103
- while(position < size) {
104
- lastPosition = position
105
- if (forEach(checkedRead()) === false) {
106
- return
107
- }
108
- }
109
- }
110
- else {
111
- values = [ value ]
112
- while(position < size) {
113
- lastPosition = position
114
- values.push(checkedRead())
115
- }
116
- return values
117
- }
118
- } catch(error) {
119
- error.lastPosition = lastPosition
120
- error.values = values
121
- throw error
122
- } finally {
123
- sequentialMode = false
124
- clearSource()
125
- }
126
- }
127
- _mergeStructures(loadedStructures, existingStructures) {
128
- loadedStructures = loadedStructures || []
129
- for (let i = 0, l = loadedStructures.length; i < l; i++) {
130
- let structure = loadedStructures[i]
131
- if (structure) {
132
- structure.isShared = true
133
- if (i >= 32)
134
- structure.highByte = (i - 32) >> 5
135
- }
136
- }
137
- loadedStructures.sharedLength = loadedStructures.length
138
- for (let id in existingStructures || []) {
139
- if (id >= 0) {
140
- let structure = loadedStructures[id]
141
- let existing = existingStructures[id]
142
- if (existing) {
143
- if (structure)
144
- (loadedStructures.restoreStructures || (loadedStructures.restoreStructures = []))[id] = structure
145
- loadedStructures[id] = existing
146
- }
147
- }
148
- }
149
- return this.structures = loadedStructures
150
- }
151
- decode(source, end) {
152
- return this.unpack(source, end)
153
- }
154
- }
155
- export function getPosition() {
156
- return position
157
- }
158
- export function checkedRead() {
159
- try {
160
- if (!currentUnpackr.trusted && !sequentialMode) {
161
- let sharedLength = currentStructures.sharedLength || 0
162
- if (sharedLength < currentStructures.length)
163
- currentStructures.length = sharedLength
164
- }
165
- let result = read()
166
- if (bundledStrings) // bundled strings to skip past
167
- position = bundledStrings.postBundlePosition
168
-
169
- if (position == srcEnd) {
170
- // finished reading this source, cleanup references
171
- if (currentStructures.restoreStructures)
172
- restoreStructures()
173
- currentStructures = null
174
- src = null
175
- if (referenceMap)
176
- referenceMap = null
177
- } else if (position > srcEnd) {
178
- // over read
179
- throw new Error('Unexpected end of MessagePack data')
180
- } else if (!sequentialMode) {
181
- throw new Error('Data read, but end of buffer not reached ' + JSON.stringify(result).slice(0, 100))
182
- }
183
- // else more to read, but we are reading sequentially, so don't clear source yet
184
- return result
185
- } catch(error) {
186
- if (currentStructures.restoreStructures)
187
- restoreStructures()
188
- clearSource()
189
- if (error instanceof RangeError || error.message.startsWith('Unexpected end of buffer') || position > srcEnd) {
190
- error.incomplete = true
191
- }
192
- throw error
193
- }
194
- }
195
-
196
- function restoreStructures() {
197
- for (let id in currentStructures.restoreStructures) {
198
- currentStructures[id] = currentStructures.restoreStructures[id]
199
- }
200
- currentStructures.restoreStructures = null
201
- }
202
-
203
- export function read() {
204
- let token = src[position++]
205
- if (token < 0xa0) {
206
- if (token < 0x80) {
207
- if (token < 0x40)
208
- return token
209
- else {
210
- let structure = currentStructures[token & 0x3f] ||
211
- currentUnpackr.getStructures && loadStructures()[token & 0x3f]
212
- if (structure) {
213
- if (!structure.read) {
214
- structure.read = createStructureReader(structure, token & 0x3f)
215
- }
216
- return structure.read()
217
- } else
218
- return token
219
- }
220
- } else if (token < 0x90) {
221
- // map
222
- token -= 0x80
223
- if (currentUnpackr.mapsAsObjects) {
224
- let object = {}
225
- for (let i = 0; i < token; i++) {
226
- object[readKey()] = read()
227
- }
228
- return object
229
- } else {
230
- let map = new Map()
231
- for (let i = 0; i < token; i++) {
232
- map.set(read(), read())
233
- }
234
- return map
235
- }
236
- } else {
237
- token -= 0x90
238
- let array = new Array(token)
239
- for (let i = 0; i < token; i++) {
240
- array[i] = read()
241
- }
242
- return array
243
- }
244
- } else if (token < 0xc0) {
245
- // fixstr
246
- let length = token - 0xa0
247
- if (srcStringEnd >= position) {
248
- return srcString.slice(position - srcStringStart, (position += length) - srcStringStart)
249
- }
250
- if (srcStringEnd == 0 && srcEnd < 140) {
251
- // for small blocks, avoiding the overhead of the extract call is helpful
252
- let string = length < 16 ? shortStringInJS(length) : longStringInJS(length)
253
- if (string != null)
254
- return string
255
- }
256
- return readFixedString(length)
257
- } else {
258
- let value
259
- switch (token) {
260
- case 0xc0: return null
261
- case 0xc1:
262
- if (bundledStrings) {
263
- value = read() // followed by the length of the string in characters (not bytes!)
264
- if (value > 0)
265
- return bundledStrings[1].slice(bundledStrings.position1, bundledStrings.position1 += value)
266
- else
267
- return bundledStrings[0].slice(bundledStrings.position0, bundledStrings.position0 -= value)
268
- }
269
- return C1; // "never-used", return special object to denote that
270
- case 0xc2: return false
271
- case 0xc3: return true
272
- case 0xc4:
273
- // bin 8
274
- value = src[position++]
275
- if (value === undefined)
276
- throw new Error('Unexpected end of buffer')
277
- return readBin(value)
278
- case 0xc5:
279
- // bin 16
280
- value = dataView.getUint16(position)
281
- position += 2
282
- return readBin(value)
283
- case 0xc6:
284
- // bin 32
285
- value = dataView.getUint32(position)
286
- position += 4
287
- return readBin(value)
288
- case 0xc7:
289
- // ext 8
290
- return readExt(src[position++])
291
- case 0xc8:
292
- // ext 16
293
- value = dataView.getUint16(position)
294
- position += 2
295
- return readExt(value)
296
- case 0xc9:
297
- // ext 32
298
- value = dataView.getUint32(position)
299
- position += 4
300
- return readExt(value)
301
- case 0xca:
302
- value = dataView.getFloat32(position)
303
- if (currentUnpackr.useFloat32 > 2) {
304
- // this does rounding of numbers that were encoded in 32-bit float to nearest significant decimal digit that could be preserved
305
- let multiplier = mult10[((src[position] & 0x7f) << 1) | (src[position + 1] >> 7)]
306
- position += 4
307
- return ((multiplier * value + (value > 0 ? 0.5 : -0.5)) >> 0) / multiplier
308
- }
309
- position += 4
310
- return value
311
- case 0xcb:
312
- value = dataView.getFloat64(position)
313
- position += 8
314
- return value
315
- // uint handlers
316
- case 0xcc:
317
- return src[position++]
318
- case 0xcd:
319
- value = dataView.getUint16(position)
320
- position += 2
321
- return value
322
- case 0xce:
323
- value = dataView.getUint32(position)
324
- position += 4
325
- return value
326
- case 0xcf:
327
- if (currentUnpackr.int64AsNumber) {
328
- value = dataView.getUint32(position) * 0x100000000
329
- value += dataView.getUint32(position + 4)
330
- } else
331
- value = dataView.getBigUint64(position)
332
- position += 8
333
- return value
334
-
335
- // int handlers
336
- case 0xd0:
337
- return dataView.getInt8(position++)
338
- case 0xd1:
339
- value = dataView.getInt16(position)
340
- position += 2
341
- return value
342
- case 0xd2:
343
- value = dataView.getInt32(position)
344
- position += 4
345
- return value
346
- case 0xd3:
347
- if (currentUnpackr.int64AsNumber) {
348
- value = dataView.getInt32(position) * 0x100000000
349
- value += dataView.getUint32(position + 4)
350
- } else
351
- value = dataView.getBigInt64(position)
352
- position += 8
353
- return value
354
-
355
- case 0xd4:
356
- // fixext 1
357
- value = src[position++]
358
- if (value == 0x72) {
359
- return recordDefinition(src[position++] & 0x3f)
360
- } else {
361
- let extension = currentExtensions[value]
362
- if (extension) {
363
- if (extension.read) {
364
- position++ // skip filler byte
365
- return extension.read(read())
366
- } else if (extension.noBuffer) {
367
- position++ // skip filler byte
368
- return extension()
369
- } else
370
- return extension(src.subarray(position, ++position))
371
- } else
372
- throw new Error('Unknown extension ' + value)
373
- }
374
- case 0xd5:
375
- // fixext 2
376
- value = src[position]
377
- if (value == 0x72) {
378
- position++
379
- return recordDefinition(src[position++] & 0x3f, src[position++])
380
- } else
381
- return readExt(2)
382
- case 0xd6:
383
- // fixext 4
384
- return readExt(4)
385
- case 0xd7:
386
- // fixext 8
387
- return readExt(8)
388
- case 0xd8:
389
- // fixext 16
390
- return readExt(16)
391
- case 0xd9:
392
- // str 8
393
- value = src[position++]
394
- if (srcStringEnd >= position) {
395
- return srcString.slice(position - srcStringStart, (position += value) - srcStringStart)
396
- }
397
- return readString8(value)
398
- case 0xda:
399
- // str 16
400
- value = dataView.getUint16(position)
401
- position += 2
402
- if (srcStringEnd >= position) {
403
- return srcString.slice(position - srcStringStart, (position += value) - srcStringStart)
404
- }
405
- return readString16(value)
406
- case 0xdb:
407
- // str 32
408
- value = dataView.getUint32(position)
409
- position += 4
410
- if (srcStringEnd >= position) {
411
- return srcString.slice(position - srcStringStart, (position += value) - srcStringStart)
412
- }
413
- return readString32(value)
414
- case 0xdc:
415
- // array 16
416
- value = dataView.getUint16(position)
417
- position += 2
418
- return readArray(value)
419
- case 0xdd:
420
- // array 32
421
- value = dataView.getUint32(position)
422
- position += 4
423
- return readArray(value)
424
- case 0xde:
425
- // map 16
426
- value = dataView.getUint16(position)
427
- position += 2
428
- return readMap(value)
429
- case 0xdf:
430
- // map 32
431
- value = dataView.getUint32(position)
432
- position += 4
433
- return readMap(value)
434
- default: // negative int
435
- if (token >= 0xe0)
436
- return token - 0x100
437
- if (token === undefined) {
438
- let error = new Error('Unexpected end of MessagePack data')
439
- error.incomplete = true
440
- throw error
441
- }
442
- throw new Error('Unknown MessagePack token ' + token)
443
-
444
- }
445
- }
446
- }
447
- const validName = /^[a-zA-Z_$][a-zA-Z\d_$]*$/
448
- function createStructureReader(structure, firstId) {
449
- function readObject() {
450
- // This initial function is quick to instantiate, but runs slower. After several iterations pay the cost to build the faster function
451
- if (readObject.count++ > inlineObjectReadThreshold) {
452
- let readObject = structure.read = (new Function('r', 'return function(){return {' + structure.map(key => validName.test(key) ? key + ':r()' : ('[' + JSON.stringify(key) + ']:r()')).join(',') + '}}'))(read)
453
- if (structure.highByte === 0)
454
- structure.read = createSecondByteReader(firstId, structure.read)
455
- return readObject() // second byte is already read, if there is one so immediately read object
456
- }
457
- let object = {}
458
- for (let i = 0, l = structure.length; i < l; i++) {
459
- let key = structure[i]
460
- object[key] = read()
461
- }
462
- return object
463
- }
464
- readObject.count = 0
465
- if (structure.highByte === 0) {
466
- return createSecondByteReader(firstId, readObject)
467
- }
468
- return readObject
469
- }
470
-
471
- const createSecondByteReader = (firstId, read0) => {
472
- return function() {
473
- let highByte = src[position++]
474
- if (highByte === 0)
475
- return read0()
476
- let id = firstId < 32 ? -(firstId + (highByte << 5)) : firstId + (highByte << 5)
477
- let structure = currentStructures[id] || loadStructures()[id]
478
- if (!structure) {
479
- throw new Error('Record id is not defined for ' + id)
480
- }
481
- if (!structure.read)
482
- structure.read = createStructureReader(structure, firstId)
483
- return structure.read()
484
- }
485
- }
486
-
487
- function loadStructures() {
488
- let loadedStructures = saveState(() => {
489
- // save the state in case getStructures modifies our buffer
490
- src = null
491
- return currentUnpackr.getStructures()
492
- })
493
- return currentStructures = currentUnpackr._mergeStructures(loadedStructures, currentStructures)
494
- }
495
-
496
- var readFixedString = readStringJS
497
- var readString8 = readStringJS
498
- var readString16 = readStringJS
499
- var readString32 = readStringJS
500
- export let isNativeAccelerationEnabled = false
501
-
502
- export function setExtractor(extractStrings) {
503
- isNativeAccelerationEnabled = true
504
- readFixedString = readString(1)
505
- readString8 = readString(2)
506
- readString16 = readString(3)
507
- readString32 = readString(5)
508
- function readString(headerLength) {
509
- return function readString(length) {
510
- let string = strings[stringPosition++]
511
- if (string == null) {
512
- if (bundledStrings)
513
- return readStringJS(length)
514
- let extraction = extractStrings(position - headerLength, srcEnd, src)
515
- if (typeof extraction == 'string') {
516
- string = extraction
517
- strings = EMPTY_ARRAY
518
- } else {
519
- strings = extraction
520
- stringPosition = 1
521
- 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
522
- string = strings[0]
523
- if (string === undefined)
524
- throw new Error('Unexpected end of buffer')
525
- }
526
- }
527
- let srcStringLength = string.length
528
- if (srcStringLength <= length) {
529
- position += length
530
- return string
531
- }
532
- srcString = string
533
- srcStringStart = position
534
- srcStringEnd = position + srcStringLength
535
- position += length
536
- return string.slice(0, length) // we know we just want the beginning
537
- }
538
- }
539
- }
540
- function readStringJS(length) {
541
- let result
542
- if (length < 16) {
543
- if (result = shortStringInJS(length))
544
- return result
545
- }
546
- if (length > 64 && decoder)
547
- return decoder.decode(src.subarray(position, position += length))
548
- const end = position + length
549
- const units = []
550
- result = ''
551
- while (position < end) {
552
- const byte1 = src[position++]
553
- if ((byte1 & 0x80) === 0) {
554
- // 1 byte
555
- units.push(byte1)
556
- } else if ((byte1 & 0xe0) === 0xc0) {
557
- // 2 bytes
558
- const byte2 = src[position++] & 0x3f
559
- units.push(((byte1 & 0x1f) << 6) | byte2)
560
- } else if ((byte1 & 0xf0) === 0xe0) {
561
- // 3 bytes
562
- const byte2 = src[position++] & 0x3f
563
- const byte3 = src[position++] & 0x3f
564
- units.push(((byte1 & 0x1f) << 12) | (byte2 << 6) | byte3)
565
- } else if ((byte1 & 0xf8) === 0xf0) {
566
- // 4 bytes
567
- const byte2 = src[position++] & 0x3f
568
- const byte3 = src[position++] & 0x3f
569
- const byte4 = src[position++] & 0x3f
570
- let unit = ((byte1 & 0x07) << 0x12) | (byte2 << 0x0c) | (byte3 << 0x06) | byte4
571
- if (unit > 0xffff) {
572
- unit -= 0x10000
573
- units.push(((unit >>> 10) & 0x3ff) | 0xd800)
574
- unit = 0xdc00 | (unit & 0x3ff)
575
- }
576
- units.push(unit)
577
- } else {
578
- units.push(byte1)
579
- }
580
-
581
- if (units.length >= 0x1000) {
582
- result += fromCharCode.apply(String, units)
583
- units.length = 0
584
- }
585
- }
586
-
587
- if (units.length > 0) {
588
- result += fromCharCode.apply(String, units)
589
- }
590
-
591
- return result
592
- }
593
-
594
- function readArray(length) {
595
- let array = new Array(length)
596
- for (let i = 0; i < length; i++) {
597
- array[i] = read()
598
- }
599
- return array
600
- }
601
-
602
- function readMap(length) {
603
- if (currentUnpackr.mapsAsObjects) {
604
- let object = {}
605
- for (let i = 0; i < length; i++) {
606
- object[readKey()] = read()
607
- }
608
- return object
609
- } else {
610
- let map = new Map()
611
- for (let i = 0; i < length; i++) {
612
- map.set(read(), read())
613
- }
614
- return map
615
- }
616
- }
617
-
618
- var fromCharCode = String.fromCharCode
619
- function longStringInJS(length) {
620
- let start = position
621
- let bytes = new Array(length)
622
- for (let i = 0; i < length; i++) {
623
- const byte = src[position++];
624
- if ((byte & 0x80) > 0) {
625
- position = start
626
- return
627
- }
628
- bytes[i] = byte
629
- }
630
- return fromCharCode.apply(String, bytes)
631
- }
632
- function shortStringInJS(length) {
633
- if (length < 4) {
634
- if (length < 2) {
635
- if (length === 0)
636
- return ''
637
- else {
638
- let a = src[position++]
639
- if ((a & 0x80) > 1) {
640
- position -= 1
641
- return
642
- }
643
- return fromCharCode(a)
644
- }
645
- } else {
646
- let a = src[position++]
647
- let b = src[position++]
648
- if ((a & 0x80) > 0 || (b & 0x80) > 0) {
649
- position -= 2
650
- return
651
- }
652
- if (length < 3)
653
- return fromCharCode(a, b)
654
- let c = src[position++]
655
- if ((c & 0x80) > 0) {
656
- position -= 3
657
- return
658
- }
659
- return fromCharCode(a, b, c)
660
- }
661
- } else {
662
- let a = src[position++]
663
- let b = src[position++]
664
- let c = src[position++]
665
- let d = src[position++]
666
- if ((a & 0x80) > 0 || (b & 0x80) > 0 || (c & 0x80) > 0 || (d & 0x80) > 0) {
667
- position -= 4
668
- return
669
- }
670
- if (length < 6) {
671
- if (length === 4)
672
- return fromCharCode(a, b, c, d)
673
- else {
674
- let e = src[position++]
675
- if ((e & 0x80) > 0) {
676
- position -= 5
677
- return
678
- }
679
- return fromCharCode(a, b, c, d, e)
680
- }
681
- } else if (length < 8) {
682
- let e = src[position++]
683
- let f = src[position++]
684
- if ((e & 0x80) > 0 || (f & 0x80) > 0) {
685
- position -= 6
686
- return
687
- }
688
- if (length < 7)
689
- return fromCharCode(a, b, c, d, e, f)
690
- let g = src[position++]
691
- if ((g & 0x80) > 0) {
692
- position -= 7
693
- return
694
- }
695
- return fromCharCode(a, b, c, d, e, f, g)
696
- } else {
697
- let e = src[position++]
698
- let f = src[position++]
699
- let g = src[position++]
700
- let h = src[position++]
701
- if ((e & 0x80) > 0 || (f & 0x80) > 0 || (g & 0x80) > 0 || (h & 0x80) > 0) {
702
- position -= 8
703
- return
704
- }
705
- if (length < 10) {
706
- if (length === 8)
707
- return fromCharCode(a, b, c, d, e, f, g, h)
708
- else {
709
- let i = src[position++]
710
- if ((i & 0x80) > 0) {
711
- position -= 9
712
- return
713
- }
714
- return fromCharCode(a, b, c, d, e, f, g, h, i)
715
- }
716
- } else if (length < 12) {
717
- let i = src[position++]
718
- let j = src[position++]
719
- if ((i & 0x80) > 0 || (j & 0x80) > 0) {
720
- position -= 10
721
- return
722
- }
723
- if (length < 11)
724
- return fromCharCode(a, b, c, d, e, f, g, h, i, j)
725
- let k = src[position++]
726
- if ((k & 0x80) > 0) {
727
- position -= 11
728
- return
729
- }
730
- return fromCharCode(a, b, c, d, e, f, g, h, i, j, k)
731
- } else {
732
- let i = src[position++]
733
- let j = src[position++]
734
- let k = src[position++]
735
- let l = src[position++]
736
- if ((i & 0x80) > 0 || (j & 0x80) > 0 || (k & 0x80) > 0 || (l & 0x80) > 0) {
737
- position -= 12
738
- return
739
- }
740
- if (length < 14) {
741
- if (length === 12)
742
- return fromCharCode(a, b, c, d, e, f, g, h, i, j, k, l)
743
- else {
744
- let m = src[position++]
745
- if ((m & 0x80) > 0) {
746
- position -= 13
747
- return
748
- }
749
- return fromCharCode(a, b, c, d, e, f, g, h, i, j, k, l, m)
750
- }
751
- } else {
752
- let m = src[position++]
753
- let n = src[position++]
754
- if ((m & 0x80) > 0 || (n & 0x80) > 0) {
755
- position -= 14
756
- return
757
- }
758
- if (length < 15)
759
- return fromCharCode(a, b, c, d, e, f, g, h, i, j, k, l, m, n)
760
- let o = src[position++]
761
- if ((o & 0x80) > 0) {
762
- position -= 15
763
- return
764
- }
765
- return fromCharCode(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o)
766
- }
767
- }
768
- }
769
- }
770
- }
771
-
772
- function readOnlyJSString() {
773
- let token = src[position++]
774
- let length
775
- if (token < 0xc0) {
776
- // fixstr
777
- length = token - 0xa0
778
- } else {
779
- switch(token) {
780
- case 0xd9:
781
- // str 8
782
- length = src[position++]
783
- break
784
- case 0xda:
785
- // str 16
786
- length = dataView.getUint16(position)
787
- position += 2
788
- break
789
- case 0xdb:
790
- // str 32
791
- length = dataView.getUint32(position)
792
- position += 4
793
- break
794
- default:
795
- throw new Error('Expected string')
796
- }
797
- }
798
- return readStringJS(length)
799
- }
800
-
801
-
802
- function readBin(length) {
803
- return currentUnpackr.copyBuffers ?
804
- // specifically use the copying slice (not the node one)
805
- Uint8Array.prototype.slice.call(src, position, position += length) :
806
- src.subarray(position, position += length)
807
- }
808
- function readExt(length) {
809
- let type = src[position++]
810
- if (currentExtensions[type]) {
811
- return currentExtensions[type](src.subarray(position, position += length))
812
- }
813
- else
814
- throw new Error('Unknown extension type ' + type)
815
- }
816
-
817
- var keyCache = new Array(4096)
818
- function readKey() {
819
- let length = src[position++]
820
- if (length >= 0xa0 && length < 0xc0) {
821
- // fixstr, potentially use key cache
822
- length = length - 0xa0
823
- if (srcStringEnd >= position) // if it has been extracted, must use it (and faster anyway)
824
- return srcString.slice(position - srcStringStart, (position += length) - srcStringStart)
825
- else if (!(srcStringEnd == 0 && srcEnd < 180))
826
- return readFixedString(length)
827
- } else { // not cacheable, go back and do a standard read
828
- position--
829
- return read()
830
- }
831
- let key = ((length << 5) ^ (length > 1 ? dataView.getUint16(position) : length > 0 ? src[position] : 0)) & 0xfff
832
- let entry = keyCache[key]
833
- let checkPosition = position
834
- let end = position + length - 3
835
- let chunk
836
- let i = 0
837
- if (entry && entry.bytes == length) {
838
- while (checkPosition < end) {
839
- chunk = dataView.getUint32(checkPosition)
840
- if (chunk != entry[i++]) {
841
- checkPosition = 0x70000000
842
- break
843
- }
844
- checkPosition += 4
845
- }
846
- end += 3
847
- while (checkPosition < end) {
848
- chunk = src[checkPosition++]
849
- if (chunk != entry[i++]) {
850
- checkPosition = 0x70000000
851
- break
852
- }
853
- }
854
- if (checkPosition === end) {
855
- position = checkPosition
856
- return entry.string
857
- }
858
- end -= 3
859
- checkPosition = position
860
- }
861
- entry = []
862
- keyCache[key] = entry
863
- entry.bytes = length
864
- while (checkPosition < end) {
865
- chunk = dataView.getUint32(checkPosition)
866
- entry.push(chunk)
867
- checkPosition += 4
868
- }
869
- end += 3
870
- while (checkPosition < end) {
871
- chunk = src[checkPosition++]
872
- entry.push(chunk)
873
- }
874
- // for small blocks, avoiding the overhead of the extract call is helpful
875
- let string = length < 16 ? shortStringInJS(length) : longStringInJS(length)
876
- if (string != null)
877
- return entry.string = string
878
- return entry.string = readFixedString(length)
879
- }
880
-
881
- // the registration of the record definition extension (as "r")
882
- const recordDefinition = (id, highByte) => {
883
- var structure = read()
884
- let firstByte = id
885
- if (highByte !== undefined) {
886
- id = id < 32 ? -((highByte << 5) + id) : ((highByte << 5) + id)
887
- structure.highByte = highByte
888
- }
889
- let existingStructure = currentStructures[id]
890
- if (existingStructure && existingStructure.isShared) {
891
- (currentStructures.restoreStructures || (currentStructures.restoreStructures = []))[id] = existingStructure
892
- }
893
- currentStructures[id] = structure
894
- structure.read = createStructureReader(structure, firstByte)
895
- return structure.read()
896
- }
897
- currentExtensions[0] = () => {} // notepack defines extension 0 to mean undefined, so use that as the default here
898
- currentExtensions[0].noBuffer = true
899
-
900
- currentExtensions[0x65] = () => {
901
- let data = read()
902
- return (globalThis[data[0]] || Error)(data[1])
903
- }
904
-
905
- currentExtensions[0x69] = (data) => {
906
- // id extension (for structured clones)
907
- let id = dataView.getUint32(position - 4)
908
- if (!referenceMap)
909
- referenceMap = new Map()
910
- let token = src[position]
911
- let target
912
- // TODO: handle Maps, Sets, and other types that can cycle; this is complicated, because you potentially need to read
913
- // ahead past references to record structure definitions
914
- if (token >= 0x90 && token < 0xa0 || token == 0xdc || token == 0xdd)
915
- target = []
916
- else
917
- target = {}
918
-
919
- let refEntry = { target } // a placeholder object
920
- referenceMap.set(id, refEntry)
921
- let targetProperties = read() // read the next value as the target object to id
922
- if (refEntry.used) // there is a cycle, so we have to assign properties to original target
923
- return Object.assign(target, targetProperties)
924
- refEntry.target = targetProperties // the placeholder wasn't used, replace with the deserialized one
925
- return targetProperties // no cycle, can just use the returned read object
926
- }
927
-
928
- currentExtensions[0x70] = (data) => {
929
- // pointer extension (for structured clones)
930
- let id = dataView.getUint32(position - 4)
931
- let refEntry = referenceMap.get(id)
932
- refEntry.used = true
933
- return refEntry.target
934
- }
935
-
936
- currentExtensions[0x73] = () => new Set(read())
937
-
938
- export const typedArrays = ['Int8','Uint8','Uint8Clamped','Int16','Uint16','Int32','Uint32','Float32','Float64','BigInt64','BigUint64'].map(type => type + 'Array')
939
-
940
- currentExtensions[0x74] = (data) => {
941
- let typeCode = data[0]
942
- let typedArrayName = typedArrays[typeCode]
943
- if (!typedArrayName)
944
- throw new Error('Could not find typed array for code ' + typeCode)
945
- // we have to always slice/copy here to get a new ArrayBuffer that is word/byte aligned
946
- return new globalThis[typedArrayName](Uint8Array.prototype.slice.call(data, 1).buffer)
947
- }
948
- currentExtensions[0x78] = () => {
949
- let data = read()
950
- return new RegExp(data[0], data[1])
951
- }
952
- const TEMP_BUNDLE = []
953
- currentExtensions[0x62] = (data) => {
954
- let dataSize = (data[0] << 24) + (data[1] << 16) + (data[2] << 8) + data[3]
955
- let dataPosition = position
956
- position += dataSize - data.length
957
- bundledStrings = TEMP_BUNDLE
958
- bundledStrings = [readOnlyJSString(), readOnlyJSString()]
959
- bundledStrings.position0 = 0
960
- bundledStrings.position1 = 0
961
- bundledStrings.postBundlePosition = position
962
- position = dataPosition
963
- return read()
964
- }
965
-
966
- currentExtensions[0xff] = (data) => {
967
- // 32-bit date extension
968
- if (data.length == 4)
969
- return new Date((data[0] * 0x1000000 + (data[1] << 16) + (data[2] << 8) + data[3]) * 1000)
970
- else if (data.length == 8)
971
- return new Date(
972
- ((data[0] << 22) + (data[1] << 14) + (data[2] << 6) + (data[3] >> 2)) / 1000000 +
973
- ((data[3] & 0x3) * 0x100000000 + data[4] * 0x1000000 + (data[5] << 16) + (data[6] << 8) + data[7]) * 1000)
974
- else if (data.length == 12)// TODO: Implement support for negative
975
- return new Date(
976
- ((data[0] << 24) + (data[1] << 16) + (data[2] << 8) + data[3]) / 1000000 +
977
- (((data[4] & 0x80) ? -0x1000000000000 : 0) + data[6] * 0x10000000000 + data[7] * 0x100000000 + data[8] * 0x1000000 + (data[9] << 16) + (data[10] << 8) + data[11]) * 1000)
978
- else
979
- return new Date('invalid')
980
- } // notepack defines extension 0 to mean undefined, so use that as the default here
981
- // registration of bulk record definition?
982
- // currentExtensions[0x52] = () =>
983
-
984
- function saveState(callback) {
985
- let savedSrcEnd = srcEnd
986
- let savedPosition = position
987
- let savedStringPosition = stringPosition
988
- let savedSrcStringStart = srcStringStart
989
- let savedSrcStringEnd = srcStringEnd
990
- let savedSrcString = srcString
991
- let savedStrings = strings
992
- let savedReferenceMap = referenceMap
993
- let savedBundledStrings = bundledStrings
994
-
995
- // TODO: We may need to revisit this if we do more external calls to user code (since it could be slow)
996
- let savedSrc = new Uint8Array(src.slice(0, srcEnd)) // we copy the data in case it changes while external data is processed
997
- let savedStructures = currentStructures
998
- let savedStructuresContents = currentStructures.slice(0, currentStructures.length)
999
- let savedPackr = currentUnpackr
1000
- let savedSequentialMode = sequentialMode
1001
- let value = callback()
1002
- srcEnd = savedSrcEnd
1003
- position = savedPosition
1004
- stringPosition = savedStringPosition
1005
- srcStringStart = savedSrcStringStart
1006
- srcStringEnd = savedSrcStringEnd
1007
- srcString = savedSrcString
1008
- strings = savedStrings
1009
- referenceMap = savedReferenceMap
1010
- bundledStrings = savedBundledStrings
1011
- src = savedSrc
1012
- sequentialMode = savedSequentialMode
1013
- currentStructures = savedStructures
1014
- currentStructures.splice(0, currentStructures.length, ...savedStructuresContents)
1015
- currentUnpackr = savedPackr
1016
- dataView = new DataView(src.buffer, src.byteOffset, src.byteLength)
1017
- return value
1018
- }
1019
- export function clearSource() {
1020
- src = null
1021
- referenceMap = null
1022
- currentStructures = null
1023
- }
1024
-
1025
- export function addExtension(extension) {
1026
- if (extension.unpack)
1027
- currentExtensions[extension.type] = extension.unpack
1028
- else
1029
- currentExtensions[extension.type] = extension
1030
- }
1031
-
1032
- export const mult10 = new Array(147) // this is a table matching binary exponents to the multiplier to determine significant digit rounding
1033
- for (let i = 0; i < 256; i++) {
1034
- mult10[i] = +('1e' + Math.floor(45.15 - i * 0.30103))
1035
- }
1036
- export const Decoder = Unpackr
1037
- var defaultUnpackr = new Unpackr({ useRecords: false })
1038
- export const unpack = defaultUnpackr.unpack
1039
- export const unpackMultiple = defaultUnpackr.unpackMultiple
1040
- export const decode = defaultUnpackr.unpack
1041
- export const FLOAT32_OPTIONS = {
1042
- NEVER: 0,
1043
- ALWAYS: 1,
1044
- DECIMAL_ROUND: 3,
1045
- DECIMAL_FIT: 4
1046
- }
1047
- let f32Array = new Float32Array(1)
1048
- let u8Array = new Uint8Array(f32Array.buffer, 0, 4)
1049
- export function roundFloat32(float32Number) {
1050
- f32Array[0] = float32Number
1051
- let multiplier = mult10[((u8Array[3] & 0x7f) << 1) | (u8Array[2] >> 7)]
1052
- return ((multiplier * float32Number + (float32Number > 0 ? 0.5 : -0.5)) >> 0) / multiplier
1053
- }
1
+ "use strict"
2
+ var decoder
3
+ try {
4
+ decoder = new TextDecoder()
5
+ } catch(error) {}
6
+ var src
7
+ var srcEnd
8
+ var position = 0
9
+ var alreadySet
10
+ const EMPTY_ARRAY = []
11
+ var strings = EMPTY_ARRAY
12
+ var stringPosition = 0
13
+ var currentUnpackr = {}
14
+ var currentStructures
15
+ var srcString
16
+ var srcStringStart = 0
17
+ var srcStringEnd = 0
18
+ var bundledStrings
19
+ var referenceMap
20
+ var currentExtensions = []
21
+ var dataView
22
+ var defaultOptions = {
23
+ useRecords: false,
24
+ mapsAsObjects: true
25
+ }
26
+ export class C1Type {}
27
+ export const C1 = new C1Type()
28
+ C1.name = 'MessagePack 0xC1'
29
+ var sequentialMode = false
30
+ var inlineObjectReadThreshold = 2
31
+ try {
32
+ new Function('')
33
+ } catch(error) {
34
+ // if eval variants are not supported, do not create inline object readers ever
35
+ inlineObjectReadThreshold = Infinity
36
+ }
37
+
38
+ export class Unpackr {
39
+ constructor(options) {
40
+ if (options) {
41
+ if (options.useRecords === false && options.mapsAsObjects === undefined)
42
+ options.mapsAsObjects = true
43
+ if (options.sequential && options.trusted !== false) {
44
+ options.trusted = true;
45
+ if (!options.structures && options.useRecords != false) {
46
+ options.structures = []
47
+ if (!options.maxSharedStructures)
48
+ options.maxSharedStructures = 0
49
+ }
50
+ }
51
+ if (options.structures)
52
+ options.structures.sharedLength = options.structures.length
53
+ else if (options.getStructures) {
54
+ (options.structures = []).uninitialized = true // this is what we use to denote an uninitialized structures
55
+ options.structures.sharedLength = 0
56
+ }
57
+ }
58
+ Object.assign(this, options)
59
+ }
60
+ unpack(source, end) {
61
+ if (src) {
62
+ // re-entrant execution, save the state and restore it after we do this unpack
63
+ return saveState(() => {
64
+ clearSource()
65
+ return this ? this.unpack(source, end) : Unpackr.prototype.unpack.call(defaultOptions, source, end)
66
+ })
67
+ }
68
+ srcEnd = end > -1 ? end : source.length
69
+ position = 0
70
+ stringPosition = 0
71
+ srcStringEnd = 0
72
+ srcString = null
73
+ strings = EMPTY_ARRAY
74
+ bundledStrings = null
75
+ src = source
76
+ // this provides cached access to the data view for a buffer if it is getting reused, which is a recommend
77
+ // technique for getting data from a database where it can be copied into an existing buffer instead of creating
78
+ // new ones
79
+ try {
80
+ dataView = source.dataView || (source.dataView = new DataView(source.buffer, source.byteOffset, source.byteLength))
81
+ } catch(error) {
82
+ // if it doesn't have a buffer, maybe it is the wrong type of object
83
+ src = null
84
+ if (source instanceof Uint8Array)
85
+ throw error
86
+ throw new Error('Source must be a Uint8Array or Buffer but was a ' + ((source && typeof source == 'object') ? source.constructor.name : typeof source))
87
+ }
88
+ if (this instanceof Unpackr) {
89
+ currentUnpackr = this
90
+ if (this.structures) {
91
+ currentStructures = this.structures
92
+ return checkedRead()
93
+ } else if (!currentStructures || currentStructures.length > 0) {
94
+ currentStructures = []
95
+ }
96
+ } else {
97
+ currentUnpackr = defaultOptions
98
+ if (!currentStructures || currentStructures.length > 0)
99
+ currentStructures = []
100
+ }
101
+ return checkedRead()
102
+ }
103
+ unpackMultiple(source, forEach) {
104
+ let values, lastPosition = 0
105
+ try {
106
+ sequentialMode = true
107
+ let size = source.length
108
+ let value = this ? this.unpack(source, size) : defaultUnpackr.unpack(source, size)
109
+ if (forEach) {
110
+ forEach(value)
111
+ while(position < size) {
112
+ lastPosition = position
113
+ if (forEach(checkedRead()) === false) {
114
+ return
115
+ }
116
+ }
117
+ }
118
+ else {
119
+ values = [ value ]
120
+ while(position < size) {
121
+ lastPosition = position
122
+ values.push(checkedRead())
123
+ }
124
+ return values
125
+ }
126
+ } catch(error) {
127
+ error.lastPosition = lastPosition
128
+ error.values = values
129
+ throw error
130
+ } finally {
131
+ sequentialMode = false
132
+ clearSource()
133
+ }
134
+ }
135
+ _mergeStructures(loadedStructures, existingStructures) {
136
+ loadedStructures = loadedStructures || []
137
+ for (let i = 0, l = loadedStructures.length; i < l; i++) {
138
+ let structure = loadedStructures[i]
139
+ if (structure) {
140
+ structure.isShared = true
141
+ if (i >= 32)
142
+ structure.highByte = (i - 32) >> 5
143
+ }
144
+ }
145
+ loadedStructures.sharedLength = loadedStructures.length
146
+ for (let id in existingStructures || []) {
147
+ if (id >= 0) {
148
+ let structure = loadedStructures[id]
149
+ let existing = existingStructures[id]
150
+ if (existing) {
151
+ if (structure)
152
+ (loadedStructures.restoreStructures || (loadedStructures.restoreStructures = []))[id] = structure
153
+ loadedStructures[id] = existing
154
+ }
155
+ }
156
+ }
157
+ return this.structures = loadedStructures
158
+ }
159
+ decode(source, end) {
160
+ return this.unpack(source, end)
161
+ }
162
+ }
163
+ export function getPosition() {
164
+ return position
165
+ }
166
+ export function checkedRead() {
167
+ try {
168
+ if (!currentUnpackr.trusted && !sequentialMode) {
169
+ let sharedLength = currentStructures.sharedLength || 0
170
+ if (sharedLength < currentStructures.length)
171
+ currentStructures.length = sharedLength
172
+ }
173
+ let result = read()
174
+ if (bundledStrings) // bundled strings to skip past
175
+ position = bundledStrings.postBundlePosition
176
+
177
+ if (position == srcEnd) {
178
+ // finished reading this source, cleanup references
179
+ if (currentStructures.restoreStructures)
180
+ restoreStructures()
181
+ currentStructures = null
182
+ src = null
183
+ if (referenceMap)
184
+ referenceMap = null
185
+ } else if (position > srcEnd) {
186
+ // over read
187
+ throw new Error('Unexpected end of MessagePack data')
188
+ } else if (!sequentialMode) {
189
+ throw new Error('Data read, but end of buffer not reached ' + JSON.stringify(result).slice(0, 100))
190
+ }
191
+ // else more to read, but we are reading sequentially, so don't clear source yet
192
+ return result
193
+ } catch(error) {
194
+ if (currentStructures.restoreStructures)
195
+ restoreStructures()
196
+ clearSource()
197
+ if (error instanceof RangeError || error.message.startsWith('Unexpected end of buffer') || position > srcEnd) {
198
+ error.incomplete = true
199
+ }
200
+ throw error
201
+ }
202
+ }
203
+
204
+ function restoreStructures() {
205
+ for (let id in currentStructures.restoreStructures) {
206
+ currentStructures[id] = currentStructures.restoreStructures[id]
207
+ }
208
+ currentStructures.restoreStructures = null
209
+ }
210
+
211
+ export function read() {
212
+ let token = src[position++]
213
+ if (token < 0xa0) {
214
+ if (token < 0x80) {
215
+ if (token < 0x40)
216
+ return token
217
+ else {
218
+ let structure = currentStructures[token & 0x3f] ||
219
+ currentUnpackr.getStructures && loadStructures()[token & 0x3f]
220
+ if (structure) {
221
+ if (!structure.read) {
222
+ structure.read = createStructureReader(structure, token & 0x3f)
223
+ }
224
+ return structure.read()
225
+ } else
226
+ return token
227
+ }
228
+ } else if (token < 0x90) {
229
+ // map
230
+ token -= 0x80
231
+ if (currentUnpackr.mapsAsObjects) {
232
+ let object = {}
233
+ for (let i = 0; i < token; i++) {
234
+ object[readKey()] = read()
235
+ }
236
+ return object
237
+ } else {
238
+ let map = new Map()
239
+ for (let i = 0; i < token; i++) {
240
+ map.set(read(), read())
241
+ }
242
+ return map
243
+ }
244
+ } else {
245
+ token -= 0x90
246
+ let array = new Array(token)
247
+ for (let i = 0; i < token; i++) {
248
+ array[i] = read()
249
+ }
250
+ return array
251
+ }
252
+ } else if (token < 0xc0) {
253
+ // fixstr
254
+ let length = token - 0xa0
255
+ if (srcStringEnd >= position) {
256
+ return srcString.slice(position - srcStringStart, (position += length) - srcStringStart)
257
+ }
258
+ if (srcStringEnd == 0 && srcEnd < 140) {
259
+ // for small blocks, avoiding the overhead of the extract call is helpful
260
+ let string = length < 16 ? shortStringInJS(length) : longStringInJS(length)
261
+ if (string != null)
262
+ return string
263
+ }
264
+ return readFixedString(length)
265
+ } else {
266
+ let value
267
+ switch (token) {
268
+ case 0xc0: return null
269
+ case 0xc1:
270
+ if (bundledStrings) {
271
+ value = read() // followed by the length of the string in characters (not bytes!)
272
+ if (value > 0)
273
+ return bundledStrings[1].slice(bundledStrings.position1, bundledStrings.position1 += value)
274
+ else
275
+ return bundledStrings[0].slice(bundledStrings.position0, bundledStrings.position0 -= value)
276
+ }
277
+ return C1; // "never-used", return special object to denote that
278
+ case 0xc2: return false
279
+ case 0xc3: return true
280
+ case 0xc4:
281
+ // bin 8
282
+ value = src[position++]
283
+ if (value === undefined)
284
+ throw new Error('Unexpected end of buffer')
285
+ return readBin(value)
286
+ case 0xc5:
287
+ // bin 16
288
+ value = dataView.getUint16(position)
289
+ position += 2
290
+ return readBin(value)
291
+ case 0xc6:
292
+ // bin 32
293
+ value = dataView.getUint32(position)
294
+ position += 4
295
+ return readBin(value)
296
+ case 0xc7:
297
+ // ext 8
298
+ return readExt(src[position++])
299
+ case 0xc8:
300
+ // ext 16
301
+ value = dataView.getUint16(position)
302
+ position += 2
303
+ return readExt(value)
304
+ case 0xc9:
305
+ // ext 32
306
+ value = dataView.getUint32(position)
307
+ position += 4
308
+ return readExt(value)
309
+ case 0xca:
310
+ value = dataView.getFloat32(position)
311
+ if (currentUnpackr.useFloat32 > 2) {
312
+ // this does rounding of numbers that were encoded in 32-bit float to nearest significant decimal digit that could be preserved
313
+ let multiplier = mult10[((src[position] & 0x7f) << 1) | (src[position + 1] >> 7)]
314
+ position += 4
315
+ return ((multiplier * value + (value > 0 ? 0.5 : -0.5)) >> 0) / multiplier
316
+ }
317
+ position += 4
318
+ return value
319
+ case 0xcb:
320
+ value = dataView.getFloat64(position)
321
+ position += 8
322
+ return value
323
+ // uint handlers
324
+ case 0xcc:
325
+ return src[position++]
326
+ case 0xcd:
327
+ value = dataView.getUint16(position)
328
+ position += 2
329
+ return value
330
+ case 0xce:
331
+ value = dataView.getUint32(position)
332
+ position += 4
333
+ return value
334
+ case 0xcf:
335
+ if (currentUnpackr.int64AsNumber) {
336
+ value = dataView.getUint32(position) * 0x100000000
337
+ value += dataView.getUint32(position + 4)
338
+ } else
339
+ value = dataView.getBigUint64(position)
340
+ position += 8
341
+ return value
342
+
343
+ // int handlers
344
+ case 0xd0:
345
+ return dataView.getInt8(position++)
346
+ case 0xd1:
347
+ value = dataView.getInt16(position)
348
+ position += 2
349
+ return value
350
+ case 0xd2:
351
+ value = dataView.getInt32(position)
352
+ position += 4
353
+ return value
354
+ case 0xd3:
355
+ if (currentUnpackr.int64AsNumber) {
356
+ value = dataView.getInt32(position) * 0x100000000
357
+ value += dataView.getUint32(position + 4)
358
+ } else
359
+ value = dataView.getBigInt64(position)
360
+ position += 8
361
+ return value
362
+
363
+ case 0xd4:
364
+ // fixext 1
365
+ value = src[position++]
366
+ if (value == 0x72) {
367
+ return recordDefinition(src[position++] & 0x3f)
368
+ } else {
369
+ let extension = currentExtensions[value]
370
+ if (extension) {
371
+ if (extension.read) {
372
+ position++ // skip filler byte
373
+ return extension.read(read())
374
+ } else if (extension.noBuffer) {
375
+ position++ // skip filler byte
376
+ return extension()
377
+ } else
378
+ return extension(src.subarray(position, ++position))
379
+ } else
380
+ throw new Error('Unknown extension ' + value)
381
+ }
382
+ case 0xd5:
383
+ // fixext 2
384
+ value = src[position]
385
+ if (value == 0x72) {
386
+ position++
387
+ return recordDefinition(src[position++] & 0x3f, src[position++])
388
+ } else
389
+ return readExt(2)
390
+ case 0xd6:
391
+ // fixext 4
392
+ return readExt(4)
393
+ case 0xd7:
394
+ // fixext 8
395
+ return readExt(8)
396
+ case 0xd8:
397
+ // fixext 16
398
+ return readExt(16)
399
+ case 0xd9:
400
+ // str 8
401
+ value = src[position++]
402
+ if (srcStringEnd >= position) {
403
+ return srcString.slice(position - srcStringStart, (position += value) - srcStringStart)
404
+ }
405
+ return readString8(value)
406
+ case 0xda:
407
+ // str 16
408
+ value = dataView.getUint16(position)
409
+ position += 2
410
+ if (srcStringEnd >= position) {
411
+ return srcString.slice(position - srcStringStart, (position += value) - srcStringStart)
412
+ }
413
+ return readString16(value)
414
+ case 0xdb:
415
+ // str 32
416
+ value = dataView.getUint32(position)
417
+ position += 4
418
+ if (srcStringEnd >= position) {
419
+ return srcString.slice(position - srcStringStart, (position += value) - srcStringStart)
420
+ }
421
+ return readString32(value)
422
+ case 0xdc:
423
+ // array 16
424
+ value = dataView.getUint16(position)
425
+ position += 2
426
+ return readArray(value)
427
+ case 0xdd:
428
+ // array 32
429
+ value = dataView.getUint32(position)
430
+ position += 4
431
+ return readArray(value)
432
+ case 0xde:
433
+ // map 16
434
+ value = dataView.getUint16(position)
435
+ position += 2
436
+ return readMap(value)
437
+ case 0xdf:
438
+ // map 32
439
+ value = dataView.getUint32(position)
440
+ position += 4
441
+ return readMap(value)
442
+ default: // negative int
443
+ if (token >= 0xe0)
444
+ return token - 0x100
445
+ if (token === undefined) {
446
+ let error = new Error('Unexpected end of MessagePack data')
447
+ error.incomplete = true
448
+ throw error
449
+ }
450
+ throw new Error('Unknown MessagePack token ' + token)
451
+
452
+ }
453
+ }
454
+ }
455
+ const validName = /^[a-zA-Z_$][a-zA-Z\d_$]*$/
456
+ function createStructureReader(structure, firstId) {
457
+ function readObject() {
458
+ // This initial function is quick to instantiate, but runs slower. After several iterations pay the cost to build the faster function
459
+ if (readObject.count++ > inlineObjectReadThreshold) {
460
+ let readObject = structure.read = (new Function('r', 'return function(){return {' + structure.map(key => validName.test(key) ? key + ':r()' : ('[' + JSON.stringify(key) + ']:r()')).join(',') + '}}'))(read)
461
+ if (structure.highByte === 0)
462
+ structure.read = createSecondByteReader(firstId, structure.read)
463
+ return readObject() // second byte is already read, if there is one so immediately read object
464
+ }
465
+ let object = {}
466
+ for (let i = 0, l = structure.length; i < l; i++) {
467
+ let key = structure[i]
468
+ object[key] = read()
469
+ }
470
+ return object
471
+ }
472
+ readObject.count = 0
473
+ if (structure.highByte === 0) {
474
+ return createSecondByteReader(firstId, readObject)
475
+ }
476
+ return readObject
477
+ }
478
+
479
+ const createSecondByteReader = (firstId, read0) => {
480
+ return function() {
481
+ let highByte = src[position++]
482
+ if (highByte === 0)
483
+ return read0()
484
+ let id = firstId < 32 ? -(firstId + (highByte << 5)) : firstId + (highByte << 5)
485
+ let structure = currentStructures[id] || loadStructures()[id]
486
+ if (!structure) {
487
+ throw new Error('Record id is not defined for ' + id)
488
+ }
489
+ if (!structure.read)
490
+ structure.read = createStructureReader(structure, firstId)
491
+ return structure.read()
492
+ }
493
+ }
494
+
495
+ function loadStructures() {
496
+ let loadedStructures = saveState(() => {
497
+ // save the state in case getStructures modifies our buffer
498
+ src = null
499
+ return currentUnpackr.getStructures()
500
+ })
501
+ return currentStructures = currentUnpackr._mergeStructures(loadedStructures, currentStructures)
502
+ }
503
+
504
+ var readFixedString = readStringJS
505
+ var readString8 = readStringJS
506
+ var readString16 = readStringJS
507
+ var readString32 = readStringJS
508
+ export let isNativeAccelerationEnabled = false
509
+
510
+ export function setExtractor(extractStrings) {
511
+ isNativeAccelerationEnabled = true
512
+ readFixedString = readString(1)
513
+ readString8 = readString(2)
514
+ readString16 = readString(3)
515
+ readString32 = readString(5)
516
+ function readString(headerLength) {
517
+ return function readString(length) {
518
+ let string = strings[stringPosition++]
519
+ if (string == null) {
520
+ if (bundledStrings)
521
+ return readStringJS(length)
522
+ let extraction = extractStrings(position - headerLength, srcEnd, src)
523
+ if (typeof extraction == 'string') {
524
+ string = extraction
525
+ strings = EMPTY_ARRAY
526
+ } else {
527
+ strings = extraction
528
+ stringPosition = 1
529
+ 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
530
+ string = strings[0]
531
+ if (string === undefined)
532
+ throw new Error('Unexpected end of buffer')
533
+ }
534
+ }
535
+ let srcStringLength = string.length
536
+ if (srcStringLength <= length) {
537
+ position += length
538
+ return string
539
+ }
540
+ srcString = string
541
+ srcStringStart = position
542
+ srcStringEnd = position + srcStringLength
543
+ position += length
544
+ return string.slice(0, length) // we know we just want the beginning
545
+ }
546
+ }
547
+ }
548
+ function readStringJS(length) {
549
+ let result
550
+ if (length < 16) {
551
+ if (result = shortStringInJS(length))
552
+ return result
553
+ }
554
+ if (length > 64 && decoder)
555
+ return decoder.decode(src.subarray(position, position += length))
556
+ const end = position + length
557
+ const units = []
558
+ result = ''
559
+ while (position < end) {
560
+ const byte1 = src[position++]
561
+ if ((byte1 & 0x80) === 0) {
562
+ // 1 byte
563
+ units.push(byte1)
564
+ } else if ((byte1 & 0xe0) === 0xc0) {
565
+ // 2 bytes
566
+ const byte2 = src[position++] & 0x3f
567
+ units.push(((byte1 & 0x1f) << 6) | byte2)
568
+ } else if ((byte1 & 0xf0) === 0xe0) {
569
+ // 3 bytes
570
+ const byte2 = src[position++] & 0x3f
571
+ const byte3 = src[position++] & 0x3f
572
+ units.push(((byte1 & 0x1f) << 12) | (byte2 << 6) | byte3)
573
+ } else if ((byte1 & 0xf8) === 0xf0) {
574
+ // 4 bytes
575
+ const byte2 = src[position++] & 0x3f
576
+ const byte3 = src[position++] & 0x3f
577
+ const byte4 = src[position++] & 0x3f
578
+ let unit = ((byte1 & 0x07) << 0x12) | (byte2 << 0x0c) | (byte3 << 0x06) | byte4
579
+ if (unit > 0xffff) {
580
+ unit -= 0x10000
581
+ units.push(((unit >>> 10) & 0x3ff) | 0xd800)
582
+ unit = 0xdc00 | (unit & 0x3ff)
583
+ }
584
+ units.push(unit)
585
+ } else {
586
+ units.push(byte1)
587
+ }
588
+
589
+ if (units.length >= 0x1000) {
590
+ result += fromCharCode.apply(String, units)
591
+ units.length = 0
592
+ }
593
+ }
594
+
595
+ if (units.length > 0) {
596
+ result += fromCharCode.apply(String, units)
597
+ }
598
+
599
+ return result
600
+ }
601
+
602
+ function readArray(length) {
603
+ let array = new Array(length)
604
+ for (let i = 0; i < length; i++) {
605
+ array[i] = read()
606
+ }
607
+ return array
608
+ }
609
+
610
+ function readMap(length) {
611
+ if (currentUnpackr.mapsAsObjects) {
612
+ let object = {}
613
+ for (let i = 0; i < length; i++) {
614
+ object[readKey()] = read()
615
+ }
616
+ return object
617
+ } else {
618
+ let map = new Map()
619
+ for (let i = 0; i < length; i++) {
620
+ map.set(read(), read())
621
+ }
622
+ return map
623
+ }
624
+ }
625
+
626
+ var fromCharCode = String.fromCharCode
627
+ function longStringInJS(length) {
628
+ let start = position
629
+ let bytes = new Array(length)
630
+ for (let i = 0; i < length; i++) {
631
+ const byte = src[position++];
632
+ if ((byte & 0x80) > 0) {
633
+ position = start
634
+ return
635
+ }
636
+ bytes[i] = byte
637
+ }
638
+ return fromCharCode.apply(String, bytes)
639
+ }
640
+ function shortStringInJS(length) {
641
+ if (length < 4) {
642
+ if (length < 2) {
643
+ if (length === 0)
644
+ return ''
645
+ else {
646
+ let a = src[position++]
647
+ if ((a & 0x80) > 1) {
648
+ position -= 1
649
+ return
650
+ }
651
+ return fromCharCode(a)
652
+ }
653
+ } else {
654
+ let a = src[position++]
655
+ let b = src[position++]
656
+ if ((a & 0x80) > 0 || (b & 0x80) > 0) {
657
+ position -= 2
658
+ return
659
+ }
660
+ if (length < 3)
661
+ return fromCharCode(a, b)
662
+ let c = src[position++]
663
+ if ((c & 0x80) > 0) {
664
+ position -= 3
665
+ return
666
+ }
667
+ return fromCharCode(a, b, c)
668
+ }
669
+ } else {
670
+ let a = src[position++]
671
+ let b = src[position++]
672
+ let c = src[position++]
673
+ let d = src[position++]
674
+ if ((a & 0x80) > 0 || (b & 0x80) > 0 || (c & 0x80) > 0 || (d & 0x80) > 0) {
675
+ position -= 4
676
+ return
677
+ }
678
+ if (length < 6) {
679
+ if (length === 4)
680
+ return fromCharCode(a, b, c, d)
681
+ else {
682
+ let e = src[position++]
683
+ if ((e & 0x80) > 0) {
684
+ position -= 5
685
+ return
686
+ }
687
+ return fromCharCode(a, b, c, d, e)
688
+ }
689
+ } else if (length < 8) {
690
+ let e = src[position++]
691
+ let f = src[position++]
692
+ if ((e & 0x80) > 0 || (f & 0x80) > 0) {
693
+ position -= 6
694
+ return
695
+ }
696
+ if (length < 7)
697
+ return fromCharCode(a, b, c, d, e, f)
698
+ let g = src[position++]
699
+ if ((g & 0x80) > 0) {
700
+ position -= 7
701
+ return
702
+ }
703
+ return fromCharCode(a, b, c, d, e, f, g)
704
+ } else {
705
+ let e = src[position++]
706
+ let f = src[position++]
707
+ let g = src[position++]
708
+ let h = src[position++]
709
+ if ((e & 0x80) > 0 || (f & 0x80) > 0 || (g & 0x80) > 0 || (h & 0x80) > 0) {
710
+ position -= 8
711
+ return
712
+ }
713
+ if (length < 10) {
714
+ if (length === 8)
715
+ return fromCharCode(a, b, c, d, e, f, g, h)
716
+ else {
717
+ let i = src[position++]
718
+ if ((i & 0x80) > 0) {
719
+ position -= 9
720
+ return
721
+ }
722
+ return fromCharCode(a, b, c, d, e, f, g, h, i)
723
+ }
724
+ } else if (length < 12) {
725
+ let i = src[position++]
726
+ let j = src[position++]
727
+ if ((i & 0x80) > 0 || (j & 0x80) > 0) {
728
+ position -= 10
729
+ return
730
+ }
731
+ if (length < 11)
732
+ return fromCharCode(a, b, c, d, e, f, g, h, i, j)
733
+ let k = src[position++]
734
+ if ((k & 0x80) > 0) {
735
+ position -= 11
736
+ return
737
+ }
738
+ return fromCharCode(a, b, c, d, e, f, g, h, i, j, k)
739
+ } else {
740
+ let i = src[position++]
741
+ let j = src[position++]
742
+ let k = src[position++]
743
+ let l = src[position++]
744
+ if ((i & 0x80) > 0 || (j & 0x80) > 0 || (k & 0x80) > 0 || (l & 0x80) > 0) {
745
+ position -= 12
746
+ return
747
+ }
748
+ if (length < 14) {
749
+ if (length === 12)
750
+ return fromCharCode(a, b, c, d, e, f, g, h, i, j, k, l)
751
+ else {
752
+ let m = src[position++]
753
+ if ((m & 0x80) > 0) {
754
+ position -= 13
755
+ return
756
+ }
757
+ return fromCharCode(a, b, c, d, e, f, g, h, i, j, k, l, m)
758
+ }
759
+ } else {
760
+ let m = src[position++]
761
+ let n = src[position++]
762
+ if ((m & 0x80) > 0 || (n & 0x80) > 0) {
763
+ position -= 14
764
+ return
765
+ }
766
+ if (length < 15)
767
+ return fromCharCode(a, b, c, d, e, f, g, h, i, j, k, l, m, n)
768
+ let o = src[position++]
769
+ if ((o & 0x80) > 0) {
770
+ position -= 15
771
+ return
772
+ }
773
+ return fromCharCode(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o)
774
+ }
775
+ }
776
+ }
777
+ }
778
+ }
779
+
780
+ function readOnlyJSString() {
781
+ let token = src[position++]
782
+ let length
783
+ if (token < 0xc0) {
784
+ // fixstr
785
+ length = token - 0xa0
786
+ } else {
787
+ switch(token) {
788
+ case 0xd9:
789
+ // str 8
790
+ length = src[position++]
791
+ break
792
+ case 0xda:
793
+ // str 16
794
+ length = dataView.getUint16(position)
795
+ position += 2
796
+ break
797
+ case 0xdb:
798
+ // str 32
799
+ length = dataView.getUint32(position)
800
+ position += 4
801
+ break
802
+ default:
803
+ throw new Error('Expected string')
804
+ }
805
+ }
806
+ return readStringJS(length)
807
+ }
808
+
809
+
810
+ function readBin(length) {
811
+ return currentUnpackr.copyBuffers ?
812
+ // specifically use the copying slice (not the node one)
813
+ Uint8Array.prototype.slice.call(src, position, position += length) :
814
+ src.subarray(position, position += length)
815
+ }
816
+ function readExt(length) {
817
+ let type = src[position++]
818
+ if (currentExtensions[type]) {
819
+ return currentExtensions[type](src.subarray(position, position += length))
820
+ }
821
+ else
822
+ throw new Error('Unknown extension type ' + type)
823
+ }
824
+
825
+ var keyCache = new Array(4096)
826
+ function readKey() {
827
+ let length = src[position++]
828
+ if (length >= 0xa0 && length < 0xc0) {
829
+ // fixstr, potentially use key cache
830
+ length = length - 0xa0
831
+ if (srcStringEnd >= position) // if it has been extracted, must use it (and faster anyway)
832
+ return srcString.slice(position - srcStringStart, (position += length) - srcStringStart)
833
+ else if (!(srcStringEnd == 0 && srcEnd < 180))
834
+ return readFixedString(length)
835
+ } else { // not cacheable, go back and do a standard read
836
+ position--
837
+ return read()
838
+ }
839
+ let key = ((length << 5) ^ (length > 1 ? dataView.getUint16(position) : length > 0 ? src[position] : 0)) & 0xfff
840
+ let entry = keyCache[key]
841
+ let checkPosition = position
842
+ let end = position + length - 3
843
+ let chunk
844
+ let i = 0
845
+ if (entry && entry.bytes == length) {
846
+ while (checkPosition < end) {
847
+ chunk = dataView.getUint32(checkPosition)
848
+ if (chunk != entry[i++]) {
849
+ checkPosition = 0x70000000
850
+ break
851
+ }
852
+ checkPosition += 4
853
+ }
854
+ end += 3
855
+ while (checkPosition < end) {
856
+ chunk = src[checkPosition++]
857
+ if (chunk != entry[i++]) {
858
+ checkPosition = 0x70000000
859
+ break
860
+ }
861
+ }
862
+ if (checkPosition === end) {
863
+ position = checkPosition
864
+ return entry.string
865
+ }
866
+ end -= 3
867
+ checkPosition = position
868
+ }
869
+ entry = []
870
+ keyCache[key] = entry
871
+ entry.bytes = length
872
+ while (checkPosition < end) {
873
+ chunk = dataView.getUint32(checkPosition)
874
+ entry.push(chunk)
875
+ checkPosition += 4
876
+ }
877
+ end += 3
878
+ while (checkPosition < end) {
879
+ chunk = src[checkPosition++]
880
+ entry.push(chunk)
881
+ }
882
+ // for small blocks, avoiding the overhead of the extract call is helpful
883
+ let string = length < 16 ? shortStringInJS(length) : longStringInJS(length)
884
+ if (string != null)
885
+ return entry.string = string
886
+ return entry.string = readFixedString(length)
887
+ }
888
+
889
+ // the registration of the record definition extension (as "r")
890
+ const recordDefinition = (id, highByte) => {
891
+ var structure = read()
892
+ let firstByte = id
893
+ if (highByte !== undefined) {
894
+ id = id < 32 ? -((highByte << 5) + id) : ((highByte << 5) + id)
895
+ structure.highByte = highByte
896
+ }
897
+ let existingStructure = currentStructures[id]
898
+ if (existingStructure && existingStructure.isShared) {
899
+ (currentStructures.restoreStructures || (currentStructures.restoreStructures = []))[id] = existingStructure
900
+ }
901
+ currentStructures[id] = structure
902
+ structure.read = createStructureReader(structure, firstByte)
903
+ return structure.read()
904
+ }
905
+ currentExtensions[0] = () => {} // notepack defines extension 0 to mean undefined, so use that as the default here
906
+ currentExtensions[0].noBuffer = true
907
+
908
+ currentExtensions[0x65] = () => {
909
+ let data = read()
910
+ return (globalThis[data[0]] || Error)(data[1])
911
+ }
912
+
913
+ currentExtensions[0x69] = (data) => {
914
+ // id extension (for structured clones)
915
+ let id = dataView.getUint32(position - 4)
916
+ if (!referenceMap)
917
+ referenceMap = new Map()
918
+ let token = src[position]
919
+ let target
920
+ // TODO: handle Maps, Sets, and other types that can cycle; this is complicated, because you potentially need to read
921
+ // ahead past references to record structure definitions
922
+ if (token >= 0x90 && token < 0xa0 || token == 0xdc || token == 0xdd)
923
+ target = []
924
+ else
925
+ target = {}
926
+
927
+ let refEntry = { target } // a placeholder object
928
+ referenceMap.set(id, refEntry)
929
+ let targetProperties = read() // read the next value as the target object to id
930
+ if (refEntry.used) // there is a cycle, so we have to assign properties to original target
931
+ return Object.assign(target, targetProperties)
932
+ refEntry.target = targetProperties // the placeholder wasn't used, replace with the deserialized one
933
+ return targetProperties // no cycle, can just use the returned read object
934
+ }
935
+
936
+ currentExtensions[0x70] = (data) => {
937
+ // pointer extension (for structured clones)
938
+ let id = dataView.getUint32(position - 4)
939
+ let refEntry = referenceMap.get(id)
940
+ refEntry.used = true
941
+ return refEntry.target
942
+ }
943
+
944
+ currentExtensions[0x73] = () => new Set(read())
945
+
946
+ export const typedArrays = ['Int8','Uint8','Uint8Clamped','Int16','Uint16','Int32','Uint32','Float32','Float64','BigInt64','BigUint64'].map(type => type + 'Array')
947
+
948
+ currentExtensions[0x74] = (data) => {
949
+ let typeCode = data[0]
950
+ let typedArrayName = typedArrays[typeCode]
951
+ if (!typedArrayName)
952
+ throw new Error('Could not find typed array for code ' + typeCode)
953
+ // we have to always slice/copy here to get a new ArrayBuffer that is word/byte aligned
954
+ return new globalThis[typedArrayName](Uint8Array.prototype.slice.call(data, 1).buffer)
955
+ }
956
+ currentExtensions[0x78] = () => {
957
+ let data = read()
958
+ return new RegExp(data[0], data[1])
959
+ }
960
+ const TEMP_BUNDLE = []
961
+ currentExtensions[0x62] = (data) => {
962
+ let dataSize = (data[0] << 24) + (data[1] << 16) + (data[2] << 8) + data[3]
963
+ let dataPosition = position
964
+ position += dataSize - data.length
965
+ bundledStrings = TEMP_BUNDLE
966
+ bundledStrings = [readOnlyJSString(), readOnlyJSString()]
967
+ bundledStrings.position0 = 0
968
+ bundledStrings.position1 = 0
969
+ bundledStrings.postBundlePosition = position
970
+ position = dataPosition
971
+ return read()
972
+ }
973
+
974
+ currentExtensions[0xff] = (data) => {
975
+ // 32-bit date extension
976
+ if (data.length == 4)
977
+ return new Date((data[0] * 0x1000000 + (data[1] << 16) + (data[2] << 8) + data[3]) * 1000)
978
+ else if (data.length == 8)
979
+ return new Date(
980
+ ((data[0] << 22) + (data[1] << 14) + (data[2] << 6) + (data[3] >> 2)) / 1000000 +
981
+ ((data[3] & 0x3) * 0x100000000 + data[4] * 0x1000000 + (data[5] << 16) + (data[6] << 8) + data[7]) * 1000)
982
+ else if (data.length == 12)// TODO: Implement support for negative
983
+ return new Date(
984
+ ((data[0] << 24) + (data[1] << 16) + (data[2] << 8) + data[3]) / 1000000 +
985
+ (((data[4] & 0x80) ? -0x1000000000000 : 0) + data[6] * 0x10000000000 + data[7] * 0x100000000 + data[8] * 0x1000000 + (data[9] << 16) + (data[10] << 8) + data[11]) * 1000)
986
+ else
987
+ return new Date('invalid')
988
+ } // notepack defines extension 0 to mean undefined, so use that as the default here
989
+ // registration of bulk record definition?
990
+ // currentExtensions[0x52] = () =>
991
+
992
+ function saveState(callback) {
993
+ let savedSrcEnd = srcEnd
994
+ let savedPosition = position
995
+ let savedStringPosition = stringPosition
996
+ let savedSrcStringStart = srcStringStart
997
+ let savedSrcStringEnd = srcStringEnd
998
+ let savedSrcString = srcString
999
+ let savedStrings = strings
1000
+ let savedReferenceMap = referenceMap
1001
+ let savedBundledStrings = bundledStrings
1002
+
1003
+ // TODO: We may need to revisit this if we do more external calls to user code (since it could be slow)
1004
+ let savedSrc = new Uint8Array(src.slice(0, srcEnd)) // we copy the data in case it changes while external data is processed
1005
+ let savedStructures = currentStructures
1006
+ let savedStructuresContents = currentStructures.slice(0, currentStructures.length)
1007
+ let savedPackr = currentUnpackr
1008
+ let savedSequentialMode = sequentialMode
1009
+ let value = callback()
1010
+ srcEnd = savedSrcEnd
1011
+ position = savedPosition
1012
+ stringPosition = savedStringPosition
1013
+ srcStringStart = savedSrcStringStart
1014
+ srcStringEnd = savedSrcStringEnd
1015
+ srcString = savedSrcString
1016
+ strings = savedStrings
1017
+ referenceMap = savedReferenceMap
1018
+ bundledStrings = savedBundledStrings
1019
+ src = savedSrc
1020
+ sequentialMode = savedSequentialMode
1021
+ currentStructures = savedStructures
1022
+ currentStructures.splice(0, currentStructures.length, ...savedStructuresContents)
1023
+ currentUnpackr = savedPackr
1024
+ dataView = new DataView(src.buffer, src.byteOffset, src.byteLength)
1025
+ return value
1026
+ }
1027
+ export function clearSource() {
1028
+ src = null
1029
+ referenceMap = null
1030
+ currentStructures = null
1031
+ }
1032
+
1033
+ export function addExtension(extension) {
1034
+ if (extension.unpack)
1035
+ currentExtensions[extension.type] = extension.unpack
1036
+ else
1037
+ currentExtensions[extension.type] = extension
1038
+ }
1039
+
1040
+ export const mult10 = new Array(147) // this is a table matching binary exponents to the multiplier to determine significant digit rounding
1041
+ for (let i = 0; i < 256; i++) {
1042
+ mult10[i] = +('1e' + Math.floor(45.15 - i * 0.30103))
1043
+ }
1044
+ export const Decoder = Unpackr
1045
+ var defaultUnpackr = new Unpackr({ useRecords: false })
1046
+ export const unpack = defaultUnpackr.unpack
1047
+ export const unpackMultiple = defaultUnpackr.unpackMultiple
1048
+ export const decode = defaultUnpackr.unpack
1049
+ export const FLOAT32_OPTIONS = {
1050
+ NEVER: 0,
1051
+ ALWAYS: 1,
1052
+ DECIMAL_ROUND: 3,
1053
+ DECIMAL_FIT: 4
1054
+ }
1055
+ let f32Array = new Float32Array(1)
1056
+ let u8Array = new Uint8Array(f32Array.buffer, 0, 4)
1057
+ export function roundFloat32(float32Number) {
1058
+ f32Array[0] = float32Number
1059
+ let multiplier = mult10[((u8Array[3] & 0x7f) << 1) | (u8Array[2] >> 7)]
1060
+ return ((multiplier * float32Number + (float32Number > 0 ? 0.5 : -0.5)) >> 0) / multiplier
1061
+ }