cbor-x 1.6.8 → 1.6.9
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/README.md +4 -0
- package/decode.js +151 -28
- package/dist/decode-no-eval.cjs +152 -28
- package/dist/decode-no-eval.cjs.map +1 -1
- package/dist/index-no-eval.cjs +540 -48
- package/dist/index-no-eval.cjs.map +1 -1
- package/dist/index-no-eval.min.js +1 -1
- package/dist/index-no-eval.min.js.map +1 -1
- package/dist/index.js +540 -48
- package/dist/index.js.map +1 -1
- package/dist/index.min.js +1 -1
- package/dist/index.min.js.map +1 -1
- package/dist/node.cjs +595 -100
- package/dist/node.cjs.map +1 -1
- package/dist/test.js +147 -30
- package/dist/test.js.map +1 -1
- package/encode.js +21 -2
- package/index.d.ts +1 -1
- package/iterators.js +123 -19
- package/package.json +2 -2
- package/scan.js +253 -0
- package/stream.js +9 -10
package/dist/index.js
CHANGED
|
@@ -16,7 +16,6 @@
|
|
|
16
16
|
const RECORD_INLINE_ID = 0xdfff; // temporary first-come first-serve tag // proposed tag: 0x7265 // 're'
|
|
17
17
|
const BUNDLED_STRINGS_ID = 0xdff9;
|
|
18
18
|
const PACKED_REFERENCE_TAG_ID = 6;
|
|
19
|
-
const STOP_CODE = {};
|
|
20
19
|
let maxArraySize = 112810000; // This is the maximum array size in V8. We would potentially detect and set it higher
|
|
21
20
|
// for JSC, but this is pretty large and should be sufficient for most use cases
|
|
22
21
|
let maxMapSize = 16810000; // JavaScript has a fixed maximum map size of about 16710000, but JS itself enforces this,
|
|
@@ -125,16 +124,11 @@
|
|
|
125
124
|
// re-entrant execution, save the state and restore it after we do this decode
|
|
126
125
|
return saveState(() => {
|
|
127
126
|
clearSource();
|
|
128
|
-
|
|
129
|
-
return this ? this.decode(source, end) : Decoder.prototype.decode.call(defaultOptions, source, end)
|
|
130
|
-
} catch (error) {
|
|
131
|
-
if (error && typeof error == 'object')
|
|
132
|
-
nestedDecodeErrors.add(error);
|
|
133
|
-
throw error
|
|
134
|
-
}
|
|
127
|
+
return this ? this.decode(source, end) : Decoder.prototype.decode.call(defaultOptions, source, end)
|
|
135
128
|
})
|
|
136
129
|
}
|
|
137
|
-
|
|
130
|
+
// past the view, the JS string readers would decode the missing bytes as zeros instead of failing as truncated
|
|
131
|
+
srcEnd = end > -1 && end < source.length ? end : source.length;
|
|
138
132
|
position$1 = 0;
|
|
139
133
|
srcStringEnd = 0;
|
|
140
134
|
srcString = null;
|
|
@@ -172,18 +166,28 @@
|
|
|
172
166
|
return checkedRead()
|
|
173
167
|
}
|
|
174
168
|
decodeMultiple(source, forEach) {
|
|
169
|
+
if (src) {
|
|
170
|
+
// Keep the complete nested sequence inside its own decoder state.
|
|
171
|
+
return saveState(() => {
|
|
172
|
+
clearSource();
|
|
173
|
+
return this ? this.decodeMultiple(source, forEach) : defaultDecoder.decodeMultiple(source, forEach)
|
|
174
|
+
})
|
|
175
|
+
}
|
|
175
176
|
let values, lastPosition = 0;
|
|
176
177
|
try {
|
|
177
178
|
let size = source.length;
|
|
178
179
|
sequentialMode = true;
|
|
179
180
|
let value = this ? this.decode(source, size) : defaultDecoder.decode(source, size);
|
|
180
181
|
if (forEach) {
|
|
182
|
+
let end = position$1;
|
|
181
183
|
if (forEach(value) === false) {
|
|
182
184
|
return
|
|
183
185
|
}
|
|
184
|
-
while(
|
|
185
|
-
lastPosition =
|
|
186
|
-
|
|
186
|
+
while(end < size) {
|
|
187
|
+
lastPosition = end;
|
|
188
|
+
value = checkedRead();
|
|
189
|
+
end = position$1;
|
|
190
|
+
if (forEach(value) === false) {
|
|
187
191
|
return
|
|
188
192
|
}
|
|
189
193
|
}
|
|
@@ -197,8 +201,10 @@
|
|
|
197
201
|
return values
|
|
198
202
|
}
|
|
199
203
|
} catch(error) {
|
|
200
|
-
error
|
|
201
|
-
|
|
204
|
+
if (error && (typeof error == 'object' || typeof error == 'function')) {
|
|
205
|
+
error.lastPosition = lastPosition;
|
|
206
|
+
error.values = values;
|
|
207
|
+
}
|
|
202
208
|
throw error
|
|
203
209
|
} finally {
|
|
204
210
|
sequentialMode = false;
|
|
@@ -252,9 +258,21 @@
|
|
|
252
258
|
}
|
|
253
259
|
}
|
|
254
260
|
|
|
255
|
-
function
|
|
261
|
+
function readBreak() {
|
|
262
|
+
if (position$1 < srcEnd && src[position$1] === 0xff) {
|
|
263
|
+
position$1++;
|
|
264
|
+
return true
|
|
265
|
+
}
|
|
266
|
+
return false
|
|
267
|
+
}
|
|
268
|
+
// neededEnd, from a length check, is a position that the source must extend to before the item can decode. It is a
|
|
269
|
+
// lower bound for any completion of the source: every byte read before the check was within the source, so a longer
|
|
270
|
+
// source reaches the same check with the same length. Streams wait for it instead of decoding on every chunk.
|
|
271
|
+
function endOfCBORError(neededEnd) {
|
|
256
272
|
let error = new Error('Unexpected end of CBOR data');
|
|
257
273
|
error.incomplete = true;
|
|
274
|
+
if (neededEnd)
|
|
275
|
+
error.neededEnd = neededEnd;
|
|
258
276
|
return error
|
|
259
277
|
}
|
|
260
278
|
|
|
@@ -306,6 +324,9 @@
|
|
|
306
324
|
} else if (currentDecoder.int64AsNumber) {
|
|
307
325
|
token = dataView.getUint32(position$1) * 0x100000000;
|
|
308
326
|
token += dataView.getUint32(position$1 + 4);
|
|
327
|
+
position$1 += 8;
|
|
328
|
+
if (majorType === 1) return -1 - token
|
|
329
|
+
break
|
|
309
330
|
} else token = dataView.getBigUint64(position$1);
|
|
310
331
|
position$1 += 8;
|
|
311
332
|
break
|
|
@@ -317,10 +338,10 @@
|
|
|
317
338
|
throw new Error('Indefinite length not supported for byte or text strings')
|
|
318
339
|
case 4: // array
|
|
319
340
|
let array = [];
|
|
320
|
-
let
|
|
321
|
-
while ((
|
|
341
|
+
let i = 0;
|
|
342
|
+
while (!readBreak()) {
|
|
322
343
|
if (i >= maxArraySize) throw new Error(`Array length exceeds ${maxArraySize}`)
|
|
323
|
-
array[i++] =
|
|
344
|
+
array[i++] = read();
|
|
324
345
|
}
|
|
325
346
|
return majorType == 4 ? array : majorType == 3 ? array.join('') : Buffer.concat(array)
|
|
326
347
|
case 5: // map
|
|
@@ -329,13 +350,15 @@
|
|
|
329
350
|
let object = {};
|
|
330
351
|
let i = 0;
|
|
331
352
|
if (currentDecoder.keyMap) {
|
|
332
|
-
while((
|
|
353
|
+
while (!readBreak()) {
|
|
354
|
+
key = read();
|
|
333
355
|
if (i++ >= objectSizeLimit) throw new Error(`Property count exceeds ${objectSizeLimit}`)
|
|
334
356
|
object[safeKey(currentDecoder.decodeKey(key))] = read();
|
|
335
357
|
}
|
|
336
358
|
}
|
|
337
359
|
else {
|
|
338
|
-
while ((
|
|
360
|
+
while (!readBreak()) {
|
|
361
|
+
key = read();
|
|
339
362
|
if (i++ >= objectSizeLimit) throw new Error(`Property count exceeds ${objectSizeLimit}`)
|
|
340
363
|
object[safeKey(key)] = read();
|
|
341
364
|
}
|
|
@@ -349,7 +372,8 @@
|
|
|
349
372
|
let map = new Map();
|
|
350
373
|
if (currentDecoder.keyMap) {
|
|
351
374
|
let i = 0;
|
|
352
|
-
while((
|
|
375
|
+
while (!readBreak()) {
|
|
376
|
+
key = read();
|
|
353
377
|
if (i++ >= maxMapSize) {
|
|
354
378
|
throw new Error(`Map size exceeds ${maxMapSize}`);
|
|
355
379
|
}
|
|
@@ -358,7 +382,8 @@
|
|
|
358
382
|
}
|
|
359
383
|
else {
|
|
360
384
|
let i = 0;
|
|
361
|
-
while ((
|
|
385
|
+
while (!readBreak()) {
|
|
386
|
+
key = read();
|
|
362
387
|
if (i++ >= maxMapSize) {
|
|
363
388
|
throw new Error(`Map size exceeds ${maxMapSize}`);
|
|
364
389
|
}
|
|
@@ -368,7 +393,8 @@
|
|
|
368
393
|
return map
|
|
369
394
|
}
|
|
370
395
|
case 7:
|
|
371
|
-
|
|
396
|
+
// readBreak consumes every break that ends an indefinite-length item
|
|
397
|
+
throw new Error('Unexpected break stop code outside of an indefinite-length item')
|
|
372
398
|
default:
|
|
373
399
|
throw new Error('Invalid major type for indefinite length ' + majorType)
|
|
374
400
|
}
|
|
@@ -382,13 +408,13 @@
|
|
|
382
408
|
case 1: // negative int
|
|
383
409
|
return ~token
|
|
384
410
|
case 2: // buffer
|
|
385
|
-
if (token > srcEnd - position$1) throw endOfCBORError()
|
|
411
|
+
if (token > srcEnd - position$1) throw endOfCBORError(position$1 + token)
|
|
386
412
|
return readBin(token)
|
|
387
413
|
case 3: // string
|
|
388
414
|
if (srcStringEnd >= position$1) { // already extracted, which only covers complete strings
|
|
389
415
|
return srcString.slice(position$1 - srcStringStart, (position$1 += token) - srcStringStart)
|
|
390
416
|
}
|
|
391
|
-
if (token > srcEnd - position$1) throw endOfCBORError()
|
|
417
|
+
if (token > srcEnd - position$1) throw endOfCBORError(position$1 + token)
|
|
392
418
|
if (srcStringEnd == 0 && srcEnd < 140 && token < 32) {
|
|
393
419
|
// for small blocks, avoiding the overhead of the extract call is helpful
|
|
394
420
|
let string = token < 16 ? shortStringInJS(token) : longStringInJS(token);
|
|
@@ -402,7 +428,7 @@
|
|
|
402
428
|
// never be satisfied; check before allocating so a tiny header can not force a huge allocation
|
|
403
429
|
// nested arrays each pass the check above yet still preallocate, so also spend from a
|
|
404
430
|
// per-decode budget of the remaining bytes; the summed lengths of any valid tree stay under it
|
|
405
|
-
if (token > srcEnd - position$1 || (arrayAllocationBudget -= token) < 0) throw endOfCBORError()
|
|
431
|
+
if (token > srcEnd - position$1 || (arrayAllocationBudget -= token) < 0) throw endOfCBORError(position$1 + token)
|
|
406
432
|
let array = new Array(token);
|
|
407
433
|
//if (currentDecoder.keyMap) for (let i = 0; i < token; i++) array[i] = currentDecoder.decodeKey(read())
|
|
408
434
|
//else
|
|
@@ -411,7 +437,7 @@
|
|
|
411
437
|
case 5: // map
|
|
412
438
|
if (currentDecoder.mapsAsObjects) {
|
|
413
439
|
if (token > objectSizeLimit) throw new Error(`Property count exceeds ${objectSizeLimit}`)
|
|
414
|
-
if (token > (srcEnd - position$1) / 2) throw endOfCBORError() // each entry needs at least two bytes
|
|
440
|
+
if (token > (srcEnd - position$1) / 2) throw endOfCBORError(position$1 + 2 * token) // each entry needs at least two bytes
|
|
415
441
|
let object = {};
|
|
416
442
|
if (currentDecoder.keyMap) for (let i = 0; i < token; i++) object[safeKey(currentDecoder.decodeKey(read()))] = read();
|
|
417
443
|
else for (let i = 0; i < token; i++) object[safeKey(read())] = read();
|
|
@@ -422,7 +448,7 @@
|
|
|
422
448
|
restoreMapsAsObject = false;
|
|
423
449
|
}
|
|
424
450
|
if (token > maxMapSize) throw new Error(`Map size exceeds ${maxMapSize}`)
|
|
425
|
-
if (token > (srcEnd - position$1) / 2) throw endOfCBORError()
|
|
451
|
+
if (token > (srcEnd - position$1) / 2) throw endOfCBORError(position$1 + 2 * token)
|
|
426
452
|
let map = new Map();
|
|
427
453
|
if (currentDecoder.keyMap) for (let i = 0; i < token; i++) map.set(currentDecoder.decodeKey(read()),read());
|
|
428
454
|
else for (let i = 0; i < token; i++) map.set(read(), read());
|
|
@@ -903,6 +929,7 @@
|
|
|
903
929
|
}
|
|
904
930
|
return object
|
|
905
931
|
};
|
|
932
|
+
const legacyRecordDefinition = currentExtensions[LEGACY_RECORD_INLINE_ID];
|
|
906
933
|
currentExtensions[14] = (value) => {
|
|
907
934
|
if (bundledStrings$1)
|
|
908
935
|
return bundledStrings$1[0].slice(bundledStrings$1.position0, bundledStrings$1.position0 += value)
|
|
@@ -1175,6 +1202,9 @@
|
|
|
1175
1202
|
}
|
|
1176
1203
|
|
|
1177
1204
|
function saveState(callback) {
|
|
1205
|
+
let savedFragmentEnd = fragmentEnd;
|
|
1206
|
+
let savedFragmentReader = fragmentReadString;
|
|
1207
|
+
let savedReadFixedString = readFixedString;
|
|
1178
1208
|
let savedSrcEnd = srcEnd;
|
|
1179
1209
|
let savedPosition = position$1;
|
|
1180
1210
|
let savedSrcStringStart = srcStringStart;
|
|
@@ -1182,6 +1212,7 @@
|
|
|
1182
1212
|
let savedSrcString = srcString;
|
|
1183
1213
|
let savedReferenceMap = referenceMap;
|
|
1184
1214
|
let savedBundledStrings = bundledStrings$1;
|
|
1215
|
+
let savedPackedValues = packedValues;
|
|
1185
1216
|
|
|
1186
1217
|
// TODO: We may need to revisit this if we do more external calls to user code (since it could be slow)
|
|
1187
1218
|
let savedSrc = new Uint8Array(src.slice(0, srcEnd)); // we copy the data in case it changes while external data is processed
|
|
@@ -1190,10 +1221,22 @@
|
|
|
1190
1221
|
let savedSequentialMode = sequentialMode;
|
|
1191
1222
|
let savedRestoreMapsAsObject = restoreMapsAsObject;
|
|
1192
1223
|
let savedArrayAllocationBudget = arrayAllocationBudget;
|
|
1224
|
+
fragmentEnd = 0;
|
|
1225
|
+
if (fragmentReadString) readFixedString = fragmentReadString;
|
|
1226
|
+
fragmentReadString = null;
|
|
1193
1227
|
restoreMapsAsObject = false;
|
|
1194
1228
|
try {
|
|
1195
1229
|
return callback()
|
|
1230
|
+
} catch (error) {
|
|
1231
|
+
// the callback decodes its own source (a shared structures blob, or an extension's embedded data), so a
|
|
1232
|
+
// truncation there cannot be completed by more of the outer input; checkedRead() clears the flag
|
|
1233
|
+
if (error && (typeof error == 'object' || typeof error == 'function'))
|
|
1234
|
+
nestedDecodeErrors.add(error);
|
|
1235
|
+
throw error
|
|
1196
1236
|
} finally {
|
|
1237
|
+
fragmentEnd = savedFragmentEnd;
|
|
1238
|
+
fragmentReadString = savedFragmentReader;
|
|
1239
|
+
readFixedString = savedReadFixedString;
|
|
1197
1240
|
srcEnd = savedSrcEnd;
|
|
1198
1241
|
position$1 = savedPosition;
|
|
1199
1242
|
srcStringStart = savedSrcStringStart;
|
|
@@ -1201,6 +1244,7 @@
|
|
|
1201
1244
|
srcString = savedSrcString;
|
|
1202
1245
|
referenceMap = savedReferenceMap;
|
|
1203
1246
|
bundledStrings$1 = savedBundledStrings;
|
|
1247
|
+
packedValues = savedPackedValues;
|
|
1204
1248
|
src = savedSrc;
|
|
1205
1249
|
sequentialMode = savedSequentialMode;
|
|
1206
1250
|
currentStructures = savedStructures;
|
|
@@ -1216,8 +1260,82 @@
|
|
|
1216
1260
|
currentStructures = null;
|
|
1217
1261
|
}
|
|
1218
1262
|
|
|
1263
|
+
const registeredExtensions = new Map();
|
|
1264
|
+
let fragmentEnd = 0;
|
|
1265
|
+
let fragmentReadString;
|
|
1266
|
+
|
|
1267
|
+
const builtinScanTags = new Map([[LEGACY_RECORD_INLINE_ID, legacyRecordDefinition], [259, currentExtensions[259]]]);
|
|
1268
|
+
function isBuiltinScanTag(tag) {
|
|
1269
|
+
return builtinScanTags.has(tag) && currentExtensions[tag] === builtinScanTags.get(tag)
|
|
1270
|
+
}
|
|
1271
|
+
|
|
1272
|
+
function getScanTag(tag, decoder) {
|
|
1273
|
+
return tag >= BUNDLED_STRINGS_ID && decoder.structures && decoder.structures[tag & 0x1fff]
|
|
1274
|
+
}
|
|
1275
|
+
|
|
1276
|
+
function checkScanContainer(major, length, mapsAsObjects) {
|
|
1277
|
+
if (major === 4) {
|
|
1278
|
+
if (length > maxArraySize) throw new Error(`Array length exceeds ${maxArraySize}`)
|
|
1279
|
+
} else if (mapsAsObjects) {
|
|
1280
|
+
if (length > objectSizeLimit) throw new Error(`Property count exceeds ${objectSizeLimit}`)
|
|
1281
|
+
} else if (length > maxMapSize) throw new Error(`Map size exceeds ${maxMapSize}`)
|
|
1282
|
+
}
|
|
1283
|
+
|
|
1284
|
+
function decodeScanned(decoder, source, end) {
|
|
1285
|
+
const boundStrings = isNativeAccelerationEnabled ;
|
|
1286
|
+
if (!registeredExtensions.size && !boundStrings) return decoder.decodeMultiple(source)
|
|
1287
|
+
const savedEnd = fragmentEnd;
|
|
1288
|
+
const savedReader = readFixedString;
|
|
1289
|
+
const savedFragmentReader = fragmentReadString;
|
|
1290
|
+
const originals = [];
|
|
1291
|
+
fragmentEnd = end;
|
|
1292
|
+
fragmentReadString = savedReader;
|
|
1293
|
+
try {
|
|
1294
|
+
if (boundStrings) ;
|
|
1295
|
+
for (const [tag, extension] of registeredExtensions) {
|
|
1296
|
+
if (!extension.handlesRead) continue
|
|
1297
|
+
const original = currentExtensions[tag];
|
|
1298
|
+
const guarded = (read) => {
|
|
1299
|
+
if (!fragmentEnd || position$1 >= fragmentEnd) return extension(read)
|
|
1300
|
+
let calls = 0, framingError;
|
|
1301
|
+
const value = extension(() => {
|
|
1302
|
+
if (calls++) {
|
|
1303
|
+
framingError = new Error('Tag ' + tag + ': fragmented decoding cannot frame multi-item handlesRead extensions');
|
|
1304
|
+
throw framingError
|
|
1305
|
+
}
|
|
1306
|
+
return read()
|
|
1307
|
+
});
|
|
1308
|
+
if (framingError) throw framingError
|
|
1309
|
+
return value
|
|
1310
|
+
};
|
|
1311
|
+
guarded.handlesRead = true;
|
|
1312
|
+
originals.push([tag, original, guarded]);
|
|
1313
|
+
currentExtensions[tag] = guarded;
|
|
1314
|
+
}
|
|
1315
|
+
return decoder.decodeMultiple(source)
|
|
1316
|
+
} finally {
|
|
1317
|
+
fragmentEnd = savedEnd;
|
|
1318
|
+
fragmentReadString = savedFragmentReader;
|
|
1319
|
+
readFixedString = savedReader;
|
|
1320
|
+
for (const [tag, original, guarded] of originals) {
|
|
1321
|
+
if (currentExtensions[tag] === guarded) currentExtensions[tag] = original;
|
|
1322
|
+
}
|
|
1323
|
+
}
|
|
1324
|
+
}
|
|
1325
|
+
|
|
1326
|
+
// Internal streaming hooks; not part of the public decoder API.
|
|
1327
|
+
const _stream = {
|
|
1328
|
+
getTag: getScanTag,
|
|
1329
|
+
isBuiltinTag: isBuiltinScanTag,
|
|
1330
|
+
checkContainer: checkScanContainer,
|
|
1331
|
+
decode: decodeScanned,
|
|
1332
|
+
get readThreshold() { return inlineObjectReadThreshold }
|
|
1333
|
+
};
|
|
1334
|
+
|
|
1219
1335
|
function addExtension$1(extension) {
|
|
1220
1336
|
currentExtensions[extension.tag] = extension.decode;
|
|
1337
|
+
if (typeof extension.decode === 'function') registeredExtensions.set(extension.tag, extension.decode);
|
|
1338
|
+
else registeredExtensions.delete(extension.tag);
|
|
1221
1339
|
}
|
|
1222
1340
|
|
|
1223
1341
|
function setSizeLimits(limits) {
|
|
@@ -1817,6 +1935,11 @@
|
|
|
1817
1935
|
return encode(json)
|
|
1818
1936
|
}
|
|
1819
1937
|
|
|
1938
|
+
// not in extensions, so class instances that reach writeObject do not pay another instanceof
|
|
1939
|
+
if (constructor === DataView) {
|
|
1940
|
+
writeBuffer(new Uint8Array(value.buffer, value.byteOffset, value.byteLength), makeRoom);
|
|
1941
|
+
return
|
|
1942
|
+
}
|
|
1820
1943
|
// no extension found, write as a plain object
|
|
1821
1944
|
writeObject(value);
|
|
1822
1945
|
}
|
|
@@ -1910,8 +2033,22 @@
|
|
|
1910
2033
|
size++;
|
|
1911
2034
|
}
|
|
1912
2035
|
}
|
|
1913
|
-
|
|
1914
|
-
|
|
2036
|
+
if (size < 0x10000) {
|
|
2037
|
+
// fits in a map-16 (uint16) count: back-patch the reserved 2 bytes
|
|
2038
|
+
target[objectOffset++ + start] = size >> 8;
|
|
2039
|
+
target[objectOffset + start] = size & 0xff;
|
|
2040
|
+
} else {
|
|
2041
|
+
// too many entries for a map-16 count: widen the already-written header
|
|
2042
|
+
// to map-32, mirroring writeArrayHeader's 0x9a/setUint32 path. Shift the
|
|
2043
|
+
// encoded entries 2 bytes forward to make room for the wider (uint32) count.
|
|
2044
|
+
if (position + 2 > safeEnd)
|
|
2045
|
+
makeRoom(position + 2);
|
|
2046
|
+
let headerPosition = objectOffset + start;
|
|
2047
|
+
target.copyWithin(headerPosition + 4, headerPosition + 2, position);
|
|
2048
|
+
position += 2;
|
|
2049
|
+
target[headerPosition - 1] = 0xba; // map 32
|
|
2050
|
+
targetView.setUint32(headerPosition, size);
|
|
2051
|
+
}
|
|
1915
2052
|
} :
|
|
1916
2053
|
(object, skipValues) => {
|
|
1917
2054
|
let nextTransition, transition = structures.transitions || (structures.transitions = Object.create(null));
|
|
@@ -2478,6 +2615,258 @@
|
|
|
2478
2615
|
const RESET_BUFFER_MODE = 1024;
|
|
2479
2616
|
const THROW_ON_ITERABLE = 2048;
|
|
2480
2617
|
|
|
2618
|
+
// Positions are relative to the retained value, including bundle pointers. Frames and their storage survive appends.
|
|
2619
|
+
class StructureScanner {
|
|
2620
|
+
constructor (decoder) {
|
|
2621
|
+
this.decoder = decoder;
|
|
2622
|
+
this.frames = [];
|
|
2623
|
+
this.records = new Map();
|
|
2624
|
+
this.readers = new Map();
|
|
2625
|
+
this.reset();
|
|
2626
|
+
}
|
|
2627
|
+
|
|
2628
|
+
reset () {
|
|
2629
|
+
this.position = 0;
|
|
2630
|
+
this.depth = 0;
|
|
2631
|
+
this.neededLength = 0;
|
|
2632
|
+
this.postBundlePosition = 0;
|
|
2633
|
+
this.headers = 0;
|
|
2634
|
+
this.mapsAsObjects = !!this.decoder.mapsAsObjects;
|
|
2635
|
+
this.restoreMap = false;
|
|
2636
|
+
this.records.clear();
|
|
2637
|
+
this.readers.clear();
|
|
2638
|
+
this.push('items', 1);
|
|
2639
|
+
}
|
|
2640
|
+
|
|
2641
|
+
push (kind, remaining) {
|
|
2642
|
+
if (this.depth === 16384) throw new RangeError('Maximum CBOR nesting depth exceeded')
|
|
2643
|
+
const frame = this.frames[this.depth] || (this.frames[this.depth] = {});
|
|
2644
|
+
frame.kind = kind;
|
|
2645
|
+
frame.remaining = remaining;
|
|
2646
|
+
frame.stage = 0;
|
|
2647
|
+
frame.id = undefined;
|
|
2648
|
+
frame.restoreMap = false;
|
|
2649
|
+
frame.legacy = false;
|
|
2650
|
+
frame.definition = undefined;
|
|
2651
|
+
frame.limitMajor = 0;
|
|
2652
|
+
frame.count = 0;
|
|
2653
|
+
this.depth++;
|
|
2654
|
+
return frame
|
|
2655
|
+
}
|
|
2656
|
+
|
|
2657
|
+
header (source, end, lengthOnly = false) {
|
|
2658
|
+
const start = this.position;
|
|
2659
|
+
if (start >= end) {
|
|
2660
|
+
this.neededLength = start + 1;
|
|
2661
|
+
return false
|
|
2662
|
+
}
|
|
2663
|
+
const byte = source[start];
|
|
2664
|
+
const major = byte >> 5;
|
|
2665
|
+
const info = byte & 31;
|
|
2666
|
+
const width = info < 24 || (lengthOnly && info > 26) ? 0 : info === 24 ? 1 : info === 25 ? 2 : info === 26 ? 4 : info === 27 ? 8 : 0;
|
|
2667
|
+
if (!lengthOnly && info >= 28 && info <= 30) throw new Error('Unknown token ' + info)
|
|
2668
|
+
if (start + 1 + width > end) {
|
|
2669
|
+
this.neededLength = start + 1 + width;
|
|
2670
|
+
return false
|
|
2671
|
+
}
|
|
2672
|
+
let value = info;
|
|
2673
|
+
if (width) {
|
|
2674
|
+
value = 0;
|
|
2675
|
+
for (let i = start + 1; i <= start + width; i++) value = value * 256 + source[i];
|
|
2676
|
+
if (width === 8 && major > 1 && major !== 7 && value > 0xffffffff) {
|
|
2677
|
+
throw new Error('JavaScript does not support arrays, maps, or strings with length over 4294967295')
|
|
2678
|
+
}
|
|
2679
|
+
}
|
|
2680
|
+
this.major = major;
|
|
2681
|
+
this.info = info;
|
|
2682
|
+
this.argument = value;
|
|
2683
|
+
this.position = start + 1 + width;
|
|
2684
|
+
this.headers++;
|
|
2685
|
+
return true
|
|
2686
|
+
}
|
|
2687
|
+
|
|
2688
|
+
scan (source, end) {
|
|
2689
|
+
while (this.depth) {
|
|
2690
|
+
if (this.position > end) {
|
|
2691
|
+
this.neededLength = this.position;
|
|
2692
|
+
return false
|
|
2693
|
+
}
|
|
2694
|
+
const frame = this.frames[this.depth - 1];
|
|
2695
|
+
if (frame.kind === 'bundle') {
|
|
2696
|
+
if (frame.stage === 0) {
|
|
2697
|
+
if (!this.header(source, end, true)) return false
|
|
2698
|
+
frame.remaining = Math.max(0, this.argument - 2);
|
|
2699
|
+
frame.stage = 1;
|
|
2700
|
+
}
|
|
2701
|
+
if (frame.stage === 1) {
|
|
2702
|
+
const offsetStart = this.position;
|
|
2703
|
+
if (!this.header(source, end)) return false
|
|
2704
|
+
if (this.major > 1 || this.info === 31) throw new Error('Invalid bundled string offset')
|
|
2705
|
+
frame.target = offsetStart + (this.major === 1 ? -1 - this.argument : this.argument);
|
|
2706
|
+
if (!Number.isSafeInteger(frame.target) || frame.target < 0) throw new Error('Invalid bundled string offset')
|
|
2707
|
+
frame.stage = 2;
|
|
2708
|
+
}
|
|
2709
|
+
if (frame.stage === 2) {
|
|
2710
|
+
if (frame.remaining) {
|
|
2711
|
+
if (!this.header(source, end, true)) return false
|
|
2712
|
+
this.position += this.argument;
|
|
2713
|
+
frame.remaining--;
|
|
2714
|
+
continue
|
|
2715
|
+
}
|
|
2716
|
+
frame.resume = this.position;
|
|
2717
|
+
this.position = frame.target;
|
|
2718
|
+
frame.remaining = 2;
|
|
2719
|
+
frame.stage = 3;
|
|
2720
|
+
continue
|
|
2721
|
+
}
|
|
2722
|
+
if (frame.stage === 3) {
|
|
2723
|
+
if (frame.remaining) {
|
|
2724
|
+
if (!this.header(source, end, true)) return false
|
|
2725
|
+
this.position += this.argument;
|
|
2726
|
+
frame.remaining--;
|
|
2727
|
+
continue
|
|
2728
|
+
}
|
|
2729
|
+
this.postBundlePosition = this.position;
|
|
2730
|
+
this.position = frame.resume;
|
|
2731
|
+
frame.kind = 'items';
|
|
2732
|
+
frame.remaining = 1;
|
|
2733
|
+
continue
|
|
2734
|
+
}
|
|
2735
|
+
}
|
|
2736
|
+
if (frame.kind === 'record') {
|
|
2737
|
+
if (!this.header(source, end, true)) return false
|
|
2738
|
+
if (this.info > 26) throw new Error('Expected array header, but got ' + source[this.position - 1])
|
|
2739
|
+
frame.kind = 'items';
|
|
2740
|
+
frame.remaining = this.argument;
|
|
2741
|
+
const reader = frame.reader;
|
|
2742
|
+
if (reader.compiled.has(this.argument)) frame.remaining = Math.min(this.argument, reader.length);
|
|
2743
|
+
else if (reader.slowReads++ >= _stream.readThreshold) {
|
|
2744
|
+
reader.compiled.add(this.argument);
|
|
2745
|
+
frame.remaining = Math.min(this.argument, reader.length);
|
|
2746
|
+
}
|
|
2747
|
+
continue
|
|
2748
|
+
}
|
|
2749
|
+
if (frame.kind === 'definition' && frame.stage === 0) {
|
|
2750
|
+
const start = this.position;
|
|
2751
|
+
if (!this.header(source, end, !frame.legacy)) return false
|
|
2752
|
+
if (frame.legacy && this.major !== 4) {
|
|
2753
|
+
this.position = start;
|
|
2754
|
+
this.headers--;
|
|
2755
|
+
frame.kind = 'items';
|
|
2756
|
+
frame.remaining = 1;
|
|
2757
|
+
continue
|
|
2758
|
+
}
|
|
2759
|
+
frame.remaining = frame.legacy ? (this.info === 31 ? -1 : this.argument) : Math.max(2, this.argument);
|
|
2760
|
+
if (frame.legacy) {
|
|
2761
|
+
if (frame.remaining >= 0) _stream.checkContainer(4, frame.remaining);
|
|
2762
|
+
else frame.limitMajor = 4;
|
|
2763
|
+
frame.index = 0;
|
|
2764
|
+
}
|
|
2765
|
+
frame.total = frame.remaining;
|
|
2766
|
+
frame.stage = 1;
|
|
2767
|
+
continue
|
|
2768
|
+
}
|
|
2769
|
+
if (frame.remaining === 0) {
|
|
2770
|
+
if (frame.definition) this.records.set(frame.id - 0xe000, frame.definition);
|
|
2771
|
+
if (frame.restoreMap && this.restoreMap) {
|
|
2772
|
+
this.mapsAsObjects = true;
|
|
2773
|
+
this.restoreMap = false;
|
|
2774
|
+
}
|
|
2775
|
+
this.depth--;
|
|
2776
|
+
continue
|
|
2777
|
+
}
|
|
2778
|
+
if (!this.header(source, end)) return false
|
|
2779
|
+
let { major, argument, info } = this;
|
|
2780
|
+
if (frame.kind === 'definition') {
|
|
2781
|
+
const index = frame.legacy ? frame.index++ : frame.total - frame.remaining;
|
|
2782
|
+
if (index === 0 && major === 0) frame.id = argument;
|
|
2783
|
+
if ((frame.multiple ? index >= 1 && index < frame.total - 1 : index === 1) && major === 4 && info !== 31 && frame.id !== undefined) {
|
|
2784
|
+
const definition = { length: argument, slowReads: 0, compiled: new Set() };
|
|
2785
|
+
if (frame.legacy) frame.definition = definition;
|
|
2786
|
+
else this.records.set(frame.id - 0xe000 + (frame.multiple ? index - 1 : 0), definition);
|
|
2787
|
+
}
|
|
2788
|
+
}
|
|
2789
|
+
if (major === 7 && info === 31 && (frame.remaining === -1 || frame.remaining === -2)) {
|
|
2790
|
+
if (frame.definition) this.records.set(frame.id - 0xe000, frame.definition);
|
|
2791
|
+
this.depth--;
|
|
2792
|
+
continue
|
|
2793
|
+
}
|
|
2794
|
+
if (frame.limitMajor && (frame.remaining === -1 || frame.remaining === -2)) {
|
|
2795
|
+
_stream.checkContainer(frame.limitMajor, ++frame.count, frame.mapsAsObjects);
|
|
2796
|
+
}
|
|
2797
|
+
if (frame.remaining > 0) frame.remaining--;
|
|
2798
|
+
else if (frame.remaining === -2) frame.remaining = -3;
|
|
2799
|
+
else if (frame.remaining === -3) frame.remaining = -2;
|
|
2800
|
+
if (info === 31) {
|
|
2801
|
+
if (major === 2 || major === 3) throw new Error('Indefinite length not supported for byte or text strings')
|
|
2802
|
+
if (major === 4 || major === 5) {
|
|
2803
|
+
const container = this.push('items', major === 4 ? -1 : -2);
|
|
2804
|
+
container.limitMajor = major;
|
|
2805
|
+
container.mapsAsObjects = this.mapsAsObjects;
|
|
2806
|
+
if (major === 5 && this.restoreMap) {
|
|
2807
|
+
this.mapsAsObjects = true;
|
|
2808
|
+
this.restoreMap = false;
|
|
2809
|
+
}
|
|
2810
|
+
}
|
|
2811
|
+
else if (major === 7) throw new Error('Unexpected break stop code outside of an indefinite-length item')
|
|
2812
|
+
else throw new Error('Invalid major type for indefinite length ' + major)
|
|
2813
|
+
continue
|
|
2814
|
+
}
|
|
2815
|
+
switch (major) {
|
|
2816
|
+
case 2:
|
|
2817
|
+
case 3:
|
|
2818
|
+
this.position += argument;
|
|
2819
|
+
break
|
|
2820
|
+
case 4:
|
|
2821
|
+
case 5:
|
|
2822
|
+
_stream.checkContainer(major, argument, this.mapsAsObjects);
|
|
2823
|
+
if (major === 5 && this.restoreMap) {
|
|
2824
|
+
this.mapsAsObjects = true;
|
|
2825
|
+
this.restoreMap = false;
|
|
2826
|
+
}
|
|
2827
|
+
if (argument) this.push('items', major === 5 ? argument * 2 : argument);
|
|
2828
|
+
break
|
|
2829
|
+
case 6: {
|
|
2830
|
+
const structure = _stream.getTag(argument, this.decoder);
|
|
2831
|
+
let reader = this.records.get(argument & 0x1fff);
|
|
2832
|
+
if (argument >= 0xdff9 && (structure || reader)) {
|
|
2833
|
+
if (!reader) {
|
|
2834
|
+
reader = this.readers.get(structure);
|
|
2835
|
+
if (!reader) {
|
|
2836
|
+
reader = { length: structure.length, slowReads: structure.slowReads || 0, compiled: new Set() };
|
|
2837
|
+
for (let compiled = structure.compiledReader; compiled; compiled = compiled.next) reader.compiled.add(compiled.propertyCount);
|
|
2838
|
+
this.readers.set(structure, reader);
|
|
2839
|
+
}
|
|
2840
|
+
}
|
|
2841
|
+
this.push('record').reader = reader;
|
|
2842
|
+
} else if (argument === 0xdff9) {
|
|
2843
|
+
this.push('bundle');
|
|
2844
|
+
} else if (argument === 0xdfff || argument === 0xdffe) {
|
|
2845
|
+
this.push('definition').multiple = argument === 0xdffe;
|
|
2846
|
+
} else if (argument === 259 && _stream.isBuiltinTag(argument) && this.mapsAsObjects) {
|
|
2847
|
+
this.push('items', 1).restoreMap = true;
|
|
2848
|
+
this.mapsAsObjects = false;
|
|
2849
|
+
this.restoreMap = true;
|
|
2850
|
+
} else if (argument === 105 && _stream.isBuiltinTag(argument)) {
|
|
2851
|
+
const definition = this.push('definition');
|
|
2852
|
+
definition.multiple = false;
|
|
2853
|
+
definition.legacy = true;
|
|
2854
|
+
} else {
|
|
2855
|
+
this.push('items', 1);
|
|
2856
|
+
}
|
|
2857
|
+
break
|
|
2858
|
+
}
|
|
2859
|
+
}
|
|
2860
|
+
}
|
|
2861
|
+
if (this.postBundlePosition) {
|
|
2862
|
+
if (this.position >= this.postBundlePosition) throw new Error('Unexpected bundle position')
|
|
2863
|
+
this.position = this.postBundlePosition;
|
|
2864
|
+
}
|
|
2865
|
+
if (this.frames.length > 256) this.frames.length = 256;
|
|
2866
|
+
return true
|
|
2867
|
+
}
|
|
2868
|
+
}
|
|
2869
|
+
|
|
2481
2870
|
/**
|
|
2482
2871
|
* Given an Iterable first argument, returns an Iterable where each value is encoded as a Buffer
|
|
2483
2872
|
* If the argument is only Async Iterable, the return value will be an Async Iterable.
|
|
@@ -2515,7 +2904,7 @@
|
|
|
2515
2904
|
* Given an Iterable/Iterator input which yields buffers, returns an IterableIterator which yields sync decoded objects
|
|
2516
2905
|
* Or, given an Async Iterable/Iterator which yields promises resolving in buffers, returns an AsyncIterableIterator.
|
|
2517
2906
|
* @param {Iterable|Iterator|AsyncIterable|AsyncIterableIterator} bufferIterator
|
|
2518
|
-
* @param {object} [options] - Decoder options
|
|
2907
|
+
* @param {object} [options] - Decoder options, and maxIncompleteBufferSize
|
|
2519
2908
|
* @returns {IterableIterator|Promise.<AsyncIterableIterator}
|
|
2520
2909
|
*/
|
|
2521
2910
|
function decodeIter (bufferIterator, options = {}) {
|
|
@@ -2524,26 +2913,15 @@
|
|
|
2524
2913
|
}
|
|
2525
2914
|
|
|
2526
2915
|
const decoder = new Decoder(options);
|
|
2527
|
-
|
|
2916
|
+
const chunkDecoder = new ChunkDecoder(decoder, options.maxIncompleteBufferSize);
|
|
2917
|
+
let fatalError;
|
|
2528
2918
|
const parser = (chunk) => {
|
|
2529
|
-
let yields;
|
|
2530
|
-
// if there's incomplete data from previous chunk, concatinate and try again
|
|
2531
|
-
if (incomplete) {
|
|
2532
|
-
chunk = Buffer.concat([incomplete, chunk]);
|
|
2533
|
-
incomplete = undefined;
|
|
2534
|
-
}
|
|
2535
|
-
|
|
2536
2919
|
try {
|
|
2537
|
-
|
|
2538
|
-
} catch (
|
|
2539
|
-
|
|
2540
|
-
|
|
2541
|
-
incomplete = chunk.slice(err.lastPosition);
|
|
2542
|
-
} else {
|
|
2543
|
-
fatalError = err;
|
|
2544
|
-
}
|
|
2920
|
+
return chunkDecoder.buffer ? chunkDecoder.decodeAfterIncomplete(chunk) : decoder.decodeMultiple(chunk)
|
|
2921
|
+
} catch (error) {
|
|
2922
|
+
fatalError = chunkDecoder.keepIncomplete(error, chunk);
|
|
2923
|
+
return (error && error.values) || []
|
|
2545
2924
|
}
|
|
2546
|
-
return yields || []
|
|
2547
2925
|
};
|
|
2548
2926
|
|
|
2549
2927
|
if (typeof bufferIterator[Symbol.iterator] === 'function') {
|
|
@@ -2552,6 +2930,8 @@
|
|
|
2552
2930
|
yield * parser(value);
|
|
2553
2931
|
if (fatalError) throw fatalError
|
|
2554
2932
|
}
|
|
2933
|
+
const endError = chunkDecoder.end();
|
|
2934
|
+
if (endError) throw endError
|
|
2555
2935
|
})()
|
|
2556
2936
|
} else if (typeof bufferIterator[Symbol.asyncIterator] === 'function') {
|
|
2557
2937
|
return (async function * iter () {
|
|
@@ -2559,10 +2939,122 @@
|
|
|
2559
2939
|
yield * parser(value);
|
|
2560
2940
|
if (fatalError) throw fatalError
|
|
2561
2941
|
}
|
|
2942
|
+
const endError = chunkDecoder.end();
|
|
2943
|
+
if (endError) throw endError
|
|
2562
2944
|
})()
|
|
2563
2945
|
}
|
|
2564
2946
|
}
|
|
2565
2947
|
|
|
2948
|
+
/**
|
|
2949
|
+
* Keeps the bytes of a value that a chunk of a stream ends inside of, for DecoderStream and decodeIter, and decodes
|
|
2950
|
+
* them again once enough have arrived to possibly complete it. Callers decode a chunk with decodeAfterIncomplete if
|
|
2951
|
+
* buffer is set, or else directly with decodeMultiple, and pass any error to keepIncomplete, which returns the error
|
|
2952
|
+
* to report, if any. end returns an error if the input ended inside a value.
|
|
2953
|
+
*/
|
|
2954
|
+
class ChunkDecoder {
|
|
2955
|
+
constructor (decoder, maxIncompleteBufferSize) {
|
|
2956
|
+
this.decoder = decoder;
|
|
2957
|
+
if (maxIncompleteBufferSize === undefined) maxIncompleteBufferSize = 0x4000000;
|
|
2958
|
+
if (typeof maxIncompleteBufferSize !== 'number' || !(maxIncompleteBufferSize >= 0)) {
|
|
2959
|
+
throw new TypeError('maxIncompleteBufferSize must be a non-negative number')
|
|
2960
|
+
}
|
|
2961
|
+
this.maxIncompleteBufferSize = Math.floor(maxIncompleteBufferSize);
|
|
2962
|
+
// buffer[0, bufferEnd) is the incomplete value; no decoded value is a view of buffer while it is kept here
|
|
2963
|
+
this.buffer = null;
|
|
2964
|
+
this.bufferEnd = 0;
|
|
2965
|
+
this.appends = 0;
|
|
2966
|
+
this.scanner = null;
|
|
2967
|
+
this.scanned = false;
|
|
2968
|
+
this.resetScanner = false;
|
|
2969
|
+
this.neededLength = 0; // a lower bound on the incomplete value's length
|
|
2970
|
+
}
|
|
2971
|
+
|
|
2972
|
+
decodeAfterIncomplete (chunk) {
|
|
2973
|
+
if (!(ArrayBuffer.isView(chunk) && chunk.BYTES_PER_ELEMENT === 1)) {
|
|
2974
|
+
throw new TypeError('Source must be a Uint8Array or Buffer')
|
|
2975
|
+
}
|
|
2976
|
+
const length = this.bufferEnd + chunk.length;
|
|
2977
|
+
if (length < this.neededLength && length > this.maxIncompleteBufferSize) throw maxIncompleteBufferSizeError()
|
|
2978
|
+
if (length > this.buffer.length) {
|
|
2979
|
+
// Values usually complete within two appends, which are sized exactly. After that the buffer grows by at least
|
|
2980
|
+
// the bytes already kept, so that they are copied a bounded number of times however small the chunks are.
|
|
2981
|
+
const size = this.appends < 2 ? length
|
|
2982
|
+
: Math.max(length, Math.min(length + this.bufferEnd, this.maxIncompleteBufferSize));
|
|
2983
|
+
const buffer = Buffer.allocUnsafe(size);
|
|
2984
|
+
if (size > length) buffer.fill(0, length); // decoded values are views of this buffer, so no uninitialized memory
|
|
2985
|
+
buffer.set(this.buffer.subarray(0, this.bufferEnd));
|
|
2986
|
+
this.buffer = buffer;
|
|
2987
|
+
}
|
|
2988
|
+
this.buffer.set(chunk, this.bufferEnd);
|
|
2989
|
+
this.bufferEnd = length;
|
|
2990
|
+
this.appends++;
|
|
2991
|
+
if (length < this.neededLength) return []
|
|
2992
|
+
if (!this.scanner) this.scanner = new StructureScanner(this.decoder);
|
|
2993
|
+
if (this.resetScanner) {
|
|
2994
|
+
this.scanner.reset();
|
|
2995
|
+
this.resetScanner = false;
|
|
2996
|
+
}
|
|
2997
|
+
if (!this.scanner.scan(this.buffer, length)) {
|
|
2998
|
+
this.neededLength = this.scanner.neededLength;
|
|
2999
|
+
if (length > this.maxIncompleteBufferSize) throw maxIncompleteBufferSizeError()
|
|
3000
|
+
return []
|
|
3001
|
+
}
|
|
3002
|
+
this.scanned = true;
|
|
3003
|
+
const values = _stream.decode(this.decoder, this.buffer.subarray(0, length), this.scanner.position);
|
|
3004
|
+
this.scanned = false;
|
|
3005
|
+
this.buffer = null;
|
|
3006
|
+
return values
|
|
3007
|
+
}
|
|
3008
|
+
|
|
3009
|
+
keepIncomplete (error, chunk) {
|
|
3010
|
+
// an extension may throw any value, and a falsy one would read as success
|
|
3011
|
+
if (!error) return this.fail(new Error('Decoding failed: ' + error))
|
|
3012
|
+
if (!error.incomplete) return this.fail(error)
|
|
3013
|
+
if (this.scanned && error.lastPosition === 0) {
|
|
3014
|
+
error.incomplete = false;
|
|
3015
|
+
return this.fail(error)
|
|
3016
|
+
}
|
|
3017
|
+
const source = this.buffer ? this.buffer.subarray(0, this.bufferEnd) : chunk;
|
|
3018
|
+
const length = source.length - error.lastPosition;
|
|
3019
|
+
if (length > this.maxIncompleteBufferSize) return this.fail(maxIncompleteBufferSizeError())
|
|
3020
|
+
if (!this.buffer || error.lastPosition > 0) {
|
|
3021
|
+
if (length === 0) return
|
|
3022
|
+
try {
|
|
3023
|
+
// copied, so that the remainder does not keep in memory the chunk, or the buffer that the values before it
|
|
3024
|
+
// are views of
|
|
3025
|
+
this.buffer = Buffer.from(source.subarray(error.lastPosition));
|
|
3026
|
+
} catch (copyError) {
|
|
3027
|
+
return this.fail(copyError)
|
|
3028
|
+
}
|
|
3029
|
+
this.bufferEnd = length;
|
|
3030
|
+
this.appends = 0;
|
|
3031
|
+
}
|
|
3032
|
+
this.scanned = false;
|
|
3033
|
+
this.resetScanner = true;
|
|
3034
|
+
this.neededLength = Math.max(length + 1, error.neededEnd ? error.neededEnd - error.lastPosition : 0);
|
|
3035
|
+
}
|
|
3036
|
+
|
|
3037
|
+
end () {
|
|
3038
|
+
if (this.buffer) {
|
|
3039
|
+
const error = this.fail(new Error('Unexpected end of CBOR data'));
|
|
3040
|
+
error.incomplete = true;
|
|
3041
|
+
return error
|
|
3042
|
+
}
|
|
3043
|
+
}
|
|
3044
|
+
|
|
3045
|
+
fail (error) {
|
|
3046
|
+
this.buffer = null;
|
|
3047
|
+
this.scanner = null;
|
|
3048
|
+
this.scanned = false;
|
|
3049
|
+
this.resetScanner = false;
|
|
3050
|
+
return error
|
|
3051
|
+
}
|
|
3052
|
+
}
|
|
3053
|
+
|
|
3054
|
+
function maxIncompleteBufferSizeError () {
|
|
3055
|
+
return new Error('Maximum incomplete buffer size exceeded')
|
|
3056
|
+
}
|
|
3057
|
+
|
|
2566
3058
|
exports.ALWAYS = ALWAYS;
|
|
2567
3059
|
exports.DECIMAL_FIT = DECIMAL_FIT;
|
|
2568
3060
|
exports.DECIMAL_ROUND = DECIMAL_ROUND;
|