public ValueParseResult TryParse(ReadOnlySpan <byte> readerSpan, out JsonValue result, out int consumedLength, out int lineSpan, out int colSpan) { result = null; consumedLength = 0; lineSpan = 1; colSpan = 0; // is input empty if (readerSpan.Length <= 0 && this._innerReader == null) { // did any prior processing occur return(this._innerReader != null ? _cleanup(this, ValueParseResult.FailureEOF) : ValueParseResult.EOF); } // continue parsing? if (this._innerReader != null) { var innerResult = this.ParseInner(readerSpan, out result, ref consumedLength); switch (innerResult.Type) { case ValueParseResultType.Success: this._innerReader.Dispose(); this._innerReader = null; return(_cleanup(this, innerResult)); case ValueParseResultType.EOF: return(innerResult); case ValueParseResultType.Failure: return(_cleanup(this, innerResult)); } } // not continuing, find any token while (consumedLength < readerSpan.Length) { switch (readerSpan[consumedLength++]) { case JsonTokens.WhitespaceSpace: ++this._colSpan; ++this._streamPos; break; case JsonTokens.WhitespaceHorizontalTab: this._colSpan += 4; // fite me ++this._streamPos; break; case JsonTokens.WhitespaceCarriageReturn: // usually as part of CRLF, really no other reason for it to exist // old macs don't exist break; case JsonTokens.WhitespaceNewline: ++this._lineSpan; this._colSpan = 0; ++this._streamPos; break; case JsonTokens.NullFirst: this._innerReader = new JsonNullReader(); break; case JsonTokens.TrueFirst: case JsonTokens.FalseFirst: this._innerReader = new JsonBooleanReader(); break; case JsonTokens.NumberSign: case JsonTokens.Digit0: case JsonTokens.Digit1: case JsonTokens.Digit2: case JsonTokens.Digit3: case JsonTokens.Digit4: case JsonTokens.Digit5: case JsonTokens.Digit6: case JsonTokens.Digit7: case JsonTokens.Digit8: case JsonTokens.Digit9: this._innerReader = new JsonNumberReader(); break; case JsonTokens.QuoteMark: this._innerReader = new JsonStringReader(); break; case JsonTokens.OpeningBracket: this._innerReader = new JsonArrayReader(new ValueReaderCollection()); break; case JsonTokens.OpeningBrace: this._innerReader = new JsonObjectReader(new ValueReaderCollection()); break; default: if (Rune.DecodeFromUtf8(readerSpan[(consumedLength - 1)..], out var rune, out _) != OperationStatus.Done)
public ValueParseResult TryParse(ReadOnlySpan <byte> readerSpan, out ImmutableArray <JsonValue> result, out int consumedLength, out int lineSpan, out int colSpan) { result = default; consumedLength = 0; lineSpan = 1; colSpan = 0; // is input empty if (readerSpan.Length <= 0 && this._innerReader == null) { // did any prior processing occur return(this._arr != null ? _cleanup(this, ValueParseResult.FailureEOF) : ValueParseResult.EOF); } // if we are not continuing, ensure it's an object that's being parsed if (this._arr == null) { if (readerSpan[consumedLength++] != JsonTokens.OpeningBracket) { if (Rune.DecodeFromUtf8(readerSpan, out var rune, out _) != OperationStatus.Done) { rune = default; } return(_cleanup(this, ValueParseResult.Failure("Unexpected token, expected {.", rune))); } this._expectedNext = ExpectedToken.ValueOrEnd; this._arr = ImmutableArray.CreateBuilder <JsonValue>(); ++this._colSpan; ++this._streamPos; } // if continuing, check if any value is being parsed if (this._innerReader != null) { // valid only if expecting value if (this._expectedNext != ExpectedToken.Value && this._expectedNext != ExpectedToken.ValueOrEnd) { return(_cleanup(this, ValueParseResult.Failure("Invalid internal state.", default))); } // parse inner value ++consumedLength; var innerResult = this.ParseInner(readerSpan, ref consumedLength); switch (innerResult.Type) { case ValueParseResultType.Success: this._innerReader.Reset(); this._innerReader = null; break; case ValueParseResultType.EOF: return(innerResult); case ValueParseResultType.Failure: return(_cleanup(this, innerResult)); } } // read and parse array items var completedParsing = false; while (consumedLength < readerSpan.Length) { switch (readerSpan[consumedLength++]) { case JsonTokens.WhitespaceSpace: ++this._colSpan; ++this._streamPos; break; case JsonTokens.WhitespaceHorizontalTab: this._colSpan += 4; // fite me ++this._streamPos; break; case JsonTokens.WhitespaceCarriageReturn: // usually as part of CRLF, really no other reason for it to exist // old macs don't exist break; case JsonTokens.WhitespaceNewline: ++this._lineSpan; this._colSpan = 0; ++this._streamPos; break; case JsonTokens.ItemSeparator: if (this._expectedNext != ExpectedToken.ItemSeparatorOrEnd) { return(_cleanup(this, ValueParseResult.Failure("Unexpected item separator.", new Rune(JsonTokens.ItemSeparator)))); } ++this._colSpan; ++this._streamPos; this._expectedNext = ExpectedToken.Value; break; case JsonTokens.ClosingBracket: if (this._expectedNext != ExpectedToken.ItemSeparatorOrEnd && this._expectedNext != ExpectedToken.ValueOrEnd) { return(_cleanup(this, ValueParseResult.Failure("Unexpected array end.", new Rune(JsonTokens.ClosingBracket)))); } ++this._colSpan; ++this._streamPos; completedParsing = true; break; case JsonTokens.NullFirst: if (this._expectedNext != ExpectedToken.Value && this._expectedNext != ExpectedToken.ValueOrEnd) { return(_cleanup(this, ValueParseResult.Failure("Unexpected array item (null).", new Rune(JsonTokens.NullFirst)))); } this._innerReader = this._innerReaders.NullReader; break; case JsonTokens.TrueFirst: case JsonTokens.FalseFirst: if (this._expectedNext != ExpectedToken.Value && this._expectedNext != ExpectedToken.ValueOrEnd) { return(_cleanup(this, ValueParseResult.Failure("Unexpected array item (boolean).", new Rune(readerSpan[consumedLength - 1])))); } this._innerReader = this._innerReaders.BooleanReader; break; case JsonTokens.NumberSign: case JsonTokens.Digit0: case JsonTokens.Digit1: case JsonTokens.Digit2: case JsonTokens.Digit3: case JsonTokens.Digit4: case JsonTokens.Digit5: case JsonTokens.Digit6: case JsonTokens.Digit7: case JsonTokens.Digit8: case JsonTokens.Digit9: if (this._expectedNext != ExpectedToken.Value && this._expectedNext != ExpectedToken.ValueOrEnd) { return(_cleanup(this, ValueParseResult.Failure("Unexpected array item (number).", new Rune(readerSpan[consumedLength - 1])))); } this._innerReader = this._innerReaders.NumberReader; break; case JsonTokens.QuoteMark: if (this._expectedNext != ExpectedToken.Value && this._expectedNext != ExpectedToken.ValueOrEnd) { return(_cleanup(this, ValueParseResult.Failure("Unexpected array item (string).", new Rune(JsonTokens.QuoteMark)))); } this._innerReader = this._innerReaders.StringReader; break; case JsonTokens.OpeningBracket: if (this._expectedNext != ExpectedToken.Value && this._expectedNext != ExpectedToken.ValueOrEnd) { return(_cleanup(this, ValueParseResult.Failure("Unexpected array item (array).", new Rune(JsonTokens.OpeningBracket)))); } this._innerReader = new JsonArrayReader(this._innerReaders); break; case JsonTokens.OpeningBrace: if (this._expectedNext != ExpectedToken.Value && this._expectedNext != ExpectedToken.ValueOrEnd) { return(_cleanup(this, ValueParseResult.Failure("Unexpected array item (object).", new Rune(JsonTokens.OpeningBracket)))); } this._innerReader = new JsonObjectReader(this._innerReaders); break; default: if (Rune.DecodeFromUtf8(readerSpan[(consumedLength - 1)..], out var rune, out _) != OperationStatus.Done)