msgpackr 1.11.12 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -29,7 +29,6 @@
29
29
  C1.name = 'MessagePack 0xC1';
30
30
  var sequentialMode = false;
31
31
  var inlineObjectReadThreshold = 2;
32
- var readStruct;
33
32
 
34
33
  class Unpackr {
35
34
  constructor(options) {
@@ -61,8 +60,8 @@
61
60
  // re-entrant execution, save the state and restore it after we do this unpack
62
61
  return saveState(() => {
63
62
  clearSource();
64
- return this ? this.unpack(source, options) : Unpackr.prototype.unpack.call(defaultOptions, source, options)
65
- })
63
+ return this ? this.unpack(source, options) : Unpackr.prototype.unpack.call(defaultOptions, source, options);
64
+ });
66
65
  }
67
66
  if (!source.buffer && source.constructor === ArrayBuffer)
68
67
  source = typeof Buffer !== 'undefined' ? Buffer.from(source) : new Uint8Array(source);
@@ -86,14 +85,14 @@
86
85
  // if it doesn't have a buffer, maybe it is the wrong type of object
87
86
  src = null;
88
87
  if (source instanceof Uint8Array)
89
- throw error
90
- throw new Error('Source must be a Uint8Array or Buffer but was a ' + ((source && typeof source == 'object') ? source.constructor.name : typeof source))
88
+ throw error;
89
+ throw new Error('Source must be a Uint8Array or Buffer but was a ' + ((source && typeof source == 'object') ? source.constructor.name : typeof source));
91
90
  }
92
91
  if (this instanceof Unpackr) {
93
92
  currentUnpackr = this;
94
93
  if (this.structures) {
95
94
  currentStructures = this.structures;
96
- return checkedRead(options)
95
+ return checkedRead(options);
97
96
  } else if (!currentStructures || currentStructures.length > 0) {
98
97
  currentStructures = [];
99
98
  }
@@ -102,7 +101,7 @@
102
101
  if (!currentStructures || currentStructures.length > 0)
103
102
  currentStructures = [];
104
103
  }
105
- return checkedRead(options)
104
+ return checkedRead(options);
106
105
  }
107
106
  unpackMultiple(source, forEach) {
108
107
  let values, lastPosition = 0;
@@ -115,7 +114,7 @@
115
114
  while(position$1 < size) {
116
115
  lastPosition = position$1;
117
116
  if (forEach(checkedRead(), lastPosition, position$1) === false) {
118
- return
117
+ return;
119
118
  }
120
119
  }
121
120
  }
@@ -125,18 +124,20 @@
125
124
  lastPosition = position$1;
126
125
  values.push(checkedRead());
127
126
  }
128
- return values
127
+ return values;
129
128
  }
130
129
  } catch(error) {
131
130
  error.lastPosition = lastPosition;
132
131
  error.values = values;
133
- throw error
132
+ throw error;
134
133
  } finally {
135
134
  sequentialMode = false;
136
135
  clearSource();
137
136
  }
138
137
  }
139
138
  _mergeStructures(loadedStructures, existingStructures) {
139
+ if (this._onLoadedStructures)
140
+ loadedStructures = this._onLoadedStructures(loadedStructures);
140
141
  loadedStructures = loadedStructures || [];
141
142
  if (Object.isFrozen(loadedStructures))
142
143
  loadedStructures = loadedStructures.map(structure => structure.slice(0));
@@ -160,10 +161,10 @@
160
161
  }
161
162
  }
162
163
  }
163
- return this.structures = loadedStructures
164
+ return this.structures = loadedStructures;
164
165
  }
165
166
  decode(source, options) {
166
- return this.unpack(source, options)
167
+ return this.unpack(source, options);
167
168
  }
168
169
  }
169
170
  function checkedRead(options) {
@@ -174,8 +175,8 @@
174
175
  currentStructures.length = sharedLength;
175
176
  }
176
177
  let result;
177
- if (currentUnpackr.randomAccessStructure && src[position$1] < 0x40 && src[position$1] >= 0x20 && readStruct) {
178
- result = readStruct(src, position$1, srcEnd, currentUnpackr);
178
+ if (currentUnpackr._readStruct && src[position$1] < 0x40 && src[position$1] >= 0x20) {
179
+ result = currentUnpackr._readStruct(src, position$1, srcEnd);
179
180
  src = null; // dispose of this so that recursive unpack calls don't save state
180
181
  if (!(options && options.lazy) && result)
181
182
  result = result.toJSON();
@@ -201,7 +202,7 @@
201
202
  referenceMap = null;
202
203
  } else if (position$1 > srcEnd) {
203
204
  // over read
204
- throw new Error('Unexpected end of MessagePack data')
205
+ throw new Error('Unexpected end of MessagePack data');
205
206
  } else if (!sequentialMode) {
206
207
  let jsonView;
207
208
  try {
@@ -209,10 +210,10 @@
209
210
  } catch(error) {
210
211
  jsonView = '(JSON view not available ' + error + ')';
211
212
  }
212
- throw new Error('Data read, but end of buffer not reached ' + jsonView)
213
+ throw new Error('Data read, but end of buffer not reached ' + jsonView);
213
214
  }
214
215
  // else more to read, but we are reading sequentially, so don't clear source yet
215
- return result
216
+ return result;
216
217
  } catch(error) {
217
218
  if (currentStructures && currentStructures.restoreStructures)
218
219
  restoreStructures();
@@ -220,7 +221,7 @@
220
221
  if (error instanceof RangeError || error.message.startsWith('Unexpected end of buffer') || position$1 > srcEnd) {
221
222
  error.incomplete = true;
222
223
  }
223
- throw error
224
+ throw error;
224
225
  }
225
226
  }
226
227
 
@@ -236,7 +237,7 @@
236
237
  if (token < 0xa0) {
237
238
  if (token < 0x80) {
238
239
  if (token < 0x40)
239
- return token
240
+ return token;
240
241
  else {
241
242
  let structure = currentStructures[token & 0x3f] ||
242
243
  currentUnpackr.getStructures && loadStructures()[token & 0x3f];
@@ -244,9 +245,9 @@
244
245
  if (!structure.read) {
245
246
  structure.read = createStructureReader(structure, token & 0x3f);
246
247
  }
247
- return structure.read()
248
+ return structure.read();
248
249
  } else
249
- return token
250
+ return token;
250
251
  }
251
252
  } else if (token < 0x90) {
252
253
  // map
@@ -259,13 +260,13 @@
259
260
  key = '__proto_';
260
261
  object[key] = read();
261
262
  }
262
- return object
263
+ return object;
263
264
  } else {
264
265
  let map = new Map();
265
266
  for (let i = 0; i < token; i++) {
266
267
  map.set(read(), read());
267
268
  }
268
- return map
269
+ return map;
269
270
  }
270
271
  } else {
271
272
  token -= 0x90;
@@ -274,91 +275,91 @@
274
275
  array[i] = read();
275
276
  }
276
277
  if (currentUnpackr.freezeData)
277
- return Object.freeze(array)
278
- return array
278
+ return Object.freeze(array);
279
+ return array;
279
280
  }
280
281
  } else if (token < 0xc0) {
281
282
  // fixstr
282
283
  let length = token - 0xa0;
283
284
  if (srcStringEnd >= position$1) {
284
- return srcString.slice(position$1 - srcStringStart, (position$1 += length) - srcStringStart)
285
+ return srcString.slice(position$1 - srcStringStart, (position$1 += length) - srcStringStart);
285
286
  }
286
287
  if (srcStringEnd == 0 && srcEnd < 140) {
287
288
  // for small blocks, avoiding the overhead of the extract call is helpful
288
289
  let string = length < 16 ? shortStringInJS(length) : longStringInJS(length);
289
290
  if (string != null)
290
- return string
291
+ return string;
291
292
  }
292
- return readFixedString(length)
293
+ return readFixedString(length);
293
294
  } else {
294
295
  let value;
295
296
  switch (token) {
296
- case 0xc0: return null
297
+ case 0xc0: return null;
297
298
  case 0xc1:
298
299
  if (bundledStrings$1) {
299
300
  value = read(); // followed by the length of the string in characters (not bytes!)
300
301
  if (value > 0)
301
- return bundledStrings$1[1].slice(bundledStrings$1.position1, bundledStrings$1.position1 += value)
302
+ return bundledStrings$1[1].slice(bundledStrings$1.position1, bundledStrings$1.position1 += value);
302
303
  else
303
- return bundledStrings$1[0].slice(bundledStrings$1.position0, bundledStrings$1.position0 -= value)
304
+ return bundledStrings$1[0].slice(bundledStrings$1.position0, bundledStrings$1.position0 -= value);
304
305
  }
305
306
  return C1; // "never-used", return special object to denote that
306
- case 0xc2: return false
307
- case 0xc3: return true
307
+ case 0xc2: return false;
308
+ case 0xc3: return true;
308
309
  case 0xc4:
309
310
  // bin 8
310
311
  value = src[position$1++];
311
312
  if (value === undefined)
312
- throw new Error('Unexpected end of buffer')
313
- return readBin(value)
313
+ throw new Error('Unexpected end of buffer');
314
+ return readBin(value);
314
315
  case 0xc5:
315
316
  // bin 16
316
317
  value = dataView.getUint16(position$1);
317
318
  position$1 += 2;
318
- return readBin(value)
319
+ return readBin(value);
319
320
  case 0xc6:
320
321
  // bin 32
321
322
  value = dataView.getUint32(position$1);
322
323
  position$1 += 4;
323
- return readBin(value)
324
+ return readBin(value);
324
325
  case 0xc7:
325
326
  // ext 8
326
- return readExt(src[position$1++])
327
+ return readExt(src[position$1++]);
327
328
  case 0xc8:
328
329
  // ext 16
329
330
  value = dataView.getUint16(position$1);
330
331
  position$1 += 2;
331
- return readExt(value)
332
+ return readExt(value);
332
333
  case 0xc9:
333
334
  // ext 32
334
335
  value = dataView.getUint32(position$1);
335
336
  position$1 += 4;
336
- return readExt(value)
337
+ return readExt(value);
337
338
  case 0xca:
338
339
  value = dataView.getFloat32(position$1);
339
340
  if (currentUnpackr.useFloat32 > 2) {
340
341
  // this does rounding of numbers that were encoded in 32-bit float to nearest significant decimal digit that could be preserved
341
342
  let multiplier = mult10[((src[position$1] & 0x7f) << 1) | (src[position$1 + 1] >> 7)];
342
343
  position$1 += 4;
343
- return ((multiplier * value + (value > 0 ? 0.5 : -0.5)) >> 0) / multiplier
344
+ return ((multiplier * value + (value > 0 ? 0.5 : -0.5)) >> 0) / multiplier;
344
345
  }
345
346
  position$1 += 4;
346
- return value
347
+ return value;
347
348
  case 0xcb:
348
349
  value = dataView.getFloat64(position$1);
349
350
  position$1 += 8;
350
- return value
351
+ return value;
351
352
  // uint handlers
352
353
  case 0xcc:
353
- return src[position$1++]
354
+ return src[position$1++];
354
355
  case 0xcd:
355
356
  value = dataView.getUint16(position$1);
356
357
  position$1 += 2;
357
- return value
358
+ return value;
358
359
  case 0xce:
359
360
  value = dataView.getUint32(position$1);
360
361
  position$1 += 4;
361
- return value
362
+ return value;
362
363
  case 0xcf:
363
364
  if (currentUnpackr.int64AsType === 'number') {
364
365
  value = dataView.getUint32(position$1) * 0x100000000;
@@ -371,19 +372,19 @@
371
372
  } else
372
373
  value = dataView.getBigUint64(position$1);
373
374
  position$1 += 8;
374
- return value
375
+ return value;
375
376
 
376
377
  // int handlers
377
378
  case 0xd0:
378
- return dataView.getInt8(position$1++)
379
+ return dataView.getInt8(position$1++);
379
380
  case 0xd1:
380
381
  value = dataView.getInt16(position$1);
381
382
  position$1 += 2;
382
- return value
383
+ return value;
383
384
  case 0xd2:
384
385
  value = dataView.getInt32(position$1);
385
386
  position$1 += 4;
386
- return value
387
+ return value;
387
388
  case 0xd3:
388
389
  if (currentUnpackr.int64AsType === 'number') {
389
390
  value = dataView.getInt32(position$1) * 0x100000000;
@@ -396,96 +397,96 @@
396
397
  } else
397
398
  value = dataView.getBigInt64(position$1);
398
399
  position$1 += 8;
399
- return value
400
+ return value;
400
401
 
401
402
  case 0xd4:
402
403
  // fixext 1
403
404
  value = src[position$1++];
404
405
  if (value == 0x72) {
405
- return recordDefinition(src[position$1++] & 0x3f)
406
+ return recordDefinition(src[position$1++] & 0x3f);
406
407
  } else {
407
408
  let extension = currentExtensions[value];
408
409
  if (extension) {
409
410
  if (extension.read) {
410
411
  position$1++; // skip filler byte
411
- return extension.read(read())
412
+ return extension.read(read());
412
413
  } else if (extension.noBuffer) {
413
414
  position$1++; // skip filler byte
414
- return extension()
415
+ return extension();
415
416
  } else
416
- return extension(src.subarray(position$1, ++position$1))
417
+ return extension(src.subarray(position$1, ++position$1));
417
418
  } else
418
- throw new Error('Unknown extension ' + value)
419
+ throw new Error('Unknown extension ' + value);
419
420
  }
420
421
  case 0xd5:
421
422
  // fixext 2
422
423
  value = src[position$1];
423
424
  if (value == 0x72) {
424
425
  position$1++;
425
- return recordDefinition(src[position$1++] & 0x3f, src[position$1++])
426
+ return recordDefinition(src[position$1++] & 0x3f, src[position$1++]);
426
427
  } else
427
- return readExt(2)
428
+ return readExt(2);
428
429
  case 0xd6:
429
430
  // fixext 4
430
- return readExt(4)
431
+ return readExt(4);
431
432
  case 0xd7:
432
433
  // fixext 8
433
- return readExt(8)
434
+ return readExt(8);
434
435
  case 0xd8:
435
436
  // fixext 16
436
- return readExt(16)
437
+ return readExt(16);
437
438
  case 0xd9:
438
439
  // str 8
439
440
  value = src[position$1++];
440
441
  if (srcStringEnd >= position$1) {
441
- return srcString.slice(position$1 - srcStringStart, (position$1 += value) - srcStringStart)
442
+ return srcString.slice(position$1 - srcStringStart, (position$1 += value) - srcStringStart);
442
443
  }
443
- return readString8(value)
444
+ return readString8(value);
444
445
  case 0xda:
445
446
  // str 16
446
447
  value = dataView.getUint16(position$1);
447
448
  position$1 += 2;
448
449
  if (srcStringEnd >= position$1) {
449
- return srcString.slice(position$1 - srcStringStart, (position$1 += value) - srcStringStart)
450
+ return srcString.slice(position$1 - srcStringStart, (position$1 += value) - srcStringStart);
450
451
  }
451
- return readString16(value)
452
+ return readString16(value);
452
453
  case 0xdb:
453
454
  // str 32
454
455
  value = dataView.getUint32(position$1);
455
456
  position$1 += 4;
456
457
  if (srcStringEnd >= position$1) {
457
- return srcString.slice(position$1 - srcStringStart, (position$1 += value) - srcStringStart)
458
+ return srcString.slice(position$1 - srcStringStart, (position$1 += value) - srcStringStart);
458
459
  }
459
- return readString32(value)
460
+ return readString32(value);
460
461
  case 0xdc:
461
462
  // array 16
462
463
  value = dataView.getUint16(position$1);
463
464
  position$1 += 2;
464
- return readArray(value)
465
+ return readArray(value);
465
466
  case 0xdd:
466
467
  // array 32
467
468
  value = dataView.getUint32(position$1);
468
469
  position$1 += 4;
469
- return readArray(value)
470
+ return readArray(value);
470
471
  case 0xde:
471
472
  // map 16
472
473
  value = dataView.getUint16(position$1);
473
474
  position$1 += 2;
474
- return readMap(value)
475
+ return readMap(value);
475
476
  case 0xdf:
476
477
  // map 32
477
478
  value = dataView.getUint32(position$1);
478
479
  position$1 += 4;
479
- return readMap(value)
480
+ return readMap(value);
480
481
  default: // negative int
481
482
  if (token >= 0xe0)
482
- return token - 0x100
483
+ return token - 0x100;
483
484
  if (token === undefined) {
484
485
  let error = new Error('Unexpected end of MessagePack data');
485
486
  error.incomplete = true;
486
- throw error
487
+ throw error;
487
488
  }
488
- throw new Error('Unknown MessagePack token ' + token)
489
+ throw new Error('Unknown MessagePack token ' + token);
489
490
 
490
491
  }
491
492
  }
@@ -506,7 +507,7 @@
506
507
  }
507
508
  if (structure.highByte === 0)
508
509
  structure.read = createSecondByteReader(firstId, structure.read);
509
- return optimizedReadObject() // second byte is already read, if there is one so immediately read object
510
+ return optimizedReadObject(); // second byte is already read, if there is one so immediately read object
510
511
  }
511
512
  let object = {};
512
513
  for (let i = 0, l = structure.length; i < l; i++) {
@@ -517,38 +518,38 @@
517
518
  }
518
519
  if (currentUnpackr.freezeData)
519
520
  return Object.freeze(object);
520
- return object
521
+ return object;
521
522
  }
522
523
  readObject.count = 0;
523
524
  if (structure.highByte === 0) {
524
- return createSecondByteReader(firstId, readObject)
525
+ return createSecondByteReader(firstId, readObject);
525
526
  }
526
- return readObject
527
+ return readObject;
527
528
  }
528
529
 
529
530
  const createSecondByteReader = (firstId, read0) => {
530
531
  return function() {
531
532
  let highByte = src[position$1++];
532
533
  if (highByte === 0)
533
- return read0()
534
+ return read0();
534
535
  let id = firstId < 32 ? -(firstId + (highByte << 5)) : firstId + (highByte << 5);
535
536
  let structure = currentStructures[id] || loadStructures()[id];
536
537
  if (!structure) {
537
- throw new Error('Record id is not defined for ' + id)
538
+ throw new Error('Record id is not defined for ' + id);
538
539
  }
539
540
  if (!structure.read)
540
541
  structure.read = createStructureReader(structure, firstId);
541
- return structure.read()
542
- }
542
+ return structure.read();
543
+ };
543
544
  };
544
545
 
545
546
  function loadStructures() {
546
547
  let loadedStructures = saveState(() => {
547
548
  // save the state in case getStructures modifies our buffer
548
549
  src = null;
549
- return currentUnpackr.getStructures()
550
+ return currentUnpackr.getStructures();
550
551
  });
551
- return currentStructures = currentUnpackr._mergeStructures(loadedStructures, currentStructures)
552
+ return currentStructures = currentUnpackr._mergeStructures(loadedStructures, currentStructures);
552
553
  }
553
554
 
554
555
  var readFixedString = readStringJS;
@@ -560,10 +561,10 @@
560
561
  let result;
561
562
  if (length < 16) {
562
563
  if (result = shortStringInJS(length))
563
- return result
564
+ return result;
564
565
  }
565
566
  if (length > 64 && decoder)
566
- return decoder.decode(src.subarray(position$1, position$1 += length))
567
+ return decoder.decode(src.subarray(position$1, position$1 += length));
567
568
  const end = position$1 + length;
568
569
  const units = [];
569
570
  result = '';
@@ -626,7 +627,7 @@
626
627
  result += fromCharCode.apply(String, units);
627
628
  }
628
629
 
629
- return result
630
+ return result;
630
631
  }
631
632
 
632
633
  function readArray(length) {
@@ -635,8 +636,8 @@
635
636
  array[i] = read();
636
637
  }
637
638
  if (currentUnpackr.freezeData)
638
- return Object.freeze(array)
639
- return array
639
+ return Object.freeze(array);
640
+ return array;
640
641
  }
641
642
 
642
643
  function readMap(length) {
@@ -648,13 +649,13 @@
648
649
  key = '__proto_';
649
650
  object[key] = read();
650
651
  }
651
- return object
652
+ return object;
652
653
  } else {
653
654
  let map = new Map();
654
655
  for (let i = 0; i < length; i++) {
655
656
  map.set(read(), read());
656
657
  }
657
- return map
658
+ return map;
658
659
  }
659
660
  }
660
661
 
@@ -666,40 +667,40 @@
666
667
  const byte = src[position$1++];
667
668
  if ((byte & 0x80) > 0) {
668
669
  position$1 = start;
669
- return
670
+ return;
670
671
  }
671
672
  bytes[i] = byte;
672
673
  }
673
- return fromCharCode.apply(String, bytes)
674
+ return fromCharCode.apply(String, bytes);
674
675
  }
675
676
  function shortStringInJS(length) {
676
677
  if (length < 4) {
677
678
  if (length < 2) {
678
679
  if (length === 0)
679
- return ''
680
+ return '';
680
681
  else {
681
682
  let a = src[position$1++];
682
683
  if ((a & 0x80) > 1) {
683
684
  position$1 -= 1;
684
- return
685
+ return;
685
686
  }
686
- return fromCharCode(a)
687
+ return fromCharCode(a);
687
688
  }
688
689
  } else {
689
690
  let a = src[position$1++];
690
691
  let b = src[position$1++];
691
692
  if ((a & 0x80) > 0 || (b & 0x80) > 0) {
692
693
  position$1 -= 2;
693
- return
694
+ return;
694
695
  }
695
696
  if (length < 3)
696
- return fromCharCode(a, b)
697
+ return fromCharCode(a, b);
697
698
  let c = src[position$1++];
698
699
  if ((c & 0x80) > 0) {
699
700
  position$1 -= 3;
700
- return
701
+ return;
701
702
  }
702
- return fromCharCode(a, b, c)
703
+ return fromCharCode(a, b, c);
703
704
  }
704
705
  } else {
705
706
  let a = src[position$1++];
@@ -708,34 +709,34 @@
708
709
  let d = src[position$1++];
709
710
  if ((a & 0x80) > 0 || (b & 0x80) > 0 || (c & 0x80) > 0 || (d & 0x80) > 0) {
710
711
  position$1 -= 4;
711
- return
712
+ return;
712
713
  }
713
714
  if (length < 6) {
714
715
  if (length === 4)
715
- return fromCharCode(a, b, c, d)
716
+ return fromCharCode(a, b, c, d);
716
717
  else {
717
718
  let e = src[position$1++];
718
719
  if ((e & 0x80) > 0) {
719
720
  position$1 -= 5;
720
- return
721
+ return;
721
722
  }
722
- return fromCharCode(a, b, c, d, e)
723
+ return fromCharCode(a, b, c, d, e);
723
724
  }
724
725
  } else if (length < 8) {
725
726
  let e = src[position$1++];
726
727
  let f = src[position$1++];
727
728
  if ((e & 0x80) > 0 || (f & 0x80) > 0) {
728
729
  position$1 -= 6;
729
- return
730
+ return;
730
731
  }
731
732
  if (length < 7)
732
- return fromCharCode(a, b, c, d, e, f)
733
+ return fromCharCode(a, b, c, d, e, f);
733
734
  let g = src[position$1++];
734
735
  if ((g & 0x80) > 0) {
735
736
  position$1 -= 7;
736
- return
737
+ return;
737
738
  }
738
- return fromCharCode(a, b, c, d, e, f, g)
739
+ return fromCharCode(a, b, c, d, e, f, g);
739
740
  } else {
740
741
  let e = src[position$1++];
741
742
  let f = src[position$1++];
@@ -743,34 +744,34 @@
743
744
  let h = src[position$1++];
744
745
  if ((e & 0x80) > 0 || (f & 0x80) > 0 || (g & 0x80) > 0 || (h & 0x80) > 0) {
745
746
  position$1 -= 8;
746
- return
747
+ return;
747
748
  }
748
749
  if (length < 10) {
749
750
  if (length === 8)
750
- return fromCharCode(a, b, c, d, e, f, g, h)
751
+ return fromCharCode(a, b, c, d, e, f, g, h);
751
752
  else {
752
753
  let i = src[position$1++];
753
754
  if ((i & 0x80) > 0) {
754
755
  position$1 -= 9;
755
- return
756
+ return;
756
757
  }
757
- return fromCharCode(a, b, c, d, e, f, g, h, i)
758
+ return fromCharCode(a, b, c, d, e, f, g, h, i);
758
759
  }
759
760
  } else if (length < 12) {
760
761
  let i = src[position$1++];
761
762
  let j = src[position$1++];
762
763
  if ((i & 0x80) > 0 || (j & 0x80) > 0) {
763
764
  position$1 -= 10;
764
- return
765
+ return;
765
766
  }
766
767
  if (length < 11)
767
- return fromCharCode(a, b, c, d, e, f, g, h, i, j)
768
+ return fromCharCode(a, b, c, d, e, f, g, h, i, j);
768
769
  let k = src[position$1++];
769
770
  if ((k & 0x80) > 0) {
770
771
  position$1 -= 11;
771
- return
772
+ return;
772
773
  }
773
- return fromCharCode(a, b, c, d, e, f, g, h, i, j, k)
774
+ return fromCharCode(a, b, c, d, e, f, g, h, i, j, k);
774
775
  } else {
775
776
  let i = src[position$1++];
776
777
  let j = src[position$1++];
@@ -778,34 +779,34 @@
778
779
  let l = src[position$1++];
779
780
  if ((i & 0x80) > 0 || (j & 0x80) > 0 || (k & 0x80) > 0 || (l & 0x80) > 0) {
780
781
  position$1 -= 12;
781
- return
782
+ return;
782
783
  }
783
784
  if (length < 14) {
784
785
  if (length === 12)
785
- return fromCharCode(a, b, c, d, e, f, g, h, i, j, k, l)
786
+ return fromCharCode(a, b, c, d, e, f, g, h, i, j, k, l);
786
787
  else {
787
788
  let m = src[position$1++];
788
789
  if ((m & 0x80) > 0) {
789
790
  position$1 -= 13;
790
- return
791
+ return;
791
792
  }
792
- return fromCharCode(a, b, c, d, e, f, g, h, i, j, k, l, m)
793
+ return fromCharCode(a, b, c, d, e, f, g, h, i, j, k, l, m);
793
794
  }
794
795
  } else {
795
796
  let m = src[position$1++];
796
797
  let n = src[position$1++];
797
798
  if ((m & 0x80) > 0 || (n & 0x80) > 0) {
798
799
  position$1 -= 14;
799
- return
800
+ return;
800
801
  }
801
802
  if (length < 15)
802
- return fromCharCode(a, b, c, d, e, f, g, h, i, j, k, l, m, n)
803
+ return fromCharCode(a, b, c, d, e, f, g, h, i, j, k, l, m, n);
803
804
  let o = src[position$1++];
804
805
  if ((o & 0x80) > 0) {
805
806
  position$1 -= 15;
806
- return
807
+ return;
807
808
  }
808
- return fromCharCode(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o)
809
+ return fromCharCode(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o);
809
810
  }
810
811
  }
811
812
  }
@@ -823,22 +824,22 @@
823
824
  case 0xd9:
824
825
  // str 8
825
826
  length = src[position$1++];
826
- break
827
+ break;
827
828
  case 0xda:
828
829
  // str 16
829
830
  length = dataView.getUint16(position$1);
830
831
  position$1 += 2;
831
- break
832
+ break;
832
833
  case 0xdb:
833
834
  // str 32
834
835
  length = dataView.getUint32(position$1);
835
836
  position$1 += 4;
836
- break
837
+ break;
837
838
  default:
838
- throw new Error('Expected string')
839
+ throw new Error('Expected string');
839
840
  }
840
841
  }
841
- return readStringJS(length)
842
+ return readStringJS(length);
842
843
  }
843
844
 
844
845
 
@@ -846,7 +847,7 @@
846
847
  return currentUnpackr.copyBuffers ?
847
848
  // specifically use the copying slice (not the node one)
848
849
  Uint8Array.prototype.slice.call(src, position$1, position$1 += length) :
849
- src.subarray(position$1, position$1 += length)
850
+ src.subarray(position$1, position$1 += length);
850
851
  }
851
852
  function readExt(length) {
852
853
  let type = src[position$1++];
@@ -859,10 +860,10 @@
859
860
  } finally {
860
861
  position$1 = end;
861
862
  }
862
- })
863
+ });
863
864
  }
864
865
  else
865
- throw new Error('Unknown extension type ' + type)
866
+ throw new Error('Unknown extension type ' + type);
866
867
  }
867
868
 
868
869
  var keyCache = new Array(4096);
@@ -872,12 +873,12 @@
872
873
  // fixstr, potentially use key cache
873
874
  length = length - 0xa0;
874
875
  if (srcStringEnd >= position$1) // if it has been extracted, must use it (and faster anyway)
875
- return srcString.slice(position$1 - srcStringStart, (position$1 += length) - srcStringStart)
876
+ return srcString.slice(position$1 - srcStringStart, (position$1 += length) - srcStringStart);
876
877
  else if (!(srcStringEnd == 0 && srcEnd < 180))
877
- return readFixedString(length)
878
+ return readFixedString(length);
878
879
  } else { // not cacheable, go back and do a standard read
879
880
  position$1--;
880
- return asSafeString(read())
881
+ return asSafeString(read());
881
882
  }
882
883
  let key = ((length << 5) ^ (length > 1 ? dataView.getUint16(position$1) : length > 0 ? src[position$1] : 0)) & 0xfff;
883
884
  let entry = keyCache[key];
@@ -890,7 +891,7 @@
890
891
  chunk = dataView.getUint32(checkPosition);
891
892
  if (chunk != entry[i++]) {
892
893
  checkPosition = 0x70000000;
893
- break
894
+ break;
894
895
  }
895
896
  checkPosition += 4;
896
897
  }
@@ -899,12 +900,12 @@
899
900
  chunk = src[checkPosition++];
900
901
  if (chunk != entry[i++]) {
901
902
  checkPosition = 0x70000000;
902
- break
903
+ break;
903
904
  }
904
905
  }
905
906
  if (checkPosition === end) {
906
907
  position$1 = checkPosition;
907
- return entry.string
908
+ return entry.string;
908
909
  }
909
910
  end -= 3;
910
911
  checkPosition = position$1;
@@ -925,8 +926,8 @@
925
926
  // for small blocks, avoiding the overhead of the extract call is helpful
926
927
  let string = length < 16 ? shortStringInJS(length) : longStringInJS(length);
927
928
  if (string != null)
928
- return entry.string = string
929
- return entry.string = readFixedString(length)
929
+ return entry.string = string;
930
+ return entry.string = readFixedString(length);
930
931
  }
931
932
 
932
933
  function asSafeString(property) {
@@ -957,7 +958,7 @@
957
958
  }
958
959
  currentStructures[id] = structure;
959
960
  structure.read = createStructureReader(structure, firstByte);
960
- return structure.read()
961
+ return structure.read();
961
962
  };
962
963
  currentExtensions[0] = () => {}; // notepack defines extension 0 to mean undefined, so use that as the default here
963
964
  currentExtensions[0].noBuffer = true;
@@ -979,17 +980,17 @@
979
980
  out <<= BigInt(64);
980
981
  out |= view.getBigUint64(i);
981
982
  }
982
- return out
983
+ return out;
983
984
  }
984
985
  // if (length === 8) return view.getBigUint64(start)
985
986
  let middle = start + (length >> 4 << 3);
986
987
  let left = decode(start, middle);
987
988
  let right = decode(middle, end);
988
- return (left << BigInt((end - middle) * 8)) | right
989
+ return (left << BigInt((end - middle) * 8)) | right;
989
990
  };
990
991
  head = (head << BigInt((view.byteLength - headLength) * 8)) | decode(headLength, view.byteLength);
991
992
  }
992
- return head
993
+ return head;
993
994
  };
994
995
 
995
996
  let errors = {
@@ -1000,14 +1001,14 @@
1000
1001
  if (!errors[data[0]]) {
1001
1002
  let error = Error(data[1], { cause: data[2] });
1002
1003
  error.name = data[0];
1003
- return error
1004
+ return error;
1004
1005
  }
1005
- return errors[data[0]](data[1], { cause: data[2] })
1006
+ return errors[data[0]](data[1], { cause: data[2] });
1006
1007
  };
1007
1008
 
1008
1009
  currentExtensions[0x69] = (data) => {
1009
1010
  // id extension (for structured clones)
1010
- if (currentUnpackr.structuredClone === false) throw new Error('Structured clone extension is disabled')
1011
+ if (currentUnpackr.structuredClone === false) throw new Error('Structured clone extension is disabled');
1011
1012
  let id = dataView.getUint32(position$1 - 4);
1012
1013
  if (!referenceMap)
1013
1014
  referenceMap = new Map();
@@ -1028,7 +1029,7 @@
1028
1029
  let targetProperties = read(); // read the next value as the target object to id
1029
1030
  if (!refEntry.used) {
1030
1031
  // no cycle, can just use the returned read object
1031
- return refEntry.target = targetProperties // replace the placeholder with the real one
1032
+ return refEntry.target = targetProperties; // replace the placeholder with the real one
1032
1033
  } else {
1033
1034
  // there is a cycle, so we have to assign properties to original target
1034
1035
  Object.assign(target, targetProperties);
@@ -1039,16 +1040,16 @@
1039
1040
  for (let [k, v] of targetProperties.entries()) target.set(k, v);
1040
1041
  if (target instanceof Set)
1041
1042
  for (let i of Array.from(targetProperties)) target.add(i);
1042
- return target
1043
+ return target;
1043
1044
  };
1044
1045
 
1045
1046
  currentExtensions[0x70] = (data) => {
1046
1047
  // pointer extension (for structured clones)
1047
- if (currentUnpackr.structuredClone === false) throw new Error('Structured clone extension is disabled')
1048
+ if (currentUnpackr.structuredClone === false) throw new Error('Structured clone extension is disabled');
1048
1049
  let id = dataView.getUint32(position$1 - 4);
1049
1050
  let refEntry = referenceMap.get(id);
1050
1051
  refEntry.used = true;
1051
- return refEntry.target
1052
+ return refEntry.target;
1052
1053
  };
1053
1054
 
1054
1055
  currentExtensions[0x73] = () => new Set(read());
@@ -1063,15 +1064,15 @@
1063
1064
 
1064
1065
  let typedArrayName = typedArrays[typeCode];
1065
1066
  if (!typedArrayName) {
1066
- if (typeCode === 16) return buffer
1067
- if (typeCode === 17) return new DataView(buffer)
1068
- throw new Error('Could not find typed array for code ' + typeCode)
1067
+ if (typeCode === 16) return buffer;
1068
+ if (typeCode === 17) return new DataView(buffer);
1069
+ throw new Error('Could not find typed array for code ' + typeCode);
1069
1070
  }
1070
- return new glbl[typedArrayName](buffer)
1071
+ return new glbl[typedArrayName](buffer);
1071
1072
  };
1072
1073
  currentExtensions[0x78] = () => {
1073
1074
  let data = read();
1074
- return new RegExp(data[0], data[1])
1075
+ return new RegExp(data[0], data[1]);
1075
1076
  };
1076
1077
  const TEMP_BUNDLE = [];
1077
1078
  currentExtensions[0x62] = (data) => {
@@ -1084,28 +1085,30 @@
1084
1085
  bundledStrings$1.position1 = 0;
1085
1086
  bundledStrings$1.postBundlePosition = position$1;
1086
1087
  position$1 = dataPosition;
1087
- return read()
1088
+ return read();
1088
1089
  };
1089
1090
 
1090
1091
  currentExtensions[0xff] = (data) => {
1091
1092
  // 32-bit date extension
1092
1093
  if (data.length == 4)
1093
- return new Date((data[0] * 0x1000000 + (data[1] << 16) + (data[2] << 8) + data[3]) * 1000)
1094
+ return new Date((data[0] * 0x1000000 + (data[1] << 16) + (data[2] << 8) + data[3]) * 1000);
1094
1095
  else if (data.length == 8)
1095
1096
  return new Date(
1096
1097
  ((data[0] << 22) + (data[1] << 14) + (data[2] << 6) + (data[3] >> 2)) / 1000000 +
1097
- ((data[3] & 0x3) * 0x100000000 + data[4] * 0x1000000 + (data[5] << 16) + (data[6] << 8) + data[7]) * 1000)
1098
+ ((data[3] & 0x3) * 0x100000000 + data[4] * 0x1000000 + (data[5] << 16) + (data[6] << 8) + data[7]) * 1000);
1098
1099
  else if (data.length == 12)
1099
1100
  return new Date(
1100
1101
  ((data[0] << 24) + (data[1] << 16) + (data[2] << 8) + data[3]) / 1000000 +
1101
- (((data[4] & 0x80) ? -0x1000000000000 : 0) + data[6] * 0x10000000000 + data[7] * 0x100000000 + data[8] * 0x1000000 + (data[9] << 16) + (data[10] << 8) + data[11]) * 1000)
1102
+ (((data[4] & 0x80) ? -0x1000000000000 : 0) + data[6] * 0x10000000000 + data[7] * 0x100000000 + data[8] * 0x1000000 + (data[9] << 16) + (data[10] << 8) + data[11]) * 1000);
1102
1103
  else
1103
- return new Date('invalid')
1104
+ return new Date('invalid');
1104
1105
  };
1105
1106
  // registration of bulk record definition?
1106
1107
  // currentExtensions[0x52] = () =>
1107
1108
 
1108
1109
  function saveState(callback) {
1110
+ if (currentUnpackr && currentUnpackr._onSaveState)
1111
+ currentUnpackr._onSaveState();
1109
1112
  let savedSrcEnd = srcEnd;
1110
1113
  let savedPosition = position$1;
1111
1114
  let savedSrcStringStart = srcStringStart;
@@ -1134,7 +1137,7 @@
1134
1137
  currentStructures.splice(0, currentStructures.length, ...savedStructuresContents);
1135
1138
  currentUnpackr = savedPackr;
1136
1139
  dataView = new DataView(src.buffer, src.byteOffset, src.byteLength);
1137
- return value
1140
+ return value;
1138
1141
  }
1139
1142
  function clearSource() {
1140
1143
  src = null;
@@ -1169,8 +1172,12 @@
1169
1172
  function roundFloat32(float32Number) {
1170
1173
  f32Array[0] = float32Number;
1171
1174
  let multiplier = mult10[((u8Array[3] & 0x7f) << 1) | (u8Array[2] >> 7)];
1172
- return ((multiplier * float32Number + (float32Number > 0 ? 0.5 : -0.5)) >> 0) / multiplier
1175
+ return ((multiplier * float32Number + (float32Number > 0 ? 0.5 : -0.5)) >> 0) / multiplier;
1173
1176
  }
1177
+ // Marker for downstream libraries (e.g. structon) to detect per-instance
1178
+ // struct-decoding hooks (this._readStruct, this._onLoadedStructures,
1179
+ // this._onSaveState). See `checkedRead` for the dispatch.
1180
+ Unpackr.SUPPORTS_STRUCT_HOOKS = true;
1174
1181
 
1175
1182
  let textEncoder;
1176
1183
  try {
@@ -1179,7 +1186,7 @@
1179
1186
  let extensions, extensionClasses;
1180
1187
  const hasNodeBuffer = typeof Buffer !== 'undefined';
1181
1188
  const ByteArrayAllocate = hasNodeBuffer ?
1182
- function(length) { return Buffer.allocUnsafeSlow(length) } : Uint8Array;
1189
+ function(length) { return Buffer.allocUnsafeSlow(length); } : Uint8Array;
1183
1190
  const ByteArray = hasNodeBuffer ? Buffer : Uint8Array;
1184
1191
  const MAX_BUFFER_SIZE = hasNodeBuffer ? 0x100000000 : 0x7fd00000;
1185
1192
  let target, keysTarget;
@@ -1187,7 +1194,6 @@
1187
1194
  let position = 0;
1188
1195
  let safeEnd;
1189
1196
  let bundledStrings = null;
1190
- let writeStructSlots;
1191
1197
  const MAX_BUNDLE_SIZE = 0x5500; // maximum characters such that the encoded bytes fits in 16 bits.
1192
1198
  const hasNonLatin = /[\u0080-\uFFFF]/;
1193
1199
  const RECORD_SYMBOL = Symbol('record-id');
@@ -1200,10 +1206,10 @@
1200
1206
  let structures;
1201
1207
  let referenceMap;
1202
1208
  let encodeUtf8 = ByteArray.prototype.utf8Write ? function(string, position) {
1203
- return target.utf8Write(string, position, target.byteLength - position)
1209
+ return target.utf8Write(string, position, target.byteLength - position);
1204
1210
  } : (textEncoder && textEncoder.encodeInto) ?
1205
1211
  function(string, position) {
1206
- return textEncoder.encodeInto(string, target.subarray(position)).written
1212
+ return textEncoder.encodeInto(string, target.subarray(position)).written;
1207
1213
  } : false;
1208
1214
 
1209
1215
  let packr = this;
@@ -1215,7 +1221,7 @@
1215
1221
  if (maxSharedStructures == null)
1216
1222
  maxSharedStructures = hasSharedStructures ? 32 : 0;
1217
1223
  if (maxSharedStructures > 8160)
1218
- throw new Error('Maximum maxSharedStructure is 8160')
1224
+ throw new Error('Maximum maxSharedStructure is 8160');
1219
1225
  if (options.structuredClone && options.moreTypes == undefined) {
1220
1226
  this.moreTypes = true;
1221
1227
  }
@@ -1229,7 +1235,7 @@
1229
1235
  let sharedLimitId = maxSharedStructures + 0x40;
1230
1236
  let maxStructureId = maxSharedStructures + maxOwnStructures + 0x40;
1231
1237
  if (maxStructureId > 8256) {
1232
- throw new Error('Maximum maxSharedStructure + maxOwnStructure is 8192')
1238
+ throw new Error('Maximum maxSharedStructure + maxOwnStructure is 8192');
1233
1239
  }
1234
1240
  let recordIdsToRemove = [];
1235
1241
  let transitionsCount = 0;
@@ -1265,7 +1271,7 @@
1265
1271
  let sharedLength = structures.sharedLength || 0;
1266
1272
  if (sharedLength > maxSharedStructures) {
1267
1273
  //if (maxSharedStructures <= 32 && structures.sharedLength > 32) // TODO: could support this, but would need to update the limit ids
1268
- throw new Error('Shared structures is larger than maximum shared structures, try increasing maxSharedStructures to ' + structures.sharedLength)
1274
+ throw new Error('Shared structures is larger than maximum shared structures, try increasing maxSharedStructures to ' + structures.sharedLength);
1269
1275
  }
1270
1276
  if (!structures.transitions) {
1271
1277
  // rebuild our structure transitions
@@ -1273,7 +1279,7 @@
1273
1279
  for (let i = 0; i < sharedLength; i++) {
1274
1280
  let keys = structures[i];
1275
1281
  if (!keys)
1276
- continue
1282
+ continue;
1277
1283
  let nextTransition, transition = structures.transitions;
1278
1284
  for (let j = 0, l = keys.length; j < l; j++) {
1279
1285
  let key = keys[j];
@@ -1295,7 +1301,7 @@
1295
1301
  hasSharedUpdate = false;
1296
1302
  let encodingError;
1297
1303
  try {
1298
- if (packr.randomAccessStructure && value && typeof value === 'object') {
1304
+ if (packr._writeStruct && value && typeof value === 'object') {
1299
1305
  if (value.constructor === Object) writeStruct(value); // simple object
1300
1306
  else if (value.constructor !== Map && !Array.isArray(value) && !extensionClasses.some(extClass => value instanceof extClass)) {
1301
1307
  // allow user classes, if they don't need special handling (but do use toJSON if available)
@@ -1339,15 +1345,15 @@
1339
1345
  packr.offset = position;
1340
1346
  let serialized = insertIds(target.subarray(start, position), idsToInsert);
1341
1347
  referenceMap = null;
1342
- return serialized
1348
+ return serialized;
1343
1349
  }
1344
1350
  packr.offset = position; // update the offset so next serialization doesn't write over our buffer, but can continue writing to same buffer sequentially
1345
1351
  if (encodeOptions & REUSE_BUFFER_MODE) {
1346
1352
  target.start = start;
1347
1353
  target.end = position;
1348
- return target
1354
+ return target;
1349
1355
  }
1350
- return target.subarray(start, position) // position can change if we call pack again in saveStructures, so we get the buffer now
1356
+ return target.subarray(start, position); // position can change if we call pack again in saveStructures, so we get the buffer now
1351
1357
  } catch(error) {
1352
1358
  encodingError = error;
1353
1359
  throw error;
@@ -1358,16 +1364,16 @@
1358
1364
  let sharedLength = structures.sharedLength || 0;
1359
1365
  // we can't rely on start/end with REUSE_BUFFER_MODE since they will (probably) change when we save
1360
1366
  let returnBuffer = target.subarray(start, position);
1361
- let newSharedData = prepareStructures(structures, packr);
1367
+ let newSharedData = (packr._prepareStructures || prepareStructures)(structures, packr);
1362
1368
  if (!encodingError) { // TODO: If there is an encoding error, should make the structures as uninitialized so they get rebuilt next time
1363
1369
  if (packr.saveStructures(newSharedData, newSharedData.isCompatible) === false) {
1364
1370
  // get updated structures and try again if the update failed
1365
- return packr.pack(value, encodeOptions)
1371
+ return packr.pack(value, encodeOptions);
1366
1372
  }
1367
1373
  packr.lastNamedStructuresLength = sharedLength;
1368
1374
  // don't keep large buffers around
1369
1375
  if (target.length > 0x40000000) target = null;
1370
- return returnBuffer
1376
+ return returnBuffer;
1371
1377
  }
1372
1378
  }
1373
1379
  }
@@ -1453,7 +1459,7 @@
1453
1459
  bundledStrings[twoByte ? 0 : 1] += value;
1454
1460
  target[position++] = 0xc1;
1455
1461
  pack(twoByte ? -strLength : strLength);
1456
- return
1462
+ return;
1457
1463
  }
1458
1464
  let headerSize;
1459
1465
  // first we estimate the header size, so we can write to the correct location
@@ -1527,7 +1533,7 @@
1527
1533
  } else if (type === 'number') {
1528
1534
  if (value >>> 0 === value) {// positive integer, 32-bit or less
1529
1535
  // positive uint
1530
- if (value < 0x20 || (value < 0x80 && this.useRecords === false) || (value < 0x40 && !this.randomAccessStructure)) {
1536
+ if (value < 0x20 || (value < 0x80 && this.useRecords === false) || (value < 0x40 && !this._writeStruct)) {
1531
1537
  target[position++] = value;
1532
1538
  } else if (value < 0x100) {
1533
1539
  target[position++] = 0xcc;
@@ -1566,7 +1572,7 @@
1566
1572
  // this checks for rounding of numbers that were encoded in 32-bit float to nearest significant decimal digit that could be preserved
1567
1573
  ((xShifted = value * mult10[((target[position] & 0x7f) << 1) | (target[position + 1] >> 7)]) >> 0) === xShifted) {
1568
1574
  position += 4;
1569
- return
1575
+ return;
1570
1576
  } else
1571
1577
  position--; // move back into position for writing a double
1572
1578
  }
@@ -1589,7 +1595,7 @@
1589
1595
  target[position++] = 0x70; // "p" for pointer
1590
1596
  targetView.setUint32(position, referee.id);
1591
1597
  position += 4;
1592
- return
1598
+ return;
1593
1599
  } else
1594
1600
  referenceMap.set(value, { offset: position - start });
1595
1601
  }
@@ -1639,7 +1645,7 @@
1639
1645
  } else {
1640
1646
  pack(writeResult);
1641
1647
  }
1642
- return
1648
+ return;
1643
1649
  }
1644
1650
  let currentTarget = target;
1645
1651
  let currentTargetView = targetView;
@@ -1656,7 +1662,7 @@
1656
1662
  makeRoom(position);
1657
1663
  return {
1658
1664
  target, targetView, position: position - size
1659
- }
1665
+ };
1660
1666
  }, pack);
1661
1667
  } finally {
1662
1668
  // restore current target information (unless already restored)
@@ -1672,7 +1678,7 @@
1672
1678
  makeRoom(result.length + position);
1673
1679
  position = writeExtensionData(result, target, position, extension.type);
1674
1680
  }
1675
- return
1681
+ return;
1676
1682
  }
1677
1683
  }
1678
1684
  // check isArray after extensions, because extensions can extend Array
@@ -1684,7 +1690,7 @@
1684
1690
  const json = value.toJSON();
1685
1691
  // if for some reason value.toJSON returns itself it'll loop forever
1686
1692
  if (json !== value)
1687
- return pack(json)
1693
+ return pack(json);
1688
1694
  }
1689
1695
 
1690
1696
  // if there is a writeFunction, use it, otherwise just encode as undefined
@@ -1723,7 +1729,7 @@
1723
1729
  let chunks = [];
1724
1730
  while (true) {
1725
1731
  chunks.push(value & mask);
1726
- if ((value >> BigInt(63)) === empty) break
1732
+ if ((value >> BigInt(63)) === empty) break;
1727
1733
  value >>= BigInt(64);
1728
1734
  }
1729
1735
 
@@ -1755,11 +1761,11 @@
1755
1761
  if (array.length + position > safeEnd)
1756
1762
  makeRoom(array.length + position);
1757
1763
  position = writeExtensionData(array, target, position, 0x42);
1758
- return
1764
+ return;
1759
1765
  } else {
1760
1766
  throw new RangeError(value + ' was too large to fit in MessagePack 64-bit integer format, use' +
1761
1767
  ' useBigIntExtension, or set largeBigIntToFloat to convert to float-64, or set' +
1762
- ' largeBigIntToString to convert to string')
1768
+ ' largeBigIntToString to convert to string');
1763
1769
  }
1764
1770
  }
1765
1771
  position += 8;
@@ -1772,7 +1778,7 @@
1772
1778
  target[position++] = 0;
1773
1779
  }
1774
1780
  } else {
1775
- throw new Error('Unknown type: ' + type)
1781
+ throw new Error('Unknown type: ' + type);
1776
1782
  }
1777
1783
  };
1778
1784
 
@@ -1918,12 +1924,30 @@
1918
1924
  checkUseRecords(object) ? writeRecord(object) : writePlainObject(object);
1919
1925
  } : writeRecord;
1920
1926
 
1927
+ const writeStruct = (object) => {
1928
+ let newPosition = packr._writeStruct(object, target, start, position, structures, makeRoom, (value, newPosition, notifySharedUpdate) => {
1929
+ if (notifySharedUpdate)
1930
+ return hasSharedUpdate = true;
1931
+ position = newPosition;
1932
+ let startTarget = target;
1933
+ pack(value);
1934
+ resetStructures();
1935
+ if (startTarget !== target) {
1936
+ return { position, targetView, target }; // indicate the buffer was re-allocated
1937
+ }
1938
+ return position;
1939
+ });
1940
+ if (newPosition === 0) // bail and go to a msgpack object
1941
+ return writeObject(object);
1942
+ position = newPosition;
1943
+ };
1944
+
1921
1945
  const makeRoom = (end) => {
1922
1946
  let newSize;
1923
1947
  if (end > 0x1000000) {
1924
1948
  // special handling for really large buffers
1925
1949
  if ((end - start) > MAX_BUFFER_SIZE)
1926
- throw new Error('Packed buffer would be larger than maximum buffer size')
1950
+ throw new Error('Packed buffer would be larger than maximum buffer size');
1927
1951
  newSize = Math.min(MAX_BUFFER_SIZE,
1928
1952
  Math.round(Math.max((end - start) * (end > 0x4000000 ? 1.25 : 2), 0x400000) / 0x1000) * 0x1000);
1929
1953
  } else // faster handling for smaller buffers
@@ -1938,7 +1962,7 @@
1938
1962
  position -= start;
1939
1963
  start = 0;
1940
1964
  safeEnd = newBuffer.length - 10;
1941
- return target = newBuffer
1965
+ return target = newBuffer;
1942
1966
  };
1943
1967
  const newRecord = (transition, keys, newTransitions) => {
1944
1968
  let recordId = structures.nextId;
@@ -2020,23 +2044,6 @@
2020
2044
  target[insertionOffset + start] = keysTarget[0];
2021
2045
  }
2022
2046
  };
2023
- const writeStruct = (object) => {
2024
- let newPosition = writeStructSlots(object, target, start, position, structures, makeRoom, (value, newPosition, notifySharedUpdate) => {
2025
- if (notifySharedUpdate)
2026
- return hasSharedUpdate = true;
2027
- position = newPosition;
2028
- let startTarget = target;
2029
- pack(value);
2030
- resetStructures();
2031
- if (startTarget !== target) {
2032
- return { position, targetView, target }; // indicate the buffer was re-allocated
2033
- }
2034
- return position;
2035
- }, this);
2036
- if (newPosition === 0) // bail and go to a msgpack object
2037
- return writeObject(object);
2038
- position = newPosition;
2039
- };
2040
2047
  }
2041
2048
  useBuffer(buffer) {
2042
2049
  // this means we are finished using our own buffer and we can write over it safely
@@ -2079,7 +2086,7 @@
2079
2086
  } else if (isNaN(seconds)) {
2080
2087
  if (this.onInvalidDate) {
2081
2088
  allocateForWrite(0);
2082
- return pack(this.onInvalidDate())
2089
+ return pack(this.onInvalidDate());
2083
2090
  }
2084
2091
  // Intentionally invalid timestamp
2085
2092
  let { target, targetView, position} = allocateForWrite(3);
@@ -2100,7 +2107,7 @@
2100
2107
  pack(set, allocateForWrite, pack) {
2101
2108
  if (this.setAsEmptyObject) {
2102
2109
  allocateForWrite(0);
2103
- return pack({})
2110
+ return pack({});
2104
2111
  }
2105
2112
  let array = Array.from(set);
2106
2113
  let { target, position} = allocateForWrite(this.moreTypes ? 3 : 0);
@@ -2208,19 +2215,19 @@
2208
2215
  switch (length) {
2209
2216
  case 1:
2210
2217
  target[position++] = 0xd4;
2211
- break
2218
+ break;
2212
2219
  case 2:
2213
2220
  target[position++] = 0xd5;
2214
- break
2221
+ break;
2215
2222
  case 4:
2216
2223
  target[position++] = 0xd6;
2217
- break
2224
+ break;
2218
2225
  case 8:
2219
2226
  target[position++] = 0xd7;
2220
- break
2227
+ break;
2221
2228
  case 16:
2222
2229
  target[position++] = 0xd8;
2223
- break
2230
+ break;
2224
2231
  default:
2225
2232
  if (length < 0x100) {
2226
2233
  target[position++] = 0xc7;
@@ -2240,7 +2247,7 @@
2240
2247
  target[position++] = type;
2241
2248
  target.set(result, position);
2242
2249
  position += length;
2243
- return position
2250
+ return position;
2244
2251
  }
2245
2252
 
2246
2253
  function insertIds(serialized, idsToInsert) {
@@ -2262,7 +2269,7 @@
2262
2269
  serialized[position++] = id & 0xff;
2263
2270
  lastEnd = offset;
2264
2271
  }
2265
- return serialized
2272
+ return serialized;
2266
2273
  }
2267
2274
 
2268
2275
  function writeBundles(start, pack, incrementPosition) {
@@ -2279,9 +2286,9 @@
2279
2286
  function addExtension(extension) {
2280
2287
  if (extension.Class) {
2281
2288
  if (!extension.pack && !extension.write)
2282
- throw new Error('Extension has no pack or write function')
2289
+ throw new Error('Extension has no pack or write function');
2283
2290
  if (extension.pack && !extension.type)
2284
- throw new Error('Extension has no type (numeric code to identify the extension)')
2291
+ throw new Error('Extension has no type (numeric code to identify the extension)');
2285
2292
  extensionClasses.unshift(extension.Class);
2286
2293
  extensions.unshift(extension);
2287
2294
  }
@@ -2294,9 +2301,14 @@
2294
2301
  packr._mergeStructures(existingStructures);
2295
2302
  return compatible;
2296
2303
  };
2297
- return structures
2304
+ return structures;
2298
2305
  }
2299
2306
 
2307
+ // Marker for downstream libraries (e.g. structon) to detect that this Packr
2308
+ // supports per-instance struct-encoding hooks (this._writeStruct,
2309
+ // this._prepareStructures). See `pack` for the dispatch.
2310
+ Packr.SUPPORTS_STRUCT_HOOKS = true;
2311
+
2300
2312
  let defaultPackr = new Packr({ useRecords: false });
2301
2313
  const pack = defaultPackr.pack;
2302
2314
  const encode = defaultPackr.pack;
@@ -2315,13 +2327,13 @@
2315
2327
  */
2316
2328
  function packIter (objectIterator, options = {}) {
2317
2329
  if (!objectIterator || typeof objectIterator !== 'object') {
2318
- throw new Error('first argument must be an Iterable, Async Iterable, or a Promise for an Async Iterable')
2330
+ throw new Error('first argument must be an Iterable, Async Iterable, or a Promise for an Async Iterable');
2319
2331
  } else if (typeof objectIterator[Symbol.iterator] === 'function') {
2320
- return packIterSync(objectIterator, options)
2332
+ return packIterSync(objectIterator, options);
2321
2333
  } else if (typeof objectIterator.then === 'function' || typeof objectIterator[Symbol.asyncIterator] === 'function') {
2322
- return packIterAsync(objectIterator, options)
2334
+ return packIterAsync(objectIterator, options);
2323
2335
  } else {
2324
- throw new Error('first argument must be an Iterable, Async Iterable, Iterator, Async Iterator, or a Promise')
2336
+ throw new Error('first argument must be an Iterable, Async Iterable, Iterator, Async Iterator, or a Promise');
2325
2337
  }
2326
2338
  }
2327
2339
 
@@ -2348,7 +2360,7 @@
2348
2360
  */
2349
2361
  function unpackIter (bufferIterator, options = {}) {
2350
2362
  if (!bufferIterator || typeof bufferIterator !== 'object') {
2351
- throw new Error('first argument must be an Iterable, Async Iterable, Iterator, Async Iterator, or a promise')
2363
+ throw new Error('first argument must be an Iterable, Async Iterable, Iterator, Async Iterator, or a promise');
2352
2364
  }
2353
2365
 
2354
2366
  const unpackr = new Unpackr(options);
@@ -2368,10 +2380,10 @@
2368
2380
  incomplete = chunk.slice(err.lastPosition);
2369
2381
  yields = err.values;
2370
2382
  } else {
2371
- throw err
2383
+ throw err;
2372
2384
  }
2373
2385
  }
2374
- return yields
2386
+ return yields;
2375
2387
  };
2376
2388
 
2377
2389
  if (typeof bufferIterator[Symbol.iterator] === 'function') {
@@ -2379,13 +2391,13 @@
2379
2391
  for (const value of bufferIterator) {
2380
2392
  yield * parser(value);
2381
2393
  }
2382
- })()
2394
+ })();
2383
2395
  } else if (typeof bufferIterator[Symbol.asyncIterator] === 'function') {
2384
2396
  return (async function * iter () {
2385
2397
  for await (const value of bufferIterator) {
2386
2398
  yield * parser(value);
2387
2399
  }
2388
- })()
2400
+ })();
2389
2401
  }
2390
2402
  }
2391
2403
  const decodeIter = unpackIter;