mirror of
https://github.com/fluencelabs/assemblyscript-json
synced 2025-04-25 14:52:24 +00:00
Refactor parser state into separate class
This commit is contained in:
parent
b036c86f5f
commit
f3800cc7d7
@ -75,33 +75,42 @@ let CHAR_9 = "9".charCodeAt(0);
|
|||||||
let CHAR_A = "A".charCodeAt(0);
|
let CHAR_A = "A".charCodeAt(0);
|
||||||
let CHAR_A_LOWER = "a".charCodeAt(0);
|
let CHAR_A_LOWER = "a".charCodeAt(0);
|
||||||
|
|
||||||
export class JSONDecoder<JSONHandlerT extends JSONHandler> {
|
export class DecoderState {
|
||||||
|
|
||||||
handler: JSONHandlerT;
|
|
||||||
readIndex: i32 = 0;
|
readIndex: i32 = 0;
|
||||||
buffer: Uint8Array = null;
|
buffer: Uint8Array = null;
|
||||||
lastKey: string = null;
|
lastKey: string = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class JSONDecoder<JSONHandlerT extends JSONHandler> {
|
||||||
|
|
||||||
|
handler: JSONHandlerT;
|
||||||
|
state: DecoderState;
|
||||||
|
|
||||||
constructor(handler: JSONHandlerT) {
|
constructor(handler: JSONHandlerT) {
|
||||||
this.handler = handler;
|
this.handler = handler;
|
||||||
}
|
}
|
||||||
|
|
||||||
deserialize(buffer: Uint8Array, startIndex: i32 = 0): void {
|
deserialize(buffer: Uint8Array, decoderState: DecoderState = null): void {
|
||||||
this.readIndex = startIndex;
|
if (decoderState) {
|
||||||
this.buffer = buffer;
|
this.state = decoderState;
|
||||||
this.lastKey = null
|
} else {
|
||||||
|
this.state = new DecoderState();
|
||||||
|
this.state.readIndex = 0;
|
||||||
|
this.state.buffer = buffer;
|
||||||
|
this.state.lastKey = null;
|
||||||
|
}
|
||||||
|
|
||||||
assert(this.parseValue(), "Cannot parse JSON");
|
assert(this.parseValue(), "Cannot parse JSON");
|
||||||
// TODO: Error if input left
|
// TODO: Error if input left
|
||||||
}
|
}
|
||||||
|
|
||||||
private peekChar(): i32 {
|
private peekChar(): i32 {
|
||||||
return this.buffer[this.readIndex];
|
return this.state.buffer[this.state.readIndex];
|
||||||
}
|
}
|
||||||
|
|
||||||
private readChar(): i32 {
|
private readChar(): i32 {
|
||||||
assert(this.readIndex < this.buffer.length, "Unexpected input end");
|
assert(this.state.readIndex < this.state.buffer.length, "Unexpected input end");
|
||||||
return this.buffer[this.readIndex++];
|
return this.state.buffer[this.state.readIndex++];
|
||||||
}
|
}
|
||||||
|
|
||||||
private parseValue(): bool {
|
private parseValue(): bool {
|
||||||
@ -120,7 +129,7 @@ export class JSONDecoder<JSONHandlerT extends JSONHandler> {
|
|||||||
if (this.peekChar() != "{".charCodeAt(0)) {
|
if (this.peekChar() != "{".charCodeAt(0)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (this.handler.pushObject(this.lastKey)) {
|
if (this.handler.pushObject(this.state.lastKey)) {
|
||||||
this.readChar();
|
this.readChar();
|
||||||
this.skipWhitespace();
|
this.skipWhitespace();
|
||||||
|
|
||||||
@ -142,7 +151,7 @@ export class JSONDecoder<JSONHandlerT extends JSONHandler> {
|
|||||||
|
|
||||||
private parseKey(): void {
|
private parseKey(): void {
|
||||||
this.skipWhitespace();
|
this.skipWhitespace();
|
||||||
this.lastKey = this.readString();
|
this.state.lastKey = this.readString();
|
||||||
this.skipWhitespace();
|
this.skipWhitespace();
|
||||||
assert(this.readChar() == ":".charCodeAt(0), "Expected ':'");
|
assert(this.readChar() == ":".charCodeAt(0), "Expected ':'");
|
||||||
}
|
}
|
||||||
@ -151,8 +160,8 @@ export class JSONDecoder<JSONHandlerT extends JSONHandler> {
|
|||||||
if (this.peekChar() != "[".charCodeAt(0)) {
|
if (this.peekChar() != "[".charCodeAt(0)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (this.handler.pushArray(this.lastKey)) {
|
if (this.handler.pushArray(this.state.lastKey)) {
|
||||||
this.lastKey = null;
|
this.state.lastKey = null;
|
||||||
this.readChar();
|
this.readChar();
|
||||||
this.skipWhitespace();
|
this.skipWhitespace();
|
||||||
|
|
||||||
@ -175,13 +184,13 @@ export class JSONDecoder<JSONHandlerT extends JSONHandler> {
|
|||||||
if (this.peekChar() != '"'.charCodeAt(0)) {
|
if (this.peekChar() != '"'.charCodeAt(0)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
this.handler.setString(this.lastKey, this.readString());
|
this.handler.setString(this.state.lastKey, this.readString());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private readString(): string {
|
private readString(): string {
|
||||||
assert(this.readChar() == '"'.charCodeAt(0), "Expected double-quoted string");
|
assert(this.readChar() == '"'.charCodeAt(0), "Expected double-quoted string");
|
||||||
let savedIndex = this.readIndex;
|
let savedIndex = this.state.readIndex;
|
||||||
let stringParts: Array<string> = new Array<string>();
|
let stringParts: Array<string> = new Array<string>();
|
||||||
for (;;) {
|
for (;;) {
|
||||||
let byte = this.readChar();
|
let byte = this.readChar();
|
||||||
@ -189,16 +198,16 @@ export class JSONDecoder<JSONHandlerT extends JSONHandler> {
|
|||||||
// TODO: Make sure unicode handled properly
|
// TODO: Make sure unicode handled properly
|
||||||
if (byte == '"'.charCodeAt(0)) {
|
if (byte == '"'.charCodeAt(0)) {
|
||||||
stringParts.push(
|
stringParts.push(
|
||||||
String.fromUTF8(this.buffer.buffer.data + savedIndex, this.readIndex - savedIndex - 1));
|
String.fromUTF8(this.state.buffer.buffer.data + savedIndex, this.state.readIndex - savedIndex - 1));
|
||||||
return stringParts.join("");
|
return stringParts.join("");
|
||||||
}
|
}
|
||||||
if (byte == "\\".charCodeAt(0)) {
|
if (byte == "\\".charCodeAt(0)) {
|
||||||
if (this.readIndex > savedIndex + 1) {
|
if (this.state.readIndex > savedIndex + 1) {
|
||||||
stringParts.push(
|
stringParts.push(
|
||||||
String.fromUTF8(this.buffer.buffer.data + savedIndex, this.readIndex - savedIndex - 1));
|
String.fromUTF8(this.state.buffer.buffer.data + savedIndex, this.state.readIndex - savedIndex - 1));
|
||||||
}
|
}
|
||||||
stringParts.push(this.readEscapedChar());
|
stringParts.push(this.readEscapedChar());
|
||||||
savedIndex = this.readIndex;
|
savedIndex = this.state.readIndex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Should never happen
|
// Should never happen
|
||||||
@ -271,7 +280,7 @@ export class JSONDecoder<JSONHandlerT extends JSONHandler> {
|
|||||||
digits++;
|
digits++;
|
||||||
}
|
}
|
||||||
if (digits > 0) {
|
if (digits > 0) {
|
||||||
this.handler.setInteger(this.lastKey, number * sign);
|
this.handler.setInteger(this.state.lastKey, number * sign);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@ -280,12 +289,12 @@ export class JSONDecoder<JSONHandlerT extends JSONHandler> {
|
|||||||
private parseBoolean(): bool {
|
private parseBoolean(): bool {
|
||||||
if (this.peekChar() == FALSE_STR.charCodeAt(0)) {
|
if (this.peekChar() == FALSE_STR.charCodeAt(0)) {
|
||||||
this.readAndAssert(FALSE_STR);
|
this.readAndAssert(FALSE_STR);
|
||||||
this.handler.setBoolean(this.lastKey, false);
|
this.handler.setBoolean(this.state.lastKey, false);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (this.peekChar() == TRUE_STR.charCodeAt(0)) {
|
if (this.peekChar() == TRUE_STR.charCodeAt(0)) {
|
||||||
this.readAndAssert(TRUE_STR);
|
this.readAndAssert(TRUE_STR);
|
||||||
this.handler.setBoolean(this.lastKey, true);
|
this.handler.setBoolean(this.state.lastKey, true);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -295,7 +304,7 @@ export class JSONDecoder<JSONHandlerT extends JSONHandler> {
|
|||||||
private parseNull(): bool {
|
private parseNull(): bool {
|
||||||
if (this.peekChar() == NULL_STR.charCodeAt(0)) {
|
if (this.peekChar() == NULL_STR.charCodeAt(0)) {
|
||||||
this.readAndAssert(NULL_STR);
|
this.readAndAssert(NULL_STR);
|
||||||
this.handler.setNull(this.lastKey);
|
this.handler.setNull(this.state.lastKey);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user