msgpackr 1.7.0-alpha2 → 1.7.0-alpha5

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/node.cjs CHANGED
@@ -33,7 +33,7 @@ const C1 = new C1Type();
33
33
  C1.name = 'MessagePack 0xC1';
34
34
  var sequentialMode = false;
35
35
  var inlineObjectReadThreshold = 2;
36
- var readStruct;
36
+ var readStruct, onLoadedStructures;
37
37
  try {
38
38
  new Function('');
39
39
  } catch(error) {
@@ -63,16 +63,21 @@ class Unpackr {
63
63
  }
64
64
  Object.assign(this, options);
65
65
  }
66
- unpack(source, end) {
66
+ unpack(source, options) {
67
67
  if (src) {
68
68
  // re-entrant execution, save the state and restore it after we do this unpack
69
69
  return saveState(() => {
70
70
  clearSource();
71
- return this ? this.unpack(source, end) : Unpackr.prototype.unpack.call(defaultOptions, source, end)
71
+ return this ? this.unpack(source, options) : Unpackr.prototype.unpack.call(defaultOptions, source, options)
72
72
  })
73
73
  }
74
- srcEnd = end > -1 ? end : source.length;
75
- position = 0;
74
+ if (typeof options === 'object') {
75
+ srcEnd = options.end || source.length;
76
+ position = options.start || 0;
77
+ } else {
78
+ position = 0;
79
+ srcEnd = options > -1 ? options : source.length;
80
+ }
76
81
  stringPosition = 0;
77
82
  srcStringEnd = 0;
78
83
  srcString = null;
@@ -95,7 +100,7 @@ class Unpackr {
95
100
  currentUnpackr = this;
96
101
  if (this.structures) {
97
102
  currentStructures = this.structures;
98
- return checkedRead()
103
+ return checkedRead(options)
99
104
  } else if (!currentStructures || currentStructures.length > 0) {
100
105
  currentStructures = [];
101
106
  }
@@ -104,7 +109,7 @@ class Unpackr {
104
109
  if (!currentStructures || currentStructures.length > 0)
105
110
  currentStructures = [];
106
111
  }
107
- return checkedRead()
112
+ return checkedRead(options)
108
113
  }
109
114
  unpackMultiple(source, forEach) {
110
115
  let values, lastPosition = 0;
@@ -139,7 +144,11 @@ class Unpackr {
139
144
  }
140
145
  }
141
146
  _mergeStructures(loadedStructures, existingStructures) {
147
+ if (onLoadedStructures)
148
+ loadedStructures = onLoadedStructures.call(this, loadedStructures);
142
149
  loadedStructures = loadedStructures || [];
150
+ if (Object.isFrozen(loadedStructures))
151
+ loadedStructures = loadedStructures.map(structure => structure.slice(0));
143
152
  for (let i = 0, l = loadedStructures.length; i < l; i++) {
144
153
  let structure = loadedStructures[i];
145
154
  if (structure) {
@@ -166,7 +175,7 @@ class Unpackr {
166
175
  return this.unpack(source, end)
167
176
  }
168
177
  }
169
- function checkedRead() {
178
+ function checkedRead(options) {
170
179
  try {
171
180
  if (!currentUnpackr.trusted && !sequentialMode) {
172
181
  let sharedLength = currentStructures.sharedLength || 0;
@@ -174,9 +183,10 @@ function checkedRead() {
174
183
  currentStructures.length = sharedLength;
175
184
  }
176
185
  let result;
177
- if (currentUnpackr.randomAccessStructure && src[position] < 0x40 && readStruct) {
178
- let id = (src[position++] << 8) + src[position++];
179
- result = readStruct(src, position, srcEnd, currentStructures[id - 0x40] || loadStructures()[id - 0x40], currentUnpackr);
186
+ if (currentUnpackr.randomAccessStructure && src[position] < 0x40 && src[position] >= 0x20 && readStruct) {
187
+ result = readStruct(src, position, srcEnd, currentUnpackr);
188
+ if (!(options && options.lazy) && result)
189
+ result = result.toJSON();
180
190
  position = srcEnd;
181
191
  } else
182
192
  result = read();
@@ -612,6 +622,16 @@ function readStringJS(length) {
612
622
 
613
623
  return result
614
624
  }
625
+ function readString(source, start, length) {
626
+ let existingSrc = src;
627
+ src = source;
628
+ position = start;
629
+ try {
630
+ return readStringJS(length);
631
+ } finally {
632
+ src = existingSrc;
633
+ }
634
+ }
615
635
 
616
636
  function readArray(length) {
617
637
  let array = new Array(length);
@@ -832,7 +852,15 @@ function readBin(length) {
832
852
  function readExt(length) {
833
853
  let type = src[position++];
834
854
  if (currentExtensions[type]) {
835
- return currentExtensions[type](src.subarray(position, position += length))
855
+ let end;
856
+ return currentExtensions[type](src.subarray(position, end = (position += length)), (readPosition) => {
857
+ position = readPosition;
858
+ try {
859
+ return read();
860
+ } finally {
861
+ position = end;
862
+ }
863
+ })
836
864
  }
837
865
  else
838
866
  throw new Error('Unknown extension type ' + type)
@@ -1075,8 +1103,9 @@ function roundFloat32(float32Number) {
1075
1103
  let multiplier = mult10[((u8Array[3] & 0x7f) << 1) | (u8Array[2] >> 7)];
1076
1104
  return ((multiplier * float32Number + (float32Number > 0 ? 0.5 : -0.5)) >> 0) / multiplier
1077
1105
  }
1078
- function setReadStruct(func) {
1079
- readStruct = func;
1106
+ function setReadStruct(updatedReadStruct, loadedStructs) {
1107
+ readStruct = updatedReadStruct;
1108
+ onLoadedStructures = loadedStructs;
1080
1109
  }
1081
1110
 
1082
1111
  let textEncoder;
@@ -1106,7 +1135,6 @@ class Packr extends Unpackr {
1106
1135
  let hasSharedUpdate;
1107
1136
  let structures;
1108
1137
  let referenceMap;
1109
- let lastSharedStructuresLength = 0;
1110
1138
  let encodeUtf8 = ByteArray.prototype.utf8Write ? function(string, position) {
1111
1139
  return target.utf8Write(string, position, 0xffffffff)
1112
1140
  } : (textEncoder && textEncoder.encodeInto) ?
@@ -1192,7 +1220,7 @@ class Packr extends Unpackr {
1192
1220
  }
1193
1221
  transition[RECORD_SYMBOL] = i + 0x40;
1194
1222
  }
1195
- lastSharedStructuresLength = sharedLength;
1223
+ this.lastNamedStructuresLength = sharedLength;
1196
1224
  }
1197
1225
  if (!isSequential) {
1198
1226
  structures.nextId = sharedLength + 0x40;
@@ -1228,7 +1256,7 @@ class Packr extends Unpackr {
1228
1256
  if (structures) {
1229
1257
  if (serializationsSinceTransitionRebuild < 10)
1230
1258
  serializationsSinceTransitionRebuild++;
1231
- let sharedLength = structures.sharedLength || maxSharedStructures;
1259
+ let sharedLength = structures.sharedLength || 0;
1232
1260
  if (structures.length > sharedLength)
1233
1261
  structures.length = sharedLength;
1234
1262
  if (transitionsCount > 10000) {
@@ -1247,12 +1275,12 @@ class Packr extends Unpackr {
1247
1275
  if (hasSharedUpdate && packr.saveStructures) {
1248
1276
  // we can't rely on start/end with REUSE_BUFFER_MODE since they will (probably) change when we save
1249
1277
  let returnBuffer = target.subarray(start, position$1);
1250
- if (packr.saveStructures(structures, lastSharedStructuresLength) === false) {
1278
+ let newSharedData = prepareStructures(structures, packr);
1279
+ if (packr.saveStructures(newSharedData, newSharedData.isCompatible) === false) {
1251
1280
  // get updated structures and try again if the update failed
1252
- packr._mergeStructures(packr.getStructures());
1253
1281
  return packr.pack(value)
1254
1282
  }
1255
- lastSharedStructuresLength = sharedLength;
1283
+ packr.lastNamedStructuresLength = sharedLength;
1256
1284
  return returnBuffer
1257
1285
  }
1258
1286
  }
@@ -1370,7 +1398,7 @@ class Packr extends Unpackr {
1370
1398
  } else if (type === 'number') {
1371
1399
  if (value >>> 0 === value) {// positive integer, 32-bit or less
1372
1400
  // positive uint
1373
- if (value < 0x40 || (value < 0x80 && this.useRecords === false)) {
1401
+ if (value < 0x20 || (value < 0x80 && this.useRecords === false) || (value < 0x40 && !this.randomAccessStructure)) {
1374
1402
  target[position$1++] = value;
1375
1403
  } else if (value < 0x100) {
1376
1404
  target[position$1++] = 0xcc;
@@ -1770,16 +1798,18 @@ class Packr extends Unpackr {
1770
1798
  }
1771
1799
  };
1772
1800
  const writeStruct = (object, safePrototype) => {
1773
- let newPosition = writeStructSlots(object, target, position$1, structures, makeRoom, (value, newPosition) => {
1801
+ let newPosition = writeStructSlots(object, target, position$1, structures, makeRoom, (value, newPosition, notifySharedUpdate) => {
1802
+ if (notifySharedUpdate)
1803
+ return hasSharedUpdate = true;
1774
1804
  position$1 = newPosition;
1775
1805
  if (start > 0) {
1776
1806
  pack(value);
1777
1807
  if (start == 0)
1778
- return { position: position$1, targetView }; // indicate the buffer was re-allocated
1808
+ return { position: position$1, targetView, target }; // indicate the buffer was re-allocated
1779
1809
  } else
1780
1810
  pack(value);
1781
1811
  return position$1;
1782
- });
1812
+ }, this);
1783
1813
  if (newPosition === 0) // bail and go to a msgpack object
1784
1814
  return writeObject(object, true);
1785
1815
  position$1 = newPosition;
@@ -1794,6 +1824,8 @@ class Packr extends Unpackr {
1794
1824
  clearSharedData() {
1795
1825
  if (this.structures)
1796
1826
  this.structures = [];
1827
+ if (this.typedStructs)
1828
+ this.typedStructs = [];
1797
1829
  }
1798
1830
  }
1799
1831
 
@@ -2013,8 +2045,18 @@ function addExtension$1(extension) {
2013
2045
  }
2014
2046
  addExtension(extension);
2015
2047
  }
2016
- function setWriteStructSlots(func) {
2017
- writeStructSlots = func;
2048
+ function prepareStructures(structures, packr) {
2049
+ structures.isCompatible = (existingStructures) => {
2050
+ let compatible = !existingStructures || ((packr.lastNamedStructuresLength || 0) === existingStructures.length);
2051
+ if (!compatible) // we want to merge these existing structures immediately since we already have it and we are in the right transaction
2052
+ packr._mergeStructures(existingStructures);
2053
+ return compatible;
2054
+ };
2055
+ return structures
2056
+ }
2057
+ function setWriteStructSlots(writeSlots, makeStructures) {
2058
+ writeStructSlots = writeSlots;
2059
+ prepareStructures = makeStructures;
2018
2060
  }
2019
2061
 
2020
2062
  let defaultPackr = new Packr({ useRecords: false });
@@ -2025,374 +2067,816 @@ const { NEVER, ALWAYS, DECIMAL_ROUND, DECIMAL_FIT } = FLOAT32_OPTIONS;
2025
2067
  const REUSE_BUFFER_MODE = 512;
2026
2068
  const RESET_BUFFER_MODE = 1024;
2027
2069
 
2028
- // first four bits
2029
- const hasNonLatin$1 = /[\u0080-\uFFFF]/;
2070
+ const ASCII = 3; // the MIBenum from https://www.iana.org/assignments/character-sets/character-sets.xhtml (and other character encodings could be referenced by MIBenum)
2071
+ const NUMBER = 0;
2072
+ const UTF8 = 2;
2073
+ const OBJECT_DATA = 1;
2074
+ const TYPE_NAMES = ['num', 'object', 'string', 'ascii'];
2030
2075
  const float32Headers = [false, true, true, false, false, true, true, false];
2031
- setWriteStructSlots(writeStruct);
2032
- function writeStruct(object, target, position, structures, makeRoom, pack) {
2033
- let transition = structures.transitions || false;
2034
- let start = position;
2035
- position += 4;
2036
- let queuedReferences = [];
2037
- let uint32 = target.uint32 || (target.uint32 = new Uint32Array(target.buffer));
2076
+ let updatedPosition;
2077
+ const hasNodeBuffer$1 = typeof Buffer !== 'undefined';
2078
+ let textEncoder$1;
2079
+ try {
2080
+ textEncoder$1 = new TextEncoder();
2081
+ } catch (error) {}
2082
+ const encodeUtf8 = hasNodeBuffer$1 ? function(target, string, position) {
2083
+ return target.utf8Write(string, position, 0xffffffff)
2084
+ } : (textEncoder$1 && textEncoder$1.encodeInto) ?
2085
+ function(target, string, position) {
2086
+ return textEncoder$1.encodeInto(string, target.subarray(position)).written
2087
+ } : false;
2088
+ setWriteStructSlots(writeStruct, prepareStructures$1);
2089
+ function writeStruct(object, target, position, structures, makeRoom, pack, packr) {
2090
+ let typedStructs = packr.typedStructs || (packr.typedStructs = []);
2091
+ // note that we rely on pack.js to load stored structures before we get to this point
2038
2092
  let targetView = target.dataView;
2039
- let encoded;
2040
- let stringData = '';
2093
+ let refsStartPosition = (typedStructs.lastStringStart || 100) + position;
2041
2094
  let safeEnd = target.length - 10;
2095
+ let start = position;
2096
+ if (position > safeEnd) {
2097
+ let lastStart = start;
2098
+ target = makeRoom(position);
2099
+ targetView = target.dataView;
2100
+ position -= lastStart;
2101
+ refsStartPosition -= lastStart;
2102
+ start = 0;
2103
+ safeEnd = target.length - 10;
2104
+ }
2105
+
2106
+ let refOffset, refPosition = refsStartPosition;
2107
+
2108
+ let transition = typedStructs.transitions || (typedStructs.transitions = Object.create(null));
2109
+ let nextId = typedStructs.nextId || typedStructs.length;
2110
+ let headerSize =
2111
+ nextId < 0xf ? 1 :
2112
+ nextId < 0xf0 ? 2 :
2113
+ nextId < 0xf000 ? 3 :
2114
+ nextId < 0xf00000 ? 4 : 0;
2115
+ if (headerSize === 0)
2116
+ return 0;
2117
+ position += headerSize;
2118
+ let queuedReferences = [];
2119
+ let keyIndex = 0;
2042
2120
  for (let key in object) {
2121
+ let value = object[key];
2043
2122
  let nextTransition = transition[key];
2044
2123
  if (!nextTransition) {
2045
- return 0; // bail
2046
- //nextTransition = transition[key] = Object.create(null)
2047
- //newTransitions++
2124
+ transition[key] = nextTransition = {
2125
+ key,
2126
+ parent: transition,
2127
+ enumerationOffset: 0,
2128
+ ascii0: null,
2129
+ ascii8: null,
2130
+ num8: null,
2131
+ string16: null,
2132
+ object16: null,
2133
+ num32: null,
2134
+ float64: null
2135
+ };
2048
2136
  }
2049
2137
  if (position > safeEnd) {
2050
- let newPosition = position - start;
2138
+ let lastStart = start;
2051
2139
  target = makeRoom(position);
2052
- position = newPosition;
2140
+ targetView = target.dataView;
2141
+ position -= lastStart;
2142
+ refsStartPosition -= lastStart;
2143
+ refPosition -= lastStart;
2053
2144
  start = 0;
2054
2145
  safeEnd = target.length - 10;
2055
2146
  }
2056
- transition = nextTransition;
2057
- let value = object[key];
2058
2147
  switch (typeof value) {
2059
2148
  case 'number':
2060
- if (value >>> 0 === value && value < 0x20000000) {
2061
- encoded = value;
2149
+ let number = value;
2150
+ if (number >> 0 === number && number < 0x20000000 && number > -0x1f000000) {
2151
+ if (number < 0xf6 && number >= 0 && (nextTransition.num8 || number < 0x20 && !nextTransition.num32)) {
2152
+ transition = nextTransition.num8 || createTypeTransition(nextTransition, NUMBER, 1);
2153
+ target[position++] = number;
2154
+ } else {
2155
+ transition = nextTransition.num32 || createTypeTransition(nextTransition, NUMBER, 4);
2156
+ targetView.setUint32(position, number, true);
2157
+ position += 4;
2158
+ }
2062
2159
  break;
2063
- } else if (value < 0x100000000 && value >= -0x80000000) {
2064
- targetView.setFloat32(position, value, true);
2160
+ } else if (number < 0x100000000 && number >= -0x80000000) {
2161
+ targetView.setFloat32(position, number, true);
2065
2162
  if (float32Headers[target[position + 3] >>> 5]) {
2066
2163
  let xShifted;
2067
2164
  // this checks for rounding of numbers that were encoded in 32-bit float to nearest significant decimal digit that could be preserved
2068
- if (((xShifted = value * mult10[((target[position + 3] & 0x7f) << 1) | (target[position + 2] >> 7)]) >> 0) === xShifted) {
2165
+ if (((xShifted = number * mult10[((target[position + 3] & 0x7f) << 1) | (target[position + 2] >> 7)]) >> 0) === xShifted) {
2166
+ transition = nextTransition.num32 || createTypeTransition(nextTransition, NUMBER, 4);
2069
2167
  position += 4;
2070
- continue;
2168
+ break;
2071
2169
  }
2072
2170
  }
2073
2171
  }
2074
- // fall back to msgpack encoding
2075
- queuedReferences.push(value, position - start);
2076
- position += 4;
2077
- continue;
2172
+ transition = nextTransition.num64 || createTypeTransition(nextTransition, NUMBER, 8);
2173
+ targetView.setFloat64(position, number, true);
2174
+ position += 8;
2175
+ break;
2078
2176
  case 'string':
2079
- if (hasNonLatin$1.test(value)) {
2080
- queuedReferences.push(value, position - start);
2081
- position += 4;
2082
- continue;
2177
+ let strLength = value.length;
2178
+ refOffset = refPosition - refsStartPosition;
2179
+ if ((strLength << 2) + position > safeEnd) {
2180
+ let lastStart = start;
2181
+ target = makeRoom(refPosition);
2182
+ targetView = target.dataView;
2183
+ position -= lastStart;
2184
+ refsStartPosition -= lastStart;
2185
+ refPosition -= lastStart;
2186
+ start = 0;
2187
+ safeEnd = target.length - 10;
2083
2188
  }
2084
- if (value.length < 4) { // we can inline really small strings
2085
- encoded = 0xf8000000 + (value.length << 24) + (value.charCodeAt(0) << 16) + (value.charCodeAt(1) << 8) + (value.charCodeAt(2) || 0);
2086
- // TODO: determining remaining and make max value be a ratio of that (probably 1/256th)
2087
- } else if (value.length < 256 && stringData.length < 61440) {
2088
- // bundle these strings
2089
- encoded = 0x60000000 | (value.length << 16) | stringData.length;
2090
- stringData += value;
2091
- } else { // else queue it
2092
- queuedReferences.push(value, position - start);
2093
- position += 4;
2094
- continue;
2189
+ if (strLength > ((0xff00 + refOffset) >> 2)) {
2190
+ queuedReferences.push(key, value, position - start);
2191
+ break;
2192
+ }
2193
+ let isNotAscii;
2194
+ let strStart = refPosition;
2195
+ if (strLength < 0x40) {
2196
+ let i, c1, c2;
2197
+ for (i = 0; i < strLength; i++) {
2198
+ c1 = value.charCodeAt(i);
2199
+ if (c1 < 0x80) {
2200
+ target[refPosition++] = c1;
2201
+ } else if (c1 < 0x800) {
2202
+ isNotAscii = true;
2203
+ target[refPosition++] = c1 >> 6 | 0xc0;
2204
+ target[refPosition++] = c1 & 0x3f | 0x80;
2205
+ } else if (
2206
+ (c1 & 0xfc00) === 0xd800 &&
2207
+ ((c2 = value.charCodeAt(i + 1)) & 0xfc00) === 0xdc00
2208
+ ) {
2209
+ isNotAscii = true;
2210
+ c1 = 0x10000 + ((c1 & 0x03ff) << 10) + (c2 & 0x03ff);
2211
+ i++;
2212
+ target[refPosition++] = c1 >> 18 | 0xf0;
2213
+ target[refPosition++] = c1 >> 12 & 0x3f | 0x80;
2214
+ target[refPosition++] = c1 >> 6 & 0x3f | 0x80;
2215
+ target[refPosition++] = c1 & 0x3f | 0x80;
2216
+ } else {
2217
+ isNotAscii = true;
2218
+ target[refPosition++] = c1 >> 12 | 0xe0;
2219
+ target[refPosition++] = c1 >> 6 & 0x3f | 0x80;
2220
+ target[refPosition++] = c1 & 0x3f | 0x80;
2221
+ }
2222
+ }
2223
+ } else {
2224
+ refPosition += encodeUtf8(target, value, refPosition);
2225
+ isNotAscii = refPosition - strStart > strLength;
2226
+ }
2227
+ if (refOffset < 0x100) {
2228
+ if (isNotAscii)
2229
+ transition = nextTransition.string8 || createTypeTransition(nextTransition, UTF8, 1);
2230
+ else
2231
+ transition = nextTransition.ascii8 || createTypeTransition(nextTransition, ASCII, 1);
2232
+ target[position++] = refOffset;
2233
+ } else {
2234
+ if (isNotAscii)
2235
+ transition = nextTransition.string16 || createTypeTransition(nextTransition, UTF8, 2);
2236
+ else
2237
+ transition = nextTransition.ascii16 || createTypeTransition(nextTransition, ASCII, 2);
2238
+ targetView.setUint16(position, refOffset, true);
2239
+ position += 2;
2095
2240
  }
2096
2241
  break;
2097
2242
  case 'object':
2098
2243
  if (value) {
2099
- queuedReferences.push(value, position - start);
2100
- position += 4;
2101
- continue;
2244
+ //transition = nextTransition.object16 || createTypeTransition(nextTransition, OBJECT_DATA, 2);
2245
+ queuedReferences.push(key, value, keyIndex);
2246
+ break;
2102
2247
  } else { // null
2103
- encoded = 0xe0000000;
2248
+ nextTransition = anyType(nextTransition, position, targetView, -10); // match CBOR with this
2249
+ if (nextTransition) {
2250
+ transition = nextTransition;
2251
+ position = updatedPosition;
2252
+ } else queuedReferences.push(key, value, keyIndex);
2104
2253
  }
2105
2254
  break;
2106
2255
  case 'boolean':
2107
- encoded = value ? 0xe3000000 : 0xe2000000;
2256
+ transition = nextTransition.num8 || nextTransition.ascii8 || createTypeTransition(nextTransition, NUMBER, 1);
2257
+ target[position++] = value ? 0xf9 : 0xf8; // match CBOR with these
2108
2258
  break;
2109
2259
  case 'undefined':
2110
- encoded = 0xe1000000;
2260
+ nextTransition = anyType(nextTransition, position, targetView, -9); // match CBOR with this
2261
+ if (nextTransition) {
2262
+ transition = nextTransition;
2263
+ position = updatedPosition;
2264
+ } else queuedReferences.push(key, value, keyIndex);
2111
2265
  break;
2112
2266
  }
2113
- targetView.setUint32(position, encoded, true);
2114
- position += 4;
2115
- }
2116
- let recordId = transition[RECORD_SYMBOL];
2117
- if (!(recordId < 1024)) {
2118
- // for now just punt and go back to writeObject
2119
- return 0;
2120
- // newRecord(transition, transition.__keys__ || Object.keys(object), newTransitions, true)
2121
- }
2122
- let stringLength = stringData.length;
2123
- if (stringData) {
2124
- if (position + stringLength > safeEnd) {
2125
- target = makeRoom(position + stringLength);
2126
- }
2127
- position += target.latin1Write(stringData, position, 0xffffffff);
2267
+ keyIndex++;
2128
2268
  }
2129
- target[start] = recordId >> 8;
2130
- target[start + 1] = recordId & 0xff;
2131
- target[start + 2] = stringLength >> 8;
2132
- target[start + 3] = stringLength & 0xff;
2133
- let queued32BitReferences;
2269
+
2134
2270
  for (let i = 0, l = queuedReferences.length; i < l;) {
2271
+ let key = queuedReferences[i++];
2135
2272
  let value = queuedReferences[i++];
2136
- let slotOffset = queuedReferences[i++] + start;
2137
- let offset = position - slotOffset;
2138
- if (offset < 0x1f000000) {
2139
- targetView.setUint32(slotOffset, 0x80000000 | (offset), true);
2273
+ let propertyIndex = queuedReferences[i++];
2274
+ let nextTransition = transition[key];
2275
+ if (!nextTransition) {
2276
+ transition[key] = nextTransition = {
2277
+ key,
2278
+ parent: transition,
2279
+ enumerationOffset: propertyIndex - keyIndex,
2280
+ ascii0: null,
2281
+ ascii8: null,
2282
+ num8: null,
2283
+ string16: null,
2284
+ object16: null,
2285
+ num32: null,
2286
+ float64: null
2287
+ };
2288
+ }
2289
+ let newPosition;
2290
+ if (value) {
2291
+ /*if (typeof value === 'string') { // TODO: we could re-enable long strings
2292
+ if (position + value.length * 3 > safeEnd) {
2293
+ target = makeRoom(position + value.length * 3);
2294
+ position -= start;
2295
+ targetView = target.dataView;
2296
+ start = 0;
2297
+ }
2298
+ newPosition = position + target.utf8Write(value, position, 0xffffffff);
2299
+ } else { */
2300
+ let size;
2301
+ refOffset = refPosition - refsStartPosition;
2302
+ if (refOffset < 0xff00) {
2303
+ transition = nextTransition.object16;
2304
+ if (transition)
2305
+ size = 2;
2306
+ else if ((transition = nextTransition.object32))
2307
+ size = 4;
2308
+ else {
2309
+ transition = createTypeTransition(nextTransition, OBJECT_DATA, 2);
2310
+ size = 2;
2311
+ }
2312
+ } else {
2313
+ transition = nextTransition.object32 || createTypeTransition(nextTransition, OBJECT_DATA, 4);
2314
+ size = 4;
2315
+ }
2316
+ newPosition = pack(value, refPosition);
2317
+ //}
2318
+ if (typeof newPosition === 'object') {
2319
+ // re-allocated
2320
+ refPosition = newPosition.position;
2321
+ targetView = newPosition.targetView;
2322
+ target = newPosition.target;
2323
+ refsStartPosition -= start;
2324
+ position -= start;
2325
+ start = 0;
2326
+ } else
2327
+ refPosition = newPosition;
2328
+ if (size === 2) {
2329
+ targetView.setUint16(position, refOffset, true);
2330
+ position += 2;
2331
+ } else {
2332
+ targetView.setUint32(position, refOffset, true);
2333
+ position += 4;
2334
+ }
2140
2335
  } else {
2141
- if (!queued32BitReferences)
2142
- queued32BitReferences = [];
2143
- queued32BitReferences.push({slotOffset, offset: position - start});
2336
+ transition = nextTransition.object16 || createTypeTransition(nextTransition, OBJECT_DATA, 2);
2337
+ targetView.setInt16(position, value === null ? -10 : -9, true);
2338
+ position += 2;
2144
2339
  }
2145
- let newPosition = pack(value, position);
2146
- if (typeof newPosition === 'object') {
2147
- // re-allocated
2148
- position = newPosition.position;
2149
- targetView = newPosition.targetView;
2150
- start = 0;
2151
- } else
2152
- position = newPosition;
2153
- }
2154
- if (queued32BitReferences) {
2155
- // TODO: makeRoom
2156
- for (let i = 0, l = queued32BitReferences.length; i < l; i++) {
2157
- let ref = queued32BitReferences[i];
2158
- targetView.setUint32(ref.slotOffset, 0xa0000000 - ((l - i) << 2), true);
2159
- targetView.setUint32(position, ref.offset, true);
2160
- position += 4;
2340
+ keyIndex++;
2341
+ }
2342
+
2343
+
2344
+ let recordId = transition[RECORD_SYMBOL];
2345
+ if (recordId == null) {
2346
+ recordId = packr.typedStructs.length;
2347
+ let structure = [];
2348
+ let nextTransition = transition;
2349
+ let key, type;
2350
+ while ((type = nextTransition.__type) !== undefined) {
2351
+ let size = nextTransition.__size;
2352
+ nextTransition = nextTransition.__parent;
2353
+ key = nextTransition.key;
2354
+ let property = [type, size, key];
2355
+ if (nextTransition.enumerationOffset)
2356
+ property.push(nextTransition.enumerationOffset);
2357
+ structure.push(property);
2358
+ nextTransition = nextTransition.parent;
2161
2359
  }
2360
+ structure.reverse();
2361
+ transition[RECORD_SYMBOL] = recordId;
2362
+ packr.typedStructs[recordId] = structure;
2363
+ pack(null, 0, true); // special call to notify that structures have been updated
2162
2364
  }
2163
2365
 
2164
- return position;
2366
+
2367
+ switch (headerSize) {
2368
+ case 1:
2369
+ if (recordId >= 0x10) return 0;
2370
+ target[start] = recordId + 0x20;
2371
+ break;
2372
+ case 2:
2373
+ if (recordId >= 0x100) return 0;
2374
+ target[start] = 0x38;
2375
+ target[start + 1] = recordId;
2376
+ break;
2377
+ case 3:
2378
+ if (recordId >= 0x10000) return 0;
2379
+ target[start] = 0x39;
2380
+ target.setUint16(start + 1, recordId, true);
2381
+ break;
2382
+ case 4:
2383
+ if (recordId >= 0x1000000) return 0;
2384
+ target.setUint32(start, (recordId << 8) + 0x3a, true);
2385
+ break;
2386
+ }
2387
+
2388
+ if (position < refsStartPosition) {
2389
+ if (refsStartPosition === refPosition)
2390
+ return position; // no refs
2391
+ // adjust positioning
2392
+ target.copyWithin(position, refsStartPosition, refPosition);
2393
+ refPosition += position - refsStartPosition;
2394
+ typedStructs.lastStringStart = position - start;
2395
+ } else if (position > refsStartPosition) {
2396
+ if (refsStartPosition === refPosition)
2397
+ return position; // no refs
2398
+ typedStructs.lastStringStart = position - start;
2399
+ return writeStruct(object, target, start, structures, makeRoom, pack, packr);
2400
+ }
2401
+ return refPosition;
2402
+ }
2403
+ function anyType(transition, position, targetView, value) {
2404
+ let nextTransition;
2405
+ if ((nextTransition = transition.ascii8 || transition.num8)) {
2406
+ targetView.setInt8(position, value, true);
2407
+ updatedPosition = position + 1;
2408
+ return nextTransition;
2409
+ }
2410
+ if ((nextTransition = transition.string16 || transition.object16)) {
2411
+ targetView.setInt16(position, value, true);
2412
+ updatedPosition = position + 2;
2413
+ return nextTransition;
2414
+ }
2415
+ if (nextTransition = transition.num32) {
2416
+ targetView.setUint32(position, 0xe0000100 + value, true);
2417
+ updatedPosition = position + 4;
2418
+ return nextTransition;
2419
+ }
2420
+ // transition.float64
2421
+ if (nextTransition = transition.num64) {
2422
+ targetView.setFloat64(position, NaN, true);
2423
+ targetView.setInt8(position, value);
2424
+ updatedPosition = position + 8;
2425
+ return nextTransition;
2426
+ }
2427
+ updatedPosition = position;
2428
+ // TODO: can we do an "any" type where we defer the decision?
2429
+ return;
2430
+ }
2431
+ function createTypeTransition(transition, type, size) {
2432
+ let typeName = TYPE_NAMES[type] + (size << 3);
2433
+ let newTransition = transition[typeName] || (transition[typeName] = Object.create(null));
2434
+ newTransition.__type = type;
2435
+ newTransition.__size = size;
2436
+ newTransition.__parent = transition;
2437
+ return newTransition;
2438
+ }
2439
+ function onLoadedStructures$1(sharedData) {
2440
+ if (!(sharedData instanceof Map))
2441
+ return sharedData;
2442
+ let typed = sharedData.get('typed') || [];
2443
+ if (Object.isFrozen(typed))
2444
+ typed = typed.map(structure => structure.slice(0));
2445
+ let named = sharedData.get('named');
2446
+ let transitions = Object.create(null);
2447
+ for (let i = 0, l = typed.length; i < l; i++) {
2448
+ let structure = typed[i];
2449
+ let transition = transitions;
2450
+ for (let [type, size, key] of structure) {
2451
+ let nextTransition = transition[key];
2452
+ if (!nextTransition) {
2453
+ transition[key] = nextTransition = {
2454
+ key,
2455
+ parent: transition,
2456
+ enumerationOffset: 0,
2457
+ ascii0: null,
2458
+ ascii8: null,
2459
+ num8: null,
2460
+ string16: null,
2461
+ object16: null,
2462
+ num32: null,
2463
+ float64: null
2464
+ };
2465
+ }
2466
+ transition = createTypeTransition(nextTransition, type, size);
2467
+ }
2468
+ transition[RECORD_SYMBOL] = i;
2469
+ }
2470
+ typed.transitions = transitions;
2471
+ this.typedStructs = typed;
2472
+ this.lastTypedStructuresLength = typed.length;
2473
+ return named;
2165
2474
  }
2166
2475
  var sourceSymbol = Symbol('source');
2167
- function readStruct$1(src, position, srcEnd, structure, unpackr) {
2168
- var stringLength = (src[position++] << 8) | src[position++];
2476
+ function readStruct$1(src, position, srcEnd, unpackr) {
2477
+ // var stringLength = (src[position++] << 8) | src[position++];
2478
+ let recordId = src[position++] - 0x20;
2479
+ if (recordId >= 24) {
2480
+ switch(recordId) {
2481
+ case 24: recordId = src[position++]; break;
2482
+ // little endian:
2483
+ case 25: recordId = src[position++] + (src[position++] << 8); break;
2484
+ case 26: recordId = src[position++] + (src[position++] << 8) + (src[position++] << 16); break;
2485
+ case 27: recordId = src[position++] + (src[position++] << 8) + (src[position++] << 16) + (src[position++] << 24); break;
2486
+ }
2487
+ }
2488
+ let structure = unpackr.typedStructs?.[recordId];
2489
+ if (!structure) {
2490
+ // copy src buffer because getStructures will override it
2491
+ src = Uint8Array.prototype.slice.call(src, position, srcEnd);
2492
+ srcEnd -= position;
2493
+ position = 0;
2494
+ unpackr._mergeStructures(unpackr.getStructures());
2495
+ if (!unpackr.typedStructs)
2496
+ throw new Error('Could not find any shared typed structures');
2497
+ unpackr.lastTypedStructuresLength = unpackr.typedStructs.length;
2498
+ structure = unpackr.typedStructs[recordId];
2499
+ if (!structure)
2500
+ throw new Error('Could not find typed structure ' + recordId);
2501
+ }
2169
2502
  var construct = structure.construct;
2170
2503
  if (!construct) {
2171
- construct = structure.construct = function() {
2504
+ construct = structure.construct = function LazyObject() {
2172
2505
  };
2173
2506
  var prototype = construct.prototype;
2507
+ let properties = [];
2174
2508
  Object.defineProperty(prototype, 'toJSON', {
2175
- get() {
2509
+ value() {
2176
2510
  // return an enumerable object with own properties to JSON stringify
2177
2511
  let resolved = {};
2178
- for (let i = 0, l = structure.length; i < l; i++) {
2179
- let key = structure[i];
2512
+ for (let i = 0, l = properties.length; i < l; i++) {
2513
+ let key = properties[i].key;
2180
2514
  resolved[key] = this[key];
2181
2515
  }
2182
2516
  return resolved;
2183
2517
  },
2184
2518
  // not enumerable or anything
2185
2519
  });
2520
+ let currentOffset = 0;
2521
+ let lastRefProperty;
2186
2522
  for (let i = 0, l = structure.length; i < l; i++) {
2187
- let key = structure[i];
2188
- Object.defineProperty(prototype, key, {
2189
- get() {
2190
- let source = this[sourceSymbol];
2191
- let src = source.src;
2192
- //let uint32 = src.uint32 || (src.uint32 = new Uint32Array(src.buffer, src.byteOffset, src.byteLength));
2193
- let dataView = src.dataView || (src.dataView = new DataView(src.buffer, src.byteOffset, src.byteLength));
2194
- let position = source.position + (i << 2);
2195
- let value = dataView.getUint32(position, true);
2196
- let start;
2197
- switch (value >>> 29) {
2198
- case 0:
2199
- return value;
2200
- case 3:
2201
- if (value & 0x10000000) {
2202
- start = (value & 0xffff) + position;
2203
- return src.toString('utf8', start, start + ((value >> 16) & 0x7ff));
2204
- } else {
2205
- if (!source.srcString) {
2206
- start = source.position + (l << 2);
2207
- source.srcString = src.toString('latin1', start, start + source.stringLength);
2208
- }
2209
- start = value & 0xffff;
2210
- return source.srcString.slice(start, start + ((value >> 16) & 0x7ff));
2211
- }
2212
- case 4:
2213
- start = (0x1fffffff & value) + position;
2214
- let end = source.srcEnd;
2215
- for (let next = i + 1; next < l; next++) {
2216
- position = source.position + (next << 2);
2217
- let nextValue = dataView.getUint32(position, true); if ((nextValue & 0xe0000000) == -0x80000000) {
2218
- end = (0x1fffffff & nextValue) + position;
2523
+ let definition = structure[i];
2524
+ let [ type, size, key, enumerationOffset ] = definition;
2525
+ let property = {
2526
+ key,
2527
+ offset: currentOffset,
2528
+ };
2529
+ if (enumerationOffset)
2530
+ properties.splice(i + enumerationOffset, 0, property);
2531
+ else
2532
+ properties.push(property);
2533
+ let getRef;
2534
+ switch(size) { // TODO: Move into a separate function
2535
+ case 0: getRef = () => 0; break;
2536
+ case 1:
2537
+ getRef = (source, position) => {
2538
+ let ref = source.src[position + property.offset];
2539
+ return ref >= 0xf6 ? toConstant(ref) : ref;
2540
+ };
2541
+ break;
2542
+ case 2:
2543
+ getRef = (source, position) => {
2544
+ let src = source.src;
2545
+ let dataView = src.dataView || (src.dataView = new DataView(src.buffer, src.byteOffset, src.byteLength));
2546
+ let ref = dataView.getUint16(position + property.offset, true);
2547
+ return ref >= 0xff00 ? toConstant(ref & 0xff) : ref;
2548
+ };
2549
+ break;
2550
+ case 4:
2551
+ getRef = (source, position) => {
2552
+ let src = source.src;
2553
+ let dataView = src.dataView || (src.dataView = new DataView(src.buffer, src.byteOffset, src.byteLength));
2554
+ let ref = dataView.getUint32(position + property.offset, true);
2555
+ return ref >= 0xffffff00 ? toConstant(ref & 0xff) : ref;
2556
+ };
2557
+ break;
2558
+ }
2559
+ property.getRef = getRef;
2560
+ currentOffset += size;
2561
+ let get;
2562
+ switch(type) {
2563
+ case ASCII:
2564
+ if (lastRefProperty && !lastRefProperty.next)
2565
+ lastRefProperty.next = property;
2566
+ lastRefProperty = property;
2567
+ property.multiGetCount = 0;
2568
+ get = function() {
2569
+ let source = this[sourceSymbol];
2570
+ let src = source.src;
2571
+ let position = source.position;
2572
+ let refStart = currentOffset + position;
2573
+ let ref = getRef(source, position);
2574
+ if (typeof ref !== 'number') return ref;
2575
+
2576
+ let end, next = property.next;
2577
+ while(next) {
2578
+ end = next.getRef(source, position);
2579
+ if (typeof end === 'number')
2580
+ break;
2581
+ else
2582
+ end = null;
2583
+ next = next.next;
2584
+ }
2585
+ if (end == null)
2586
+ end = source.srcEnd - refStart;
2587
+ if (source.srcString) {
2588
+ return source.srcString.slice(ref, end);
2589
+ }
2590
+ /*if (property.multiGetCount > 0) {
2591
+ let asciiEnd;
2592
+ next = firstRefProperty;
2593
+ let dataView = src.dataView || (src.dataView = new DataView(src.buffer, src.byteOffset, src.byteLength));
2594
+ do {
2595
+ asciiEnd = dataView.getUint16(source.position + next.offset, true);
2596
+ if (asciiEnd < 0xff00)
2219
2597
  break;
2598
+ else
2599
+ asciiEnd = null;
2600
+ } while((next = next.next));
2601
+ if (asciiEnd == null)
2602
+ asciiEnd = source.srcEnd - refStart
2603
+ source.srcString = src.toString('latin1', refStart, refStart + asciiEnd);
2604
+ return source.srcString.slice(ref, end);
2605
+ }
2606
+ if (source.prevStringGet) {
2607
+ source.prevStringGet.multiGetCount += 2;
2608
+ } else {
2609
+ source.prevStringGet = property;
2610
+ property.multiGetCount--;
2611
+ }*/
2612
+ return readString(src, ref + refStart, end - ref);
2613
+ //return src.toString('latin1', ref + refStart, end + refStart);
2614
+ };
2615
+ break;
2616
+ case UTF8: case OBJECT_DATA:
2617
+ if (lastRefProperty && !lastRefProperty.next)
2618
+ lastRefProperty.next = property;
2619
+ lastRefProperty = property;
2620
+ get = function() {
2621
+ let source = this[sourceSymbol];
2622
+ let position = source.position;
2623
+ let refStart = currentOffset + position;
2624
+ let ref = getRef(source, position);
2625
+ if (typeof ref !== 'number') return ref;
2626
+ let src = source.src;
2627
+ let end, next = property.next;
2628
+ while(next) {
2629
+ end = next.getRef(source, position);
2630
+ if (typeof end === 'number')
2631
+ break;
2632
+ else
2633
+ end = null;
2634
+ next = next.next;
2635
+ }
2636
+ if (end == null)
2637
+ end = source.srcEnd - refStart;
2638
+ if (type === UTF8) {
2639
+ return src.toString('utf8', ref + refStart, end + refStart);
2640
+ } else {
2641
+ return unpackr.unpack(src, { start: ref + refStart, end: end + refStart }); // could reuse this object
2642
+ }
2643
+ };
2644
+ break;
2645
+ case NUMBER:
2646
+ switch(size) {
2647
+ case 4:
2648
+ get = function () {
2649
+ let source = this[sourceSymbol];
2650
+ let src = source.src;
2651
+ let dataView = src.dataView || (src.dataView = new DataView(src.buffer, src.byteOffset, src.byteLength));
2652
+ let position = source.position + property.offset;
2653
+ let value = dataView.getInt32(position, true);
2654
+ if (value < 0x20000000) {
2655
+ if (value > -0x1f000000)
2656
+ return value;
2657
+ if (value > -0x20000000)
2658
+ return toConstant(value & 0xff);
2220
2659
  }
2221
- }
2222
- return unpackr.unpack(src.slice(start, end));
2223
- case 1: case 2: case 5: case 6:
2224
- let fValue = dataView.getFloat32(position, true);
2225
- // this does rounding of numbers that were encoded in 32-bit float to nearest significant decimal digit that could be preserved
2226
- let multiplier = mult10[((src[position + 3] & 0x7f) << 1) | (src[position + 2] >> 7)];
2227
- return ((multiplier * fValue + (fValue > 0 ? 0.5 : -0.5)) >> 0) / multiplier;
2228
- case 7:
2229
- switch((value >> 24) & 0x1f) {
2230
- case 0: return null;
2231
- case 1: return undefined;
2232
- case 2: return false;
2233
- case 3: return true;
2234
- case 8: return dataView.getFloat64(position + (value & 0x3ffffff), true);
2235
- case 0x18: return '';
2236
- case 0x19: return String.fromCharCode((value >> 16) & 0xff);
2237
- case 0x1a: return String.fromCharCode((value >> 16) & 0xff, (value >> 8) & 0xff);
2238
- case 0x1b: return String.fromCharCode((value >> 16) & 0xff, (value >> 8) & 0xff, value & 0xff);
2239
- default: throw new Error('Unknown constant');
2240
- }
2660
+ let fValue = dataView.getFloat32(position, true);
2661
+ // this does rounding of numbers that were encoded in 32-bit float to nearest significant decimal digit that could be preserved
2662
+ let multiplier = mult10[((src[position + 3] & 0x7f) << 1) | (src[position + 2] >> 7)];
2663
+ return ((multiplier * fValue + (fValue > 0 ? 0.5 : -0.5)) >> 0) / multiplier;
2664
+ };
2665
+ break;
2666
+ case 8:
2667
+ get = function () {
2668
+ let source = this[sourceSymbol];
2669
+ let src = source.src;
2670
+ let dataView = src.dataView || (src.dataView = new DataView(src.buffer, src.byteOffset, src.byteLength));
2671
+ let value = dataView.getFloat64(source.position + property.offset, true);
2672
+ if (isNaN(value)) {
2673
+ let byte = src[source.position + property.offset];
2674
+ if (byte >= 0xf6)
2675
+ return toConstant(byte);
2676
+ }
2677
+ return value;
2678
+ };
2679
+ break;
2680
+ case 1:
2681
+ get = function () {
2682
+ let source = this[sourceSymbol];
2683
+ let src = source.src;
2684
+ let value = src[source.position + property.offset];
2685
+ return value < 0xf6 ? value : toConstant(value);
2686
+ };
2687
+ break;
2241
2688
  }
2242
- },
2243
- enumerable: true,
2244
- });
2689
+ }
2690
+ property.get = get;
2245
2691
  }
2692
+ for (let property of properties) // assign in enumeration order
2693
+ Object.defineProperty(prototype, property.key, { get: property.get, enumerable: true });
2246
2694
  }
2247
2695
  var instance = new construct();
2248
2696
  instance[sourceSymbol] = {
2249
2697
  src,
2250
- uint32: src.uint32,
2251
2698
  position,
2252
2699
  srcString: '',
2253
- srcEnd,
2254
- stringLength
2700
+ srcEnd
2255
2701
  };
2256
2702
  return instance;
2257
2703
  }
2258
- setReadStruct(readStruct$1);
2259
-
2260
- class PackrStream extends stream.Transform {
2261
- constructor(options) {
2262
- if (!options)
2263
- options = {};
2264
- options.writableObjectMode = true;
2265
- super(options);
2266
- options.sequential = true;
2267
- this.packr = options.packr || new Packr(options);
2268
- }
2269
- _transform(value, encoding, callback) {
2270
- this.push(this.packr.pack(value));
2271
- callback();
2272
- }
2273
- }
2274
-
2275
- class UnpackrStream extends stream.Transform {
2276
- constructor(options) {
2277
- if (!options)
2278
- options = {};
2279
- options.objectMode = true;
2280
- super(options);
2281
- options.structures = [];
2282
- this.unpackr = options.unpackr || new Unpackr(options);
2283
- }
2284
- _transform(chunk, encoding, callback) {
2285
- if (this.incompleteBuffer) {
2286
- chunk = Buffer.concat([this.incompleteBuffer, chunk]);
2287
- this.incompleteBuffer = null;
2288
- }
2289
- let values;
2290
- try {
2291
- values = this.unpackr.unpackMultiple(chunk);
2292
- } catch(error) {
2293
- if (error.incomplete) {
2294
- this.incompleteBuffer = chunk.slice(error.lastPosition);
2295
- values = error.values;
2296
- }
2297
- else
2298
- throw error
2299
- } finally {
2300
- for (let value of values || []) {
2301
- if (value === null)
2302
- value = this.getNullValue();
2303
- this.push(value);
2304
- }
2305
- }
2306
- if (callback) callback();
2307
- }
2308
- getNullValue() {
2309
- return Symbol.for(null)
2310
- }
2704
+ function toConstant(code) {
2705
+ switch(code) {
2706
+ case 0xf6: return null;
2707
+ case 0xf7: return undefined;
2708
+ case 0xf8: return false;
2709
+ case 0xf9: return true;
2710
+ }
2711
+ throw new Error('Unknown constant');
2311
2712
  }
2713
+ function prepareStructures$1(structures, packr) {
2714
+ if (packr.typedStructs) {
2715
+ let structMap = new Map();
2716
+ structMap.set('named', structures);
2717
+ structMap.set('typed', packr.typedStructs);
2718
+ structures = structMap;
2719
+ }
2720
+ let lastTypedStructuresLength = packr.lastTypedStructuresLength || 0;
2721
+ structures.isCompatible = existing => {
2722
+ let compatible = true;
2723
+ if (existing instanceof Map) {
2724
+ let named = existing.get('named') || [];
2725
+ if (named.length !== (packr.lastNamedStructuresLength || 0))
2726
+ compatible = false;
2727
+ let typed = existing.get('typed') || [];
2728
+ if (typed.length !== lastTypedStructuresLength)
2729
+ compatible = false;
2730
+ } else if (existing instanceof Array) {
2731
+ if (existing.length !== (packr.lastNamedStructuresLength || 0))
2732
+ compatible = false;
2733
+ }
2734
+ if (!compatible)
2735
+ packr._mergeStructures(existing);
2736
+ return compatible;
2737
+ };
2738
+ packr.lastTypedStructuresLength = packr.typedStructs?.length;
2739
+ return structures;
2740
+ }
2741
+
2742
+ setReadStruct(readStruct$1, onLoadedStructures$1);
2312
2743
 
2313
- /**
2314
- * Given an Iterable first argument, returns an Iterable where each value is packed as a Buffer
2315
- * If the argument is only Async Iterable, the return value will be an Async Iterable.
2316
- * @param {Iterable|Iterator|AsyncIterable|AsyncIterator} objectIterator - iterable source, like a Readable object stream, an array, Set, or custom object
2317
- * @param {options} [options] - msgpackr pack options
2318
- * @returns {IterableIterator|Promise.<AsyncIterableIterator>}
2319
- */
2320
- function packIter (objectIterator, options = {}) {
2321
- if (!objectIterator || typeof objectIterator !== 'object') {
2322
- throw new Error('first argument must be an Iterable, Async Iterable, or a Promise for an Async Iterable')
2323
- } else if (typeof objectIterator[Symbol.iterator] === 'function') {
2324
- return packIterSync(objectIterator, options)
2325
- } else if (typeof objectIterator.then === 'function' || typeof objectIterator[Symbol.asyncIterator] === 'function') {
2326
- return packIterAsync(objectIterator, options)
2327
- } else {
2328
- throw new Error('first argument must be an Iterable, Async Iterable, Iterator, Async Iterator, or a Promise')
2329
- }
2330
- }
2331
-
2332
- function * packIterSync (objectIterator, options) {
2333
- const packr = new Packr(options);
2334
- for (const value of objectIterator) {
2335
- yield packr.pack(value);
2336
- }
2337
- }
2338
-
2339
- async function * packIterAsync (objectIterator, options) {
2340
- const packr = new Packr(options);
2341
- for await (const value of objectIterator) {
2342
- yield packr.pack(value);
2343
- }
2344
- }
2345
-
2346
- /**
2347
- * Given an Iterable/Iterator input which yields buffers, returns an IterableIterator which yields sync decoded objects
2348
- * Or, given an Async Iterable/Iterator which yields promises resolving in buffers, returns an AsyncIterableIterator.
2349
- * @param {Iterable|Iterator|AsyncIterable|AsyncIterableIterator} bufferIterator
2350
- * @param {object} [options] - unpackr options
2351
- * @returns {IterableIterator|Promise.<AsyncIterableIterator}
2352
- */
2353
- function unpackIter (bufferIterator, options = {}) {
2354
- if (!bufferIterator || typeof bufferIterator !== 'object') {
2355
- throw new Error('first argument must be an Iterable, Async Iterable, Iterator, Async Iterator, or a promise')
2356
- }
2357
-
2358
- const unpackr = new Unpackr(options);
2359
- let incomplete;
2360
- const parser = (chunk) => {
2361
- let yields;
2362
- // if there's incomplete data from previous chunk, concatinate and try again
2363
- if (incomplete) {
2364
- chunk = Buffer.concat([incomplete, chunk]);
2365
- incomplete = undefined;
2366
- }
2367
-
2368
- try {
2369
- yields = unpackr.unpackMultiple(chunk);
2370
- } catch (err) {
2371
- if (err.incomplete) {
2372
- incomplete = chunk.slice(err.lastPosition);
2373
- yields = err.values;
2374
- } else {
2375
- throw err
2376
- }
2377
- }
2378
- return yields
2379
- };
2380
-
2381
- if (typeof bufferIterator[Symbol.iterator] === 'function') {
2382
- return (function * iter () {
2383
- for (const value of bufferIterator) {
2384
- yield * parser(value);
2385
- }
2386
- })()
2387
- } else if (typeof bufferIterator[Symbol.asyncIterator] === 'function') {
2388
- return (async function * iter () {
2389
- for await (const value of bufferIterator) {
2390
- yield * parser(value);
2391
- }
2392
- })()
2393
- }
2394
- }
2395
- const decodeIter = unpackIter;
2744
+ class PackrStream extends stream.Transform {
2745
+ constructor(options) {
2746
+ if (!options)
2747
+ options = {};
2748
+ options.writableObjectMode = true;
2749
+ super(options);
2750
+ options.sequential = true;
2751
+ this.packr = options.packr || new Packr(options);
2752
+ }
2753
+ _transform(value, encoding, callback) {
2754
+ this.push(this.packr.pack(value));
2755
+ callback();
2756
+ }
2757
+ }
2758
+
2759
+ class UnpackrStream extends stream.Transform {
2760
+ constructor(options) {
2761
+ if (!options)
2762
+ options = {};
2763
+ options.objectMode = true;
2764
+ super(options);
2765
+ options.structures = [];
2766
+ this.unpackr = options.unpackr || new Unpackr(options);
2767
+ }
2768
+ _transform(chunk, encoding, callback) {
2769
+ if (this.incompleteBuffer) {
2770
+ chunk = Buffer.concat([this.incompleteBuffer, chunk]);
2771
+ this.incompleteBuffer = null;
2772
+ }
2773
+ let values;
2774
+ try {
2775
+ values = this.unpackr.unpackMultiple(chunk);
2776
+ } catch(error) {
2777
+ if (error.incomplete) {
2778
+ this.incompleteBuffer = chunk.slice(error.lastPosition);
2779
+ values = error.values;
2780
+ }
2781
+ else
2782
+ throw error
2783
+ } finally {
2784
+ for (let value of values || []) {
2785
+ if (value === null)
2786
+ value = this.getNullValue();
2787
+ this.push(value);
2788
+ }
2789
+ }
2790
+ if (callback) callback();
2791
+ }
2792
+ getNullValue() {
2793
+ return Symbol.for(null)
2794
+ }
2795
+ }
2796
+
2797
+ /**
2798
+ * Given an Iterable first argument, returns an Iterable where each value is packed as a Buffer
2799
+ * If the argument is only Async Iterable, the return value will be an Async Iterable.
2800
+ * @param {Iterable|Iterator|AsyncIterable|AsyncIterator} objectIterator - iterable source, like a Readable object stream, an array, Set, or custom object
2801
+ * @param {options} [options] - msgpackr pack options
2802
+ * @returns {IterableIterator|Promise.<AsyncIterableIterator>}
2803
+ */
2804
+ function packIter (objectIterator, options = {}) {
2805
+ if (!objectIterator || typeof objectIterator !== 'object') {
2806
+ throw new Error('first argument must be an Iterable, Async Iterable, or a Promise for an Async Iterable')
2807
+ } else if (typeof objectIterator[Symbol.iterator] === 'function') {
2808
+ return packIterSync(objectIterator, options)
2809
+ } else if (typeof objectIterator.then === 'function' || typeof objectIterator[Symbol.asyncIterator] === 'function') {
2810
+ return packIterAsync(objectIterator, options)
2811
+ } else {
2812
+ throw new Error('first argument must be an Iterable, Async Iterable, Iterator, Async Iterator, or a Promise')
2813
+ }
2814
+ }
2815
+
2816
+ function * packIterSync (objectIterator, options) {
2817
+ const packr = new Packr(options);
2818
+ for (const value of objectIterator) {
2819
+ yield packr.pack(value);
2820
+ }
2821
+ }
2822
+
2823
+ async function * packIterAsync (objectIterator, options) {
2824
+ const packr = new Packr(options);
2825
+ for await (const value of objectIterator) {
2826
+ yield packr.pack(value);
2827
+ }
2828
+ }
2829
+
2830
+ /**
2831
+ * Given an Iterable/Iterator input which yields buffers, returns an IterableIterator which yields sync decoded objects
2832
+ * Or, given an Async Iterable/Iterator which yields promises resolving in buffers, returns an AsyncIterableIterator.
2833
+ * @param {Iterable|Iterator|AsyncIterable|AsyncIterableIterator} bufferIterator
2834
+ * @param {object} [options] - unpackr options
2835
+ * @returns {IterableIterator|Promise.<AsyncIterableIterator}
2836
+ */
2837
+ function unpackIter (bufferIterator, options = {}) {
2838
+ if (!bufferIterator || typeof bufferIterator !== 'object') {
2839
+ throw new Error('first argument must be an Iterable, Async Iterable, Iterator, Async Iterator, or a promise')
2840
+ }
2841
+
2842
+ const unpackr = new Unpackr(options);
2843
+ let incomplete;
2844
+ const parser = (chunk) => {
2845
+ let yields;
2846
+ // if there's incomplete data from previous chunk, concatinate and try again
2847
+ if (incomplete) {
2848
+ chunk = Buffer.concat([incomplete, chunk]);
2849
+ incomplete = undefined;
2850
+ }
2851
+
2852
+ try {
2853
+ yields = unpackr.unpackMultiple(chunk);
2854
+ } catch (err) {
2855
+ if (err.incomplete) {
2856
+ incomplete = chunk.slice(err.lastPosition);
2857
+ yields = err.values;
2858
+ } else {
2859
+ throw err
2860
+ }
2861
+ }
2862
+ return yields
2863
+ };
2864
+
2865
+ if (typeof bufferIterator[Symbol.iterator] === 'function') {
2866
+ return (function * iter () {
2867
+ for (const value of bufferIterator) {
2868
+ yield * parser(value);
2869
+ }
2870
+ })()
2871
+ } else if (typeof bufferIterator[Symbol.asyncIterator] === 'function') {
2872
+ return (async function * iter () {
2873
+ for await (const value of bufferIterator) {
2874
+ yield * parser(value);
2875
+ }
2876
+ })()
2877
+ }
2878
+ }
2879
+ const decodeIter = unpackIter;
2396
2880
  const encodeIter = packIter;
2397
2881
 
2398
2882
  const useRecords = false;