msgpackr 1.7.0-alpha1 → 1.7.0-alpha4

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