/// <inheritdoc /> public override bool Read() { JsonTokenType jsonTokenType; int nextTokenOffset; // First check if we just finished an array or object context if (!this.arrayAndObjectEndStack.Empty() && (this.arrayAndObjectEndStack.Peek() == this.jsonBinaryBuffer.Position)) { if (this.JsonObjectState.InArrayContext) { jsonTokenType = JsonTokenType.EndArray; } else if (this.JsonObjectState.InObjectContext) { jsonTokenType = JsonTokenType.EndObject; } else { throw new JsonInvalidTokenException(); } nextTokenOffset = 0; this.arrayAndObjectEndStack.Pop(); } else { // We are not at the end of a context. if (this.jsonBinaryBuffer.IsEof) { // Need to check if we are still inside of an object or array if (this.JsonObjectState.CurrentDepth != 0) { if (this.JsonObjectState.InObjectContext) { throw new JsonMissingEndObjectException(); } else if (this.JsonObjectState.InArrayContext) { throw new JsonMissingEndArrayException(); } else { throw new InvalidOperationException("Expected to be in either array or object context"); } } return false; } if ((this.JsonObjectState.CurrentDepth == 0) && (this.CurrentTokenType != JsonTokenType.NotStarted)) { // There are trailing characters outside of the outter most object or array throw new JsonUnexpectedTokenException(); } byte firstByte = this.jsonBinaryBuffer.Peek(); jsonTokenType = JsonBinaryReader.GetJsonTokenType(firstByte); if ((jsonTokenType == JsonTokenType.String) && this.JsonObjectState.IsPropertyExpected) { jsonTokenType = JsonTokenType.FieldName; } // If this is begin array/object token then we need to identify where array/object end token is. // Also the next token offset is just the array type marker + length prefix + count prefix if ((jsonTokenType == JsonTokenType.BeginArray) || (jsonTokenType == JsonTokenType.BeginObject)) { if (!JsonBinaryEncoding.TryGetValueLength( this.jsonBinaryBuffer.GetBufferedRawJsonToken().Span, out int arrayOrObjectLength)) { throw new JsonUnexpectedTokenException(); } this.arrayAndObjectEndStack.Push(this.jsonBinaryBuffer.Position + arrayOrObjectLength); nextTokenOffset = JsonBinaryReader.GetArrayOrObjectPrefixLength(firstByte); } else { if (!JsonBinaryEncoding.TryGetValueLength( this.jsonBinaryBuffer.GetBufferedRawJsonToken().Span, out nextTokenOffset)) { throw new JsonUnexpectedTokenException(); } } } this.JsonObjectState.RegisterToken(jsonTokenType); this.currentTokenPosition = this.jsonBinaryBuffer.Position; this.jsonBinaryBuffer.SkipBytes(nextTokenOffset); return true; }
/// <inheritdoc /> public override bool Read() { // Check if we just finished an array or object context if (!this.arrayAndObjectEndStack.Empty() && this.arrayAndObjectEndStack.Peek() == this.jsonBinaryBuffer.Position) { if (this.JsonObjectState.InArrayContext) { this.JsonObjectState.RegisterEndArray(); } else if (this.JsonObjectState.InObjectContext) { this.JsonObjectState.RegisterEndObject(); } else { throw new JsonInvalidTokenException(); } this.currentTokenPosition = this.jsonBinaryBuffer.Position; this.arrayAndObjectEndStack.Pop(); } else if (this.jsonBinaryBuffer.IsEof) { // Need to check if we are still inside of an object or array if (this.JsonObjectState.CurrentDepth != 0) { if (this.JsonObjectState.InObjectContext) { throw new JsonMissingEndObjectException(); } if (this.JsonObjectState.InArrayContext) { throw new JsonMissingEndArrayException(); } throw new InvalidOperationException("Expected to be in either array or object context"); } return(false); } else if (this.JsonObjectState.CurrentDepth == 0 && this.CurrentTokenType != JsonTokenType.NotStarted) { // There are trailing characters outside of the outter most object or array throw new JsonUnexpectedTokenException(); } else { ReadOnlySpan <byte> readOnlySpan = this.jsonBinaryBuffer.GetBufferedRawJsonToken().Span; int nextTokenOffset = JsonBinaryEncoding.GetValueLength(readOnlySpan); byte typeMarker = readOnlySpan[0]; JsonTokenType jsonTokenType = JsonBinaryReader.GetJsonTokenType(typeMarker); switch (jsonTokenType) { case JsonTokenType.String when this.JsonObjectState.IsPropertyExpected: jsonTokenType = JsonTokenType.FieldName; break; // If this is begin array/object token then we need to identify where array/object end token is. // Also the next token offset is just the array type marker + length prefix + count prefix case JsonTokenType.BeginArray: case JsonTokenType.BeginObject: this.arrayAndObjectEndStack.Push(this.jsonBinaryBuffer.Position + nextTokenOffset); nextTokenOffset = JsonBinaryReader.GetArrayOrObjectPrefixLength(typeMarker); break; } this.JsonObjectState.RegisterToken(jsonTokenType); this.currentTokenPosition = this.jsonBinaryBuffer.Position; this.jsonBinaryBuffer.SkipBytes(nextTokenOffset); } return(true); }