/// <summary> /// Gets next JSON token from the JsonReader as a raw series of bytes that is buffered. /// </summary> /// <returns>The next JSON token from the JsonReader as a raw series of bytes that is buffered.</returns> public override ReadOnlyMemory <byte> GetBufferedRawJsonToken() { if (!JsonBinaryEncoding.TryGetValueLength( this.jsonBinaryBuffer.GetBufferedRawJsonToken(this.currentTokenPosition).Span, out int length)) { throw new InvalidOperationException(); } return(this.jsonBinaryBuffer.GetBufferedRawJsonToken(this.currentTokenPosition, this.currentTokenPosition + length)); }
/// <inheritdoc /> public override bool TryGetBufferedRawJsonToken(out ReadOnlyMemory<byte> bufferedRawJsonToken) { if (!JsonBinaryEncoding.TryGetValueLength( this.jsonBinaryBuffer.GetBufferedRawJsonToken(this.currentTokenPosition).Span, out int length)) { throw new InvalidOperationException(); } ReadOnlyMemory<byte> candidate = this.jsonBinaryBuffer.GetBufferedRawJsonToken( this.currentTokenPosition, this.currentTokenPosition + length); if ((this.jsonStringDictionary != null) && JsonBinaryReader.IsStringOrNested(this.CurrentTokenType)) { // If there is dictionary encoding, then we need to force a rewrite. bufferedRawJsonToken = default; return false; } bufferedRawJsonToken = candidate; return true; }
/// <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; }