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/SECURITY.md CHANGED
@@ -1,11 +1,11 @@
1
- # Security Policy
2
-
3
- ## Supported Versions
4
-
5
- | Version | Supported |
6
- | ------- | ------------------ |
7
- | 1.4.x | :white_check_mark: |
8
-
9
- ## Reporting a Vulnerability
10
-
11
- Please report security vulnerabilities to kriszyp@gmail.com.
1
+ # Security Policy
2
+
3
+ ## Supported Versions
4
+
5
+ | Version | Supported |
6
+ | ------- | ------------------ |
7
+ | 1.4.x | :white_check_mark: |
8
+
9
+ ## Reporting a Vulnerability
10
+
11
+ Please report security vulnerabilities to kriszyp@gmail.com.
package/benchmark.md CHANGED
@@ -1,67 +1,67 @@
1
- Here are more comprehensive benchmarks. This is comparison with the next fastest JS projects using the benchmark tool from `msgpack-lite` (and data is from some clinical research data we use that has a good mix of different value types and structures). It also includes comparison to V8 native JSON functionality, and JavaScript Avro (`avsc`, a very optimized Avro implementation):
2
-
3
- operation | op | ms | op/s
4
- ---------------------------------------------------------- | ------: | ----: | -----:
5
- buf = Buffer(JSON.stringify(obj)); | 82000 | 5004 | 16386
6
- obj = JSON.parse(buf); | 88600 | 5000 | 17720
7
- require("msgpackr").pack(obj); | 161500 | 5002 | 32287
8
- require("msgpackr").unpack(buf); | 94600 | 5004 | 18904
9
- msgpackr w/ shared structures: packr.pack(obj); | 178400 | 5002 | 35665
10
- msgpackr w/ shared structures: packr.unpack(buf); | 376700 | 5000 | 75340
11
- buf = require("msgpack-lite").encode(obj); | 30100 | 5012 | 6005
12
- obj = require("msgpack-lite").decode(buf); | 16200 | 5001 | 3239
13
- buf = require("notepack").encode(obj); | 62600 | 5005 | 12507
14
- obj = require("notepack").decode(buf); | 32400 | 5007 | 6470
15
- require("what-the-pack")... encoder.encode(obj); | 63500 | 5002 | 12694
16
- require("what-the-pack")... encoder.decode(buf); | 32000 | 5001 | 6398
17
- require("avsc")...make schema/type...type.toBuffer(obj); | 84600 | 5003 | 16909
18
- require("avsc")...make schema/type...type.toBuffer(obj); | 99300 | 5001 | 19856
19
-
20
- (`avsc` is schema-based and more comparable in style to msgpackr with shared structures).
21
-
22
- Here is a benchmark of streaming data (again borrowed from `msgpack-lite`'s benchmarking), where msgpackr is able to take advantage of the structured record extension and really pull away from other tools:
23
-
24
- operation (1000000 x 2) | op | ms | op/s
25
- ------------------------------------------------ | ------: | ----: | -----:
26
- new PackrStream().write(obj); | 1000000 | 372 | 2688172
27
- new UnpackrStream().write(buf); | 1000000 | 247 | 4048582
28
- stream.write(msgpack.encode(obj)); | 1000000 | 2898 | 345065
29
- stream.write(msgpack.decode(buf)); | 1000000 | 1969 | 507872
30
- stream.write(notepack.encode(obj)); | 1000000 | 901 | 1109877
31
- stream.write(notepack.decode(buf)); | 1000000 | 1012 | 988142
32
- msgpack.Encoder().on("data",ondata).encode(obj); | 1000000 | 1763 | 567214
33
- msgpack.createDecodeStream().write(buf); | 1000000 | 2222 | 450045
34
- msgpack.createEncodeStream().write(obj); | 1000000 | 1577 | 634115
35
- msgpack.Decoder().on("data",ondata).decode(buf); | 1000000 | 2246 | 445235
36
-
37
-
38
-
39
- These are the benchmarks from notepack package. The larger test data for these benchmarks is very heavily weighted with large binary/buffer data and objects with extreme numbers of keys (much more than I typically see with real-world data, but YMMV):
40
-
41
- node ./benchmarks/encode
42
-
43
- library | tiny | small | medium | large
44
- ---------------- | ----------------: | --------------: | ---------------| -------:
45
- notepack | 2,171,621 ops/sec | 546,905 ops/sec | 29,578 ops/sec | 265 ops/sec
46
- msgpack-js | 967,682 ops/sec | 184,455 ops/sec | 20,556 ops/sec | 259 ops/sec
47
- msgpackr | 2,392,826 ops/sec | 556,915 ops/sec | 70,573 ops/sec | 313 ops/sec
48
- msgpack-lite | 553,143 ops/sec | 132,318 ops/sec | 11,816 ops/sec | 186 ops/sec
49
- @msgpack/msgpack | 2,157,655 ops/sec | 573,236 ops/sec | 25,864 ops/sec | 90.26 ops/sec
50
-
51
-
52
- node ./benchmarks/decode
53
-
54
- library | tiny | small | medium | large
55
- ---------------- | ----------------: | --------------: | --------------- | -------:
56
- notepack | 2,220,904 ops/sec | 560,630 ops/sec | 28,177 ops/sec | 275 ops/sec
57
- msgpack-js | 965,719 ops/sec | 222,047 ops/sec | 21,431 ops/sec | 257 ops/sec
58
- msgpackr | 2,320,046 ops/sec | 589,167 ops/sec | 70,299 ops/sec | 329 ops/sec
59
- msgpackr records | 3,750,547 ops/sec | 912,419 ops/sec | 136,853 ops/sec | 733 ops/sec
60
- msgpack-lite | 569,222 ops/sec | 129,008 ops/sec | 12,424 ops/sec | 180 ops/sec
61
- @msgpack/msgpack | 2,089,697 ops/sec | 557,507 ops/sec | 20,256 ops/sec | 85.03 ops/sec
62
-
63
- This was run by adding the msgpackr to the benchmarks for notepack.
64
-
65
- All benchmarks were performed on Node 14.8.0 (Windows i7-4770 3.4Ghz). They can be run with:
66
- npm install --no-save msgpack msgpack-js @msgpack/msgpack msgpack-lite notepack avsc
67
- node tests/benchmark
1
+ Here are more comprehensive benchmarks. This is comparison with the next fastest JS projects using the benchmark tool from `msgpack-lite` (and data is from some clinical research data we use that has a good mix of different value types and structures). It also includes comparison to V8 native JSON functionality, and JavaScript Avro (`avsc`, a very optimized Avro implementation):
2
+
3
+ operation | op | ms | op/s
4
+ ---------------------------------------------------------- | ------: | ----: | -----:
5
+ buf = Buffer(JSON.stringify(obj)); | 82000 | 5004 | 16386
6
+ obj = JSON.parse(buf); | 88600 | 5000 | 17720
7
+ require("msgpackr").pack(obj); | 161500 | 5002 | 32287
8
+ require("msgpackr").unpack(buf); | 94600 | 5004 | 18904
9
+ msgpackr w/ shared structures: packr.pack(obj); | 178400 | 5002 | 35665
10
+ msgpackr w/ shared structures: packr.unpack(buf); | 376700 | 5000 | 75340
11
+ buf = require("msgpack-lite").encode(obj); | 30100 | 5012 | 6005
12
+ obj = require("msgpack-lite").decode(buf); | 16200 | 5001 | 3239
13
+ buf = require("notepack").encode(obj); | 62600 | 5005 | 12507
14
+ obj = require("notepack").decode(buf); | 32400 | 5007 | 6470
15
+ require("what-the-pack")... encoder.encode(obj); | 63500 | 5002 | 12694
16
+ require("what-the-pack")... encoder.decode(buf); | 32000 | 5001 | 6398
17
+ require("avsc")...make schema/type...type.toBuffer(obj); | 84600 | 5003 | 16909
18
+ require("avsc")...make schema/type...type.toBuffer(obj); | 99300 | 5001 | 19856
19
+
20
+ (`avsc` is schema-based and more comparable in style to msgpackr with shared structures).
21
+
22
+ Here is a benchmark of streaming data (again borrowed from `msgpack-lite`'s benchmarking), where msgpackr is able to take advantage of the structured record extension and really pull away from other tools:
23
+
24
+ operation (1000000 x 2) | op | ms | op/s
25
+ ------------------------------------------------ | ------: | ----: | -----:
26
+ new PackrStream().write(obj); | 1000000 | 372 | 2688172
27
+ new UnpackrStream().write(buf); | 1000000 | 247 | 4048582
28
+ stream.write(msgpack.encode(obj)); | 1000000 | 2898 | 345065
29
+ stream.write(msgpack.decode(buf)); | 1000000 | 1969 | 507872
30
+ stream.write(notepack.encode(obj)); | 1000000 | 901 | 1109877
31
+ stream.write(notepack.decode(buf)); | 1000000 | 1012 | 988142
32
+ msgpack.Encoder().on("data",ondata).encode(obj); | 1000000 | 1763 | 567214
33
+ msgpack.createDecodeStream().write(buf); | 1000000 | 2222 | 450045
34
+ msgpack.createEncodeStream().write(obj); | 1000000 | 1577 | 634115
35
+ msgpack.Decoder().on("data",ondata).decode(buf); | 1000000 | 2246 | 445235
36
+
37
+
38
+
39
+ These are the benchmarks from notepack package. The larger test data for these benchmarks is very heavily weighted with large binary/buffer data and objects with extreme numbers of keys (much more than I typically see with real-world data, but YMMV):
40
+
41
+ node ./benchmarks/encode
42
+
43
+ library | tiny | small | medium | large
44
+ ---------------- | ----------------: | --------------: | ---------------| -------:
45
+ notepack | 2,171,621 ops/sec | 546,905 ops/sec | 29,578 ops/sec | 265 ops/sec
46
+ msgpack-js | 967,682 ops/sec | 184,455 ops/sec | 20,556 ops/sec | 259 ops/sec
47
+ msgpackr | 2,392,826 ops/sec | 556,915 ops/sec | 70,573 ops/sec | 313 ops/sec
48
+ msgpack-lite | 553,143 ops/sec | 132,318 ops/sec | 11,816 ops/sec | 186 ops/sec
49
+ @msgpack/msgpack | 2,157,655 ops/sec | 573,236 ops/sec | 25,864 ops/sec | 90.26 ops/sec
50
+
51
+
52
+ node ./benchmarks/decode
53
+
54
+ library | tiny | small | medium | large
55
+ ---------------- | ----------------: | --------------: | --------------- | -------:
56
+ notepack | 2,220,904 ops/sec | 560,630 ops/sec | 28,177 ops/sec | 275 ops/sec
57
+ msgpack-js | 965,719 ops/sec | 222,047 ops/sec | 21,431 ops/sec | 257 ops/sec
58
+ msgpackr | 2,320,046 ops/sec | 589,167 ops/sec | 70,299 ops/sec | 329 ops/sec
59
+ msgpackr records | 3,750,547 ops/sec | 912,419 ops/sec | 136,853 ops/sec | 733 ops/sec
60
+ msgpack-lite | 569,222 ops/sec | 129,008 ops/sec | 12,424 ops/sec | 180 ops/sec
61
+ @msgpack/msgpack | 2,089,697 ops/sec | 557,507 ops/sec | 20,256 ops/sec | 85.03 ops/sec
62
+
63
+ This was run by adding the msgpackr to the benchmarks for notepack.
64
+
65
+ All benchmarks were performed on Node 14.8.0 (Windows i7-4770 3.4Ghz). They can be run with:
66
+ npm install --no-save msgpack msgpack-js @msgpack/msgpack msgpack-lite notepack avsc
67
+ node tests/benchmark
package/dist/index.js CHANGED
@@ -59,16 +59,21 @@
59
59
  }
60
60
  Object.assign(this, options);
61
61
  }
62
- unpack(source, end) {
62
+ unpack(source, options) {
63
63
  if (src) {
64
64
  // re-entrant execution, save the state and restore it after we do this unpack
65
65
  return saveState(() => {
66
66
  clearSource();
67
- return this ? this.unpack(source, end) : Unpackr.prototype.unpack.call(defaultOptions, source, end)
67
+ return this ? this.unpack(source, options) : Unpackr.prototype.unpack.call(defaultOptions, source, options)
68
68
  })
69
69
  }
70
- srcEnd = end > -1 ? end : source.length;
71
- position = 0;
70
+ if (typeof options === 'object') {
71
+ srcEnd = options.end || source.length;
72
+ position = options.start || 0;
73
+ } else {
74
+ position = 0;
75
+ srcEnd = options > -1 ? options : source.length;
76
+ }
72
77
  srcStringEnd = 0;
73
78
  srcString = null;
74
79
  bundledStrings = null;
@@ -134,6 +139,8 @@
134
139
  }
135
140
  _mergeStructures(loadedStructures, existingStructures) {
136
141
  loadedStructures = loadedStructures || [];
142
+ if (Object.isFrozen(loadedStructures))
143
+ loadedStructures = loadedStructures.map(structure => structure.slice(0));
137
144
  for (let i = 0, l = loadedStructures.length; i < l; i++) {
138
145
  let structure = loadedStructures[i];
139
146
  if (structure) {
@@ -168,9 +175,8 @@
168
175
  currentStructures.length = sharedLength;
169
176
  }
170
177
  let result;
171
- if (currentUnpackr.randomAccessStructure && src[position] < 0x40 && readStruct) {
172
- let id = (src[position++] << 8) + src[position++];
173
- result = readStruct(src, position, srcEnd, currentStructures[id - 0x40] || loadStructures()[id - 0x40], currentUnpackr);
178
+ if (currentUnpackr.randomAccessStructure && src[position] < 0x40 && src[position] >= 0x20 && readStruct) {
179
+ result = readStruct(src, position, srcEnd, currentUnpackr);
174
180
  position = srcEnd;
175
181
  } else
176
182
  result = read();
@@ -787,7 +793,15 @@
787
793
  function readExt(length) {
788
794
  let type = src[position++];
789
795
  if (currentExtensions[type]) {
790
- return currentExtensions[type](src.subarray(position, position += length))
796
+ let end;
797
+ return currentExtensions[type](src.subarray(position, end = (position += length)), (readPosition) => {
798
+ position = readPosition;
799
+ try {
800
+ return read();
801
+ } finally {
802
+ position = end;
803
+ }
804
+ })
791
805
  }
792
806
  else
793
807
  throw new Error('Unknown extension type ' + type)
@@ -1054,7 +1068,6 @@
1054
1068
  let hasSharedUpdate;
1055
1069
  let structures;
1056
1070
  let referenceMap;
1057
- let lastSharedStructuresLength = 0;
1058
1071
  let encodeUtf8 = ByteArray.prototype.utf8Write ? function(string, position) {
1059
1072
  return target.utf8Write(string, position, 0xffffffff)
1060
1073
  } : (textEncoder && textEncoder.encodeInto) ?
@@ -1140,7 +1153,7 @@
1140
1153
  }
1141
1154
  transition[RECORD_SYMBOL] = i + 0x40;
1142
1155
  }
1143
- lastSharedStructuresLength = sharedLength;
1156
+ this.lastNamedStructuresLength = sharedLength;
1144
1157
  }
1145
1158
  if (!isSequential) {
1146
1159
  structures.nextId = sharedLength + 0x40;
@@ -1149,7 +1162,7 @@
1149
1162
  if (hasSharedUpdate)
1150
1163
  hasSharedUpdate = false;
1151
1164
  try {
1152
- if (packr.randomAccessStructure)
1165
+ if (packr.randomAccessStructure && value.constructor && value.constructor === Object)
1153
1166
  writeStruct(value);
1154
1167
  else
1155
1168
  pack(value);
@@ -1176,7 +1189,7 @@
1176
1189
  if (structures) {
1177
1190
  if (serializationsSinceTransitionRebuild < 10)
1178
1191
  serializationsSinceTransitionRebuild++;
1179
- let sharedLength = structures.sharedLength || maxSharedStructures;
1192
+ let sharedLength = structures.sharedLength || 0;
1180
1193
  if (structures.length > sharedLength)
1181
1194
  structures.length = sharedLength;
1182
1195
  if (transitionsCount > 10000) {
@@ -1195,12 +1208,12 @@
1195
1208
  if (hasSharedUpdate && packr.saveStructures) {
1196
1209
  // we can't rely on start/end with REUSE_BUFFER_MODE since they will (probably) change when we save
1197
1210
  let returnBuffer = target.subarray(start, position$1);
1198
- if (packr.saveStructures(structures, lastSharedStructuresLength) === false) {
1211
+ let newSharedData = prepareStructures(structures, packr);
1212
+ if (packr.saveStructures(newSharedData, newSharedData.isCompatible) === false) {
1199
1213
  // get updated structures and try again if the update failed
1200
- packr._mergeStructures(packr.getStructures());
1201
1214
  return packr.pack(value)
1202
1215
  }
1203
- lastSharedStructuresLength = sharedLength;
1216
+ packr.lastNamedStructuresLength = sharedLength;
1204
1217
  return returnBuffer
1205
1218
  }
1206
1219
  }
@@ -1318,7 +1331,7 @@
1318
1331
  } else if (type === 'number') {
1319
1332
  if (value >>> 0 === value) {// positive integer, 32-bit or less
1320
1333
  // positive uint
1321
- if (value < 0x40 || (value < 0x80 && this.useRecords === false)) {
1334
+ if (value < 0x20 || (value < 0x80 && this.useRecords === false) || (value < 0x40 && !this.randomAccessStructure)) {
1322
1335
  target[position$1++] = value;
1323
1336
  } else if (value < 0x100) {
1324
1337
  target[position$1++] = 0xcc;
@@ -1733,6 +1746,8 @@
1733
1746
  clearSharedData() {
1734
1747
  if (this.structures)
1735
1748
  this.structures = [];
1749
+ if (this.typedStructs)
1750
+ this.typedStructs = [];
1736
1751
  }
1737
1752
  }
1738
1753
 
@@ -1952,6 +1967,15 @@
1952
1967
  }
1953
1968
  addExtension(extension);
1954
1969
  }
1970
+ function prepareStructures(structures, packr) {
1971
+ structures.isCompatible = (existingStructures) => {
1972
+ let compatible = !existingStructures || ((packr.lastNamedStructuresLength || 0) === existingStructures.length);
1973
+ if (!compatible) // we want to merge these existing structures immediately since we already have it and we are in the right transaction
1974
+ packr._mergeStructures(existingStructures);
1975
+ return compatible;
1976
+ };
1977
+ return structures
1978
+ }
1955
1979
 
1956
1980
  let defaultPackr = new Packr({ useRecords: false });
1957
1981
  const pack = defaultPackr.pack;
@@ -1961,92 +1985,92 @@
1961
1985
  const REUSE_BUFFER_MODE = 512;
1962
1986
  const RESET_BUFFER_MODE = 1024;
1963
1987
 
1964
- /**
1965
- * Given an Iterable first argument, returns an Iterable where each value is packed as a Buffer
1966
- * If the argument is only Async Iterable, the return value will be an Async Iterable.
1967
- * @param {Iterable|Iterator|AsyncIterable|AsyncIterator} objectIterator - iterable source, like a Readable object stream, an array, Set, or custom object
1968
- * @param {options} [options] - msgpackr pack options
1969
- * @returns {IterableIterator|Promise.<AsyncIterableIterator>}
1970
- */
1971
- function packIter (objectIterator, options = {}) {
1972
- if (!objectIterator || typeof objectIterator !== 'object') {
1973
- throw new Error('first argument must be an Iterable, Async Iterable, or a Promise for an Async Iterable')
1974
- } else if (typeof objectIterator[Symbol.iterator] === 'function') {
1975
- return packIterSync(objectIterator, options)
1976
- } else if (typeof objectIterator.then === 'function' || typeof objectIterator[Symbol.asyncIterator] === 'function') {
1977
- return packIterAsync(objectIterator, options)
1978
- } else {
1979
- throw new Error('first argument must be an Iterable, Async Iterable, Iterator, Async Iterator, or a Promise')
1980
- }
1981
- }
1982
-
1983
- function * packIterSync (objectIterator, options) {
1984
- const packr = new Packr(options);
1985
- for (const value of objectIterator) {
1986
- yield packr.pack(value);
1987
- }
1988
- }
1989
-
1990
- async function * packIterAsync (objectIterator, options) {
1991
- const packr = new Packr(options);
1992
- for await (const value of objectIterator) {
1993
- yield packr.pack(value);
1994
- }
1995
- }
1996
-
1997
- /**
1998
- * Given an Iterable/Iterator input which yields buffers, returns an IterableIterator which yields sync decoded objects
1999
- * Or, given an Async Iterable/Iterator which yields promises resolving in buffers, returns an AsyncIterableIterator.
2000
- * @param {Iterable|Iterator|AsyncIterable|AsyncIterableIterator} bufferIterator
2001
- * @param {object} [options] - unpackr options
2002
- * @returns {IterableIterator|Promise.<AsyncIterableIterator}
2003
- */
2004
- function unpackIter (bufferIterator, options = {}) {
2005
- if (!bufferIterator || typeof bufferIterator !== 'object') {
2006
- throw new Error('first argument must be an Iterable, Async Iterable, Iterator, Async Iterator, or a promise')
2007
- }
2008
-
2009
- const unpackr = new Unpackr(options);
2010
- let incomplete;
2011
- const parser = (chunk) => {
2012
- let yields;
2013
- // if there's incomplete data from previous chunk, concatinate and try again
2014
- if (incomplete) {
2015
- chunk = Buffer.concat([incomplete, chunk]);
2016
- incomplete = undefined;
2017
- }
2018
-
2019
- try {
2020
- yields = unpackr.unpackMultiple(chunk);
2021
- } catch (err) {
2022
- if (err.incomplete) {
2023
- incomplete = chunk.slice(err.lastPosition);
2024
- yields = err.values;
2025
- } else {
2026
- throw err
2027
- }
2028
- }
2029
- return yields
2030
- };
2031
-
2032
- if (typeof bufferIterator[Symbol.iterator] === 'function') {
2033
- return (function * iter () {
2034
- for (const value of bufferIterator) {
2035
- yield * parser(value);
2036
- }
2037
- })()
2038
- } else if (typeof bufferIterator[Symbol.asyncIterator] === 'function') {
2039
- return (async function * iter () {
2040
- for await (const value of bufferIterator) {
2041
- yield * parser(value);
2042
- }
2043
- })()
2044
- }
2045
- }
2046
- const decodeIter = unpackIter;
1988
+ /**
1989
+ * Given an Iterable first argument, returns an Iterable where each value is packed as a Buffer
1990
+ * If the argument is only Async Iterable, the return value will be an Async Iterable.
1991
+ * @param {Iterable|Iterator|AsyncIterable|AsyncIterator} objectIterator - iterable source, like a Readable object stream, an array, Set, or custom object
1992
+ * @param {options} [options] - msgpackr pack options
1993
+ * @returns {IterableIterator|Promise.<AsyncIterableIterator>}
1994
+ */
1995
+ function packIter (objectIterator, options = {}) {
1996
+ if (!objectIterator || typeof objectIterator !== 'object') {
1997
+ throw new Error('first argument must be an Iterable, Async Iterable, or a Promise for an Async Iterable')
1998
+ } else if (typeof objectIterator[Symbol.iterator] === 'function') {
1999
+ return packIterSync(objectIterator, options)
2000
+ } else if (typeof objectIterator.then === 'function' || typeof objectIterator[Symbol.asyncIterator] === 'function') {
2001
+ return packIterAsync(objectIterator, options)
2002
+ } else {
2003
+ throw new Error('first argument must be an Iterable, Async Iterable, Iterator, Async Iterator, or a Promise')
2004
+ }
2005
+ }
2006
+
2007
+ function * packIterSync (objectIterator, options) {
2008
+ const packr = new Packr(options);
2009
+ for (const value of objectIterator) {
2010
+ yield packr.pack(value);
2011
+ }
2012
+ }
2013
+
2014
+ async function * packIterAsync (objectIterator, options) {
2015
+ const packr = new Packr(options);
2016
+ for await (const value of objectIterator) {
2017
+ yield packr.pack(value);
2018
+ }
2019
+ }
2020
+
2021
+ /**
2022
+ * Given an Iterable/Iterator input which yields buffers, returns an IterableIterator which yields sync decoded objects
2023
+ * Or, given an Async Iterable/Iterator which yields promises resolving in buffers, returns an AsyncIterableIterator.
2024
+ * @param {Iterable|Iterator|AsyncIterable|AsyncIterableIterator} bufferIterator
2025
+ * @param {object} [options] - unpackr options
2026
+ * @returns {IterableIterator|Promise.<AsyncIterableIterator}
2027
+ */
2028
+ function unpackIter (bufferIterator, options = {}) {
2029
+ if (!bufferIterator || typeof bufferIterator !== 'object') {
2030
+ throw new Error('first argument must be an Iterable, Async Iterable, Iterator, Async Iterator, or a promise')
2031
+ }
2032
+
2033
+ const unpackr = new Unpackr(options);
2034
+ let incomplete;
2035
+ const parser = (chunk) => {
2036
+ let yields;
2037
+ // if there's incomplete data from previous chunk, concatinate and try again
2038
+ if (incomplete) {
2039
+ chunk = Buffer.concat([incomplete, chunk]);
2040
+ incomplete = undefined;
2041
+ }
2042
+
2043
+ try {
2044
+ yields = unpackr.unpackMultiple(chunk);
2045
+ } catch (err) {
2046
+ if (err.incomplete) {
2047
+ incomplete = chunk.slice(err.lastPosition);
2048
+ yields = err.values;
2049
+ } else {
2050
+ throw err
2051
+ }
2052
+ }
2053
+ return yields
2054
+ };
2055
+
2056
+ if (typeof bufferIterator[Symbol.iterator] === 'function') {
2057
+ return (function * iter () {
2058
+ for (const value of bufferIterator) {
2059
+ yield * parser(value);
2060
+ }
2061
+ })()
2062
+ } else if (typeof bufferIterator[Symbol.asyncIterator] === 'function') {
2063
+ return (async function * iter () {
2064
+ for await (const value of bufferIterator) {
2065
+ yield * parser(value);
2066
+ }
2067
+ })()
2068
+ }
2069
+ }
2070
+ const decodeIter = unpackIter;
2047
2071
  const encodeIter = packIter;
2048
2072
 
2049
- const useRecords = false;
2073
+ const useRecords = false;
2050
2074
  const mapsAsObjects = true;
2051
2075
 
2052
2076
  exports.ALWAYS = ALWAYS;
@@ -2077,3 +2101,4 @@
2077
2101
  Object.defineProperty(exports, '__esModule', { value: true });
2078
2102
 
2079
2103
  })));
2104
+ //# sourceMappingURL=index.js.map