Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 | 2x 2x 24x 24x 2x 7860x 7860x 31x 7x 1857x 1857x 1857x 1857x 1857x 1857x 3495x 3495x 3495x 1649x 1176x 1642x 1642x 1642x 4x 4x 1638x 2739x 2739x 2739x 2739x 2739x 12218x 12218x 12218x 9499x 3434x 3434x 6065x 6065x 6065x 6052x 6052x 6052x 6052x 6048x 6048x 6048x 3x 3x 20x 20x | import {JsonDecoder, readKey} from './JsonDecoder';
import type {PackValue} from '../types';
export class DecodeFinishError extends Error {
constructor(public readonly value: unknown) {
super('DECODE_FINISH');
}
}
/**
* This class parses JSON which is mostly correct but not necessarily complete
* or with missing parts. It can be used to parse JSON that is being streamed
* in chunks or JSON output of an LLM model.
*
* If the end of a nested JSON value (array, object) is missing, this parser
* will return the initial correct part for that value, which it was able to
* parse, until the point where the JSON is no longer valid.
*
* Examples:
*
* ```js
* // Missing closing brace
* decoder.readAny('[1, 2, 3'); // [1, 2, 3]
*
* // Trailing comma and missing closing brace
* decoder.readAny('[1, 2, '); // [1, 2]
*
* // Corrupt second element and missing closing brace
* decoder.readAny('{"foo": 1, "bar":'); // {"foo": 1}
* ```
*/
export class JsonDecoderPartial extends JsonDecoder {
public readAny(): unknown {
try {
return super.readAny();
} catch (error) {
if (error instanceof DecodeFinishError) return error.value;
throw error;
}
}
public readArr(): unknown[] {
const reader = this.reader;
Iif (reader.u8() !== 0x5b /* [ */) throw new Error('Invalid JSON');
const arr: unknown[] = [];
const uint8 = reader.uint8;
let first = true;
while (true) {
this.skipWhitespace();
const char = uint8[reader.x];
if (char === 0x5d /* ] */) return reader.x++, arr;
if (char === 0x2c /* , */) reader.x++;
else if (!first) return arr;
this.skipWhitespace();
try {
arr.push(this.readAny());
} catch (error) {
Iif (error instanceof DecodeFinishError) return arr.push(error.value), arr;
if (error instanceof Error && error.message === 'Invalid JSON') throw new DecodeFinishError(arr);
throw error;
}
first = false;
}
}
public readObj(): PackValue | Record<string, unknown> | unknown {
const reader = this.reader;
Iif (reader.u8() !== 0x7b /* { */) throw new Error('Invalid JSON');
const obj: Record<string, unknown> = {};
const uint8 = reader.uint8;
while (true) {
this.skipWhitespace();
let char = uint8[reader.x];
if (char === 0x7d /* } */) return reader.x++, obj;
if (char === 0x2c /* , */) {
reader.x++;
continue;
}
try {
char = uint8[reader.x++];
if (char !== 0x22 /* " */) throw new Error('Invalid JSON');
const key = readKey(reader);
Iif (key === '__proto__') throw new Error('Invalid JSON');
this.skipWhitespace();
if (reader.u8() !== 0x3a /* : */) throw new Error('Invalid JSON');
this.skipWhitespace();
try {
obj[key] = this.readAny();
} catch (error) {
Iif (error instanceof DecodeFinishError) {
obj[key] = error.value;
return obj;
}
throw error;
}
} catch (error) {
Iif (error instanceof DecodeFinishError) return obj;
if (error instanceof Error && error.message === 'Invalid JSON') throw new DecodeFinishError(obj);
throw error;
}
}
}
}
|