<PackageReference Include="System.Text.Json" Version="9.0.5" />

Utf8JsonReader

public struct Utf8JsonReader
Provides a high-performance API for forward-only, read-only access to UTF-8 encoded JSON text.
using System.Buffers; using System.Buffers.Text; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; namespace System.Text.Json { [DebuggerDisplay("{DebuggerDisplay,nq}")] public ref struct Utf8JsonReader { private readonly struct PartialStateForRollback { public readonly long _prevTotalConsumed; public readonly long _prevBytePositionInLine; public readonly int _prevConsumed; public readonly SequencePosition _prevCurrentPosition; public PartialStateForRollback(long totalConsumed, long bytePositionInLine, int consumed, SequencePosition currentPosition) { _prevTotalConsumed = totalConsumed; _prevBytePositionInLine = bytePositionInLine; _prevConsumed = consumed; _prevCurrentPosition = currentPosition; } public SequencePosition GetStartPosition(int offset = 0) { return new SequencePosition(_prevCurrentPosition.GetObject(), _prevCurrentPosition.GetInteger() + _prevConsumed + offset); } } private ReadOnlySpan<byte> _buffer; private readonly bool _isFinalBlock; private readonly bool _isInputSequence; private long _lineNumber; private long _bytePositionInLine; private int _consumed; private bool _inObject; private bool _isNotPrimitive; private JsonTokenType _tokenType; private JsonTokenType _previousTokenType; private JsonReaderOptions _readerOptions; private BitStack _bitStack; private long _totalConsumed; private bool _isLastSegment; private readonly bool _isMultiSegment; private bool _trailingCommaBeforeComment; private SequencePosition _nextPosition; private SequencePosition _currentPosition; private readonly ReadOnlySequence<byte> _sequence; private bool IsLastSpan { [System.Runtime.CompilerServices.IsReadOnly] get { if (_isFinalBlock) { if (_isMultiSegment) return _isLastSegment; return true; } return false; } } internal ReadOnlySequence<byte> OriginalSequence { [System.Runtime.CompilerServices.IsReadOnly] get { return _sequence; } } internal ReadOnlySpan<byte> OriginalSpan { [System.Runtime.CompilerServices.IsReadOnly] get { if (!_sequence.IsEmpty) return default(ReadOnlySpan<byte>); return _buffer; } } internal int ValueLength { [System.Runtime.CompilerServices.IsReadOnly] get { if (!HasValueSequence) return ValueSpan.Length; return checked((int)ValueSequence.Length); } } internal bool AllowMultipleValues { [System.Runtime.CompilerServices.IsReadOnly] get { return _readerOptions.AllowMultipleValues; } } public ReadOnlySpan<byte> ValueSpan { [System.Runtime.CompilerServices.IsReadOnly] get; private set; } public long BytesConsumed { [System.Runtime.CompilerServices.IsReadOnly] get { return _totalConsumed + _consumed; } } public long TokenStartIndex { [System.Runtime.CompilerServices.IsReadOnly] get; private set; } public int CurrentDepth { [System.Runtime.CompilerServices.IsReadOnly] get { BitStack bitStack = _bitStack; int num = bitStack.CurrentDepth; JsonTokenType tokenType = TokenType; if ((tokenType == JsonTokenType.StartObject || tokenType == JsonTokenType.StartArray) ? true : false) num--; return num; } } internal bool IsInArray { [System.Runtime.CompilerServices.IsReadOnly] get { return !_inObject; } } public JsonTokenType TokenType { [System.Runtime.CompilerServices.IsReadOnly] get { return _tokenType; } } public bool HasValueSequence { [System.Runtime.CompilerServices.IsReadOnly] get; private set; } public bool ValueIsEscaped { [System.Runtime.CompilerServices.IsReadOnly] get; private set; } public bool IsFinalBlock { [System.Runtime.CompilerServices.IsReadOnly] get { return _isFinalBlock; } } public ReadOnlySequence<byte> ValueSequence { [System.Runtime.CompilerServices.IsReadOnly] get; private set; } public SequencePosition Position { [System.Runtime.CompilerServices.IsReadOnly] get { if (_isInputSequence) return _sequence.GetPosition(_consumed, _currentPosition); return default(SequencePosition); } } public JsonReaderState CurrentState { [System.Runtime.CompilerServices.IsReadOnly] get { return new JsonReaderState(_lineNumber, _bytePositionInLine, _inObject, _isNotPrimitive, ValueIsEscaped, _trailingCommaBeforeComment, _tokenType, _previousTokenType, _readerOptions, _bitStack); } } [System.Runtime.CompilerServices.Nullable(1)] [DebuggerBrowsable(DebuggerBrowsableState.Never)] private string DebuggerDisplay { get { return $"""{DebugTokenType}""{TokenStartIndex}""{BytesConsumed}"; } } [System.Runtime.CompilerServices.Nullable(1)] private string DebugTokenType { get { switch (TokenType) { case JsonTokenType.Comment: return "Comment"; case JsonTokenType.EndArray: return "EndArray"; case JsonTokenType.EndObject: return "EndObject"; case JsonTokenType.False: return "False"; case JsonTokenType.None: return "None"; case JsonTokenType.Null: return "Null"; case JsonTokenType.Number: return "Number"; case JsonTokenType.PropertyName: return "PropertyName"; case JsonTokenType.StartArray: return "StartArray"; case JsonTokenType.StartObject: return "StartObject"; case JsonTokenType.String: return "String"; case JsonTokenType.True: return "True"; default: return ((byte)TokenType).ToString(); } } } public Utf8JsonReader(ReadOnlySpan<byte> jsonData, bool isFinalBlock, JsonReaderState state) { _buffer = jsonData; _isFinalBlock = isFinalBlock; _isInputSequence = false; _lineNumber = state._lineNumber; _bytePositionInLine = state._bytePositionInLine; _inObject = state._inObject; _isNotPrimitive = state._isNotPrimitive; ValueIsEscaped = state._valueIsEscaped; _trailingCommaBeforeComment = state._trailingCommaBeforeComment; _tokenType = state._tokenType; _previousTokenType = state._previousTokenType; _readerOptions = state._readerOptions; if (_readerOptions.MaxDepth == 0) _readerOptions.MaxDepth = 64; _bitStack = state._bitStack; _consumed = 0; TokenStartIndex = 0; _totalConsumed = 0; _isLastSegment = _isFinalBlock; _isMultiSegment = false; ValueSpan = ReadOnlySpan<byte>.Empty; _currentPosition = default(SequencePosition); _nextPosition = default(SequencePosition); _sequence = default(ReadOnlySequence<byte>); HasValueSequence = false; ValueSequence = ReadOnlySequence<byte>.Empty; } public Utf8JsonReader(ReadOnlySpan<byte> jsonData, JsonReaderOptions options = default(JsonReaderOptions)) { this = new Utf8JsonReader(jsonData, true, new JsonReaderState(options)); } public bool Read() { bool num = _isMultiSegment ? ReadMultiSegment() : ReadSingleSegment(); if (!num && _isFinalBlock && TokenType == JsonTokenType.None && !_readerOptions.AllowMultipleValues) ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.ExpectedJsonTokens, 0, default(ReadOnlySpan<byte>)); return num; } public void Skip() { if (!_isFinalBlock) ThrowHelper.ThrowInvalidOperationException_CannotSkipOnPartial(); SkipHelper(); } [MethodImpl(MethodImplOptions.AggressiveInlining)] private void SkipHelper() { if (TokenType == JsonTokenType.PropertyName) Read(); JsonTokenType tokenType = TokenType; if ((tokenType == JsonTokenType.StartObject || tokenType == JsonTokenType.StartArray) ? true : false) { int currentDepth = CurrentDepth; do { Read(); } while (currentDepth < CurrentDepth); } } public bool TrySkip() { if (_isFinalBlock) { SkipHelper(); return true; } Utf8JsonReader utf8JsonReader = this; bool num = TrySkipPartial(CurrentDepth); if (!num) this = utf8JsonReader; return num; } internal bool TrySkipPartial(int targetDepth) { if (targetDepth == CurrentDepth) { if (TokenType == JsonTokenType.PropertyName && !Read()) return false; JsonTokenType tokenType = TokenType; if ((tokenType != JsonTokenType.StartObject && tokenType != JsonTokenType.StartArray) || 1 == 0) return true; } do { if (!Read()) return false; } while (targetDepth < CurrentDepth); return true; } [System.Runtime.CompilerServices.IsReadOnly] public bool ValueTextEquals(ReadOnlySpan<byte> utf8Text) { if (!IsTokenTypeString(TokenType)) ThrowHelper.ThrowInvalidOperationException_ExpectedStringComparison(TokenType); return TextEqualsHelper(utf8Text); } [System.Runtime.CompilerServices.IsReadOnly] [System.Runtime.CompilerServices.NullableContext(2)] public bool ValueTextEquals(string text) { return ValueTextEquals(text.AsSpan()); } [MethodImpl(MethodImplOptions.AggressiveInlining)] [System.Runtime.CompilerServices.IsReadOnly] private bool TextEqualsHelper(ReadOnlySpan<byte> otherUtf8Text) { if (HasValueSequence) return CompareToSequence(otherUtf8Text); if (ValueIsEscaped) return UnescapeAndCompare(otherUtf8Text); return otherUtf8Text.SequenceEqual(ValueSpan); } [System.Runtime.CompilerServices.IsReadOnly] public unsafe bool ValueTextEquals(ReadOnlySpan<char> text) { if (!IsTokenTypeString(TokenType)) ThrowHelper.ThrowInvalidOperationException_ExpectedStringComparison(TokenType); if (MatchNotPossible(text.Length)) return false; byte[] array = null; int num = checked(text.Length * 3); Span<byte> destination; if (num > 256) { array = ArrayPool<byte>.Shared.Rent(num); destination = array; } else destination = new Span<byte>(stackalloc byte[256], 256); int written; bool result = JsonWriterHelper.ToUtf8(text, destination, out written) != OperationStatus.InvalidData && TextEqualsHelper(destination.Slice(0, written)); if (array != null) { destination.Slice(0, written).Clear(); ArrayPool<byte>.Shared.Return(array, false); } return result; } [System.Runtime.CompilerServices.IsReadOnly] private bool CompareToSequence(ReadOnlySpan<byte> other) { if (ValueIsEscaped) return UnescapeSequenceAndCompare(other); ReadOnlySequence<byte> valueSequence = ValueSequence; if (valueSequence.Length != other.Length) return false; int num = 0; ReadOnlySequence<byte>.Enumerator enumerator = valueSequence.GetEnumerator(); while (enumerator.MoveNext()) { ReadOnlySpan<byte> span = enumerator.Current.Span; if (!other.Slice(num).StartsWith(span)) return false; num += span.Length; } return true; } [System.Runtime.CompilerServices.IsReadOnly] private bool UnescapeAndCompare(ReadOnlySpan<byte> other) { ReadOnlySpan<byte> valueSpan = ValueSpan; if (valueSpan.Length < other.Length || valueSpan.Length / 6 > other.Length) return false; int num = valueSpan.IndexOf<byte>(92); if (!other.StartsWith(valueSpan.Slice(0, num))) return false; return JsonReaderHelper.UnescapeAndCompare(valueSpan.Slice(num), other.Slice(num)); } [System.Runtime.CompilerServices.IsReadOnly] private bool UnescapeSequenceAndCompare(ReadOnlySpan<byte> other) { ReadOnlySequence<byte> utf8Source = ValueSequence; long length = utf8Source.Length; if (length < other.Length || length / 6 > other.Length) return false; int num = 0; bool result = false; ReadOnlySequence<byte>.Enumerator enumerator = utf8Source.GetEnumerator(); while (enumerator.MoveNext()) { ReadOnlySpan<byte> span = enumerator.Current.Span; int num2 = span.IndexOf<byte>(92); if (num2 != -1) { if (other.Slice(num).StartsWith(span.Slice(0, num2))) { num += num2; other = other.Slice(num); utf8Source = utf8Source.Slice(num); result = ((!utf8Source.IsSingleSegment) ? JsonReaderHelper.UnescapeAndCompare(utf8Source, other) : JsonReaderHelper.UnescapeAndCompare(utf8Source.First.Span, other)); } break; } if (!other.Slice(num).StartsWith(span)) break; num += span.Length; } return result; } private static bool IsTokenTypeString(JsonTokenType tokenType) { if (tokenType != JsonTokenType.PropertyName) return tokenType == JsonTokenType.String; return true; } [MethodImpl(MethodImplOptions.AggressiveInlining)] [System.Runtime.CompilerServices.IsReadOnly] private bool MatchNotPossible(int charTextLength) { if (HasValueSequence) return MatchNotPossibleSequence(charTextLength); int length = ValueSpan.Length; if (length < charTextLength || length / (ValueIsEscaped ? 6 : 3) > charTextLength) return true; return false; } [MethodImpl(MethodImplOptions.NoInlining)] [System.Runtime.CompilerServices.IsReadOnly] private bool MatchNotPossibleSequence(int charTextLength) { long length = ValueSequence.Length; if (length < charTextLength || length / (ValueIsEscaped ? 6 : 3) > charTextLength) return true; return false; } private void StartObject() { if (_bitStack.CurrentDepth >= _readerOptions.MaxDepth) ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.ObjectDepthTooLarge, 0, default(ReadOnlySpan<byte>)); _bitStack.PushTrue(); ValueSpan = _buffer.Slice(_consumed, 1); _consumed++; _bytePositionInLine++; _tokenType = JsonTokenType.StartObject; _inObject = true; } private void EndObject() { if (!_inObject || _bitStack.CurrentDepth <= 0) ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.MismatchedObjectArray, 125, default(ReadOnlySpan<byte>)); if (_trailingCommaBeforeComment) { if (!_readerOptions.AllowTrailingCommas) ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.TrailingCommaNotAllowedBeforeObjectEnd, 0, default(ReadOnlySpan<byte>)); _trailingCommaBeforeComment = false; } _tokenType = JsonTokenType.EndObject; ValueSpan = _buffer.Slice(_consumed, 1); UpdateBitStackOnEndToken(); } private void StartArray() { if (_bitStack.CurrentDepth >= _readerOptions.MaxDepth) ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.ArrayDepthTooLarge, 0, default(ReadOnlySpan<byte>)); _bitStack.PushFalse(); ValueSpan = _buffer.Slice(_consumed, 1); _consumed++; _bytePositionInLine++; _tokenType = JsonTokenType.StartArray; _inObject = false; } private void EndArray() { if (_inObject || _bitStack.CurrentDepth <= 0) ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.MismatchedObjectArray, 93, default(ReadOnlySpan<byte>)); if (_trailingCommaBeforeComment) { if (!_readerOptions.AllowTrailingCommas) ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.TrailingCommaNotAllowedBeforeArrayEnd, 0, default(ReadOnlySpan<byte>)); _trailingCommaBeforeComment = false; } _tokenType = JsonTokenType.EndArray; ValueSpan = _buffer.Slice(_consumed, 1); UpdateBitStackOnEndToken(); } [MethodImpl(MethodImplOptions.AggressiveInlining)] private void UpdateBitStackOnEndToken() { _consumed++; _bytePositionInLine++; _inObject = _bitStack.Pop(); } private bool ReadSingleSegment() { bool flag = false; ValueSpan = default(ReadOnlySpan<byte>); ValueIsEscaped = false; if (HasMoreData()) { byte b = _buffer[_consumed]; if (b <= 32) { SkipWhiteSpace(); if (!HasMoreData()) goto IL_0139; b = _buffer[_consumed]; } TokenStartIndex = _consumed; if (_tokenType != 0) { if (b == 47) flag = ConsumeNextTokenOrRollback(b); else { if (_tokenType == JsonTokenType.StartObject) { switch (b) { case 125: break; default: ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.ExpectedStartOfPropertyNotFound, b, default(ReadOnlySpan<byte>)); goto case 34; case 34: { int consumed = _consumed; long bytePositionInLine = _bytePositionInLine; long lineNumber = _lineNumber; flag = ConsumePropertyName(); if (!flag) { _consumed = consumed; _tokenType = JsonTokenType.StartObject; _bytePositionInLine = bytePositionInLine; _lineNumber = lineNumber; } goto IL_0139; } } EndObject(); goto IL_0137; } if (_tokenType != JsonTokenType.StartArray) flag = ((_tokenType != JsonTokenType.PropertyName) ? ConsumeNextTokenOrRollback(b) : ConsumeValue(b)); else { if (b == 93) { EndArray(); goto IL_0137; } flag = ConsumeValue(b); } } } else flag = ReadFirstToken(b); } goto IL_0139; IL_0137: flag = true; goto IL_0139; IL_0139: return flag; } [MethodImpl(MethodImplOptions.AggressiveInlining)] private bool HasMoreData() { if (_consumed >= (uint)_buffer.Length) { if (_isNotPrimitive && IsLastSpan) { if (_bitStack.CurrentDepth != 0) ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.ZeroDepthAtEnd, 0, default(ReadOnlySpan<byte>)); if (_readerOptions.CommentHandling == JsonCommentHandling.Allow && _tokenType == JsonTokenType.Comment) return false; JsonTokenType tokenType = _tokenType; if (tokenType != JsonTokenType.EndArray && tokenType != JsonTokenType.EndObject) ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.InvalidEndOfJsonNonPrimitive, 0, default(ReadOnlySpan<byte>)); } return false; } return true; } [MethodImpl(MethodImplOptions.AggressiveInlining)] private bool HasMoreData(ExceptionResource resource) { if (_consumed >= (uint)_buffer.Length) { if (IsLastSpan) ThrowHelper.ThrowJsonReaderException(ref this, resource, 0, default(ReadOnlySpan<byte>)); return false; } return true; } private bool ReadFirstToken(byte first) { switch (first) { case 123: _bitStack.SetFirstBit(); _tokenType = JsonTokenType.StartObject; ValueSpan = _buffer.Slice(_consumed, 1); _consumed++; _bytePositionInLine++; _inObject = true; _isNotPrimitive = true; break; case 91: _bitStack.ResetFirstBit(); _tokenType = JsonTokenType.StartArray; ValueSpan = _buffer.Slice(_consumed, 1); _consumed++; _bytePositionInLine++; _isNotPrimitive = true; break; default: { ReadOnlySpan<byte> buffer = _buffer; if (JsonHelpers.IsDigit(first) || first == 45) { if (!TryGetNumber(buffer.Slice(_consumed), out int consumed)) return false; _tokenType = JsonTokenType.Number; _consumed += consumed; _bytePositionInLine += consumed; } else if (!ConsumeValue(first)) { return false; } JsonTokenType tokenType = _tokenType; bool flag = _isNotPrimitive = ((tokenType == JsonTokenType.StartObject || tokenType == JsonTokenType.StartArray) ? true : false); break; } } return true; } private void SkipWhiteSpace() { ReadOnlySpan<byte> buffer = _buffer; while (_consumed < buffer.Length) { byte b = buffer[_consumed]; if (b != 32 && b != 13 && b != 10 && b != 9) break; if (b == 10) { _lineNumber++; _bytePositionInLine = 0; } else _bytePositionInLine++; _consumed++; } } private bool ConsumeValue(byte marker) { while (true) { _trailingCommaBeforeComment = false; switch (marker) { case 34: return ConsumeString(); case 123: StartObject(); goto IL_0166; case 91: StartArray(); goto IL_0166; default: { if (!JsonHelpers.IsDigit(marker)) { switch (marker) { case 45: break; case 102: return ConsumeLiteral(JsonConstants.FalseValue, JsonTokenType.False); case 116: return ConsumeLiteral(JsonConstants.TrueValue, JsonTokenType.True); case 110: return ConsumeLiteral(JsonConstants.NullValue, JsonTokenType.Null); default: goto IL_0080; } } return ConsumeNumber(); } IL_0166: return true; IL_0080: switch (_readerOptions.CommentHandling) { case JsonCommentHandling.Allow: if (marker == 47) return ConsumeComment(); goto IL_0154; case JsonCommentHandling.Disallow: goto IL_0154; } if (marker == 47) break; goto IL_0154; IL_0154: ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.ExpectedStartOfValueNotFound, marker, default(ReadOnlySpan<byte>)); goto IL_0166; } if (!SkipComment()) break; if (_consumed >= (uint)_buffer.Length) { if (_isNotPrimitive && IsLastSpan && _tokenType != JsonTokenType.EndArray && _tokenType != JsonTokenType.EndObject) ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.InvalidEndOfJsonNonPrimitive, 0, default(ReadOnlySpan<byte>)); return false; } marker = _buffer[_consumed]; if (marker <= 32) { SkipWhiteSpace(); if (!HasMoreData()) return false; marker = _buffer[_consumed]; } TokenStartIndex = _consumed; } return false; } private bool ConsumeLiteral(ReadOnlySpan<byte> literal, JsonTokenType tokenType) { ReadOnlySpan<byte> span = _buffer.Slice(_consumed); if (!span.StartsWith(literal)) return CheckLiteral(span, literal); ValueSpan = span.Slice(0, literal.Length); _tokenType = tokenType; _consumed += literal.Length; _bytePositionInLine += literal.Length; return true; } private bool CheckLiteral(ReadOnlySpan<byte> span, ReadOnlySpan<byte> literal) { int num = 0; for (int i = 1; i < literal.Length; i++) { if (span.Length <= i) { num = i; break; } if (span[i] != literal[i]) { _bytePositionInLine += i; ThrowInvalidLiteral(span); } } if (IsLastSpan) { _bytePositionInLine += num; ThrowInvalidLiteral(span); } return false; } private void ThrowInvalidLiteral(ReadOnlySpan<byte> span) { ExceptionResource resource; switch (span[0]) { case 116: resource = ExceptionResource.ExpectedTrue; break; case 102: resource = ExceptionResource.ExpectedFalse; break; default: resource = ExceptionResource.ExpectedNull; break; } ThrowHelper.ThrowJsonReaderException(ref this, resource, 0, span); } private bool ConsumeNumber() { if (!TryGetNumber(_buffer.Slice(_consumed), out int consumed)) return false; _tokenType = JsonTokenType.Number; _consumed += consumed; _bytePositionInLine += consumed; if (_consumed >= (uint)_buffer.Length && _isNotPrimitive) ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.ExpectedEndOfDigitNotFound, _buffer[_consumed - 1], default(ReadOnlySpan<byte>)); return true; } private bool ConsumePropertyName() { _trailingCommaBeforeComment = false; if (!ConsumeString()) return false; if (!HasMoreData(ExceptionResource.ExpectedValueAfterPropertyNameNotFound)) return false; byte b = _buffer[_consumed]; if (b <= 32) { SkipWhiteSpace(); if (!HasMoreData(ExceptionResource.ExpectedValueAfterPropertyNameNotFound)) return false; b = _buffer[_consumed]; } if (b != 58) ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.ExpectedSeparatorAfterPropertyNameNotFound, b, default(ReadOnlySpan<byte>)); _consumed++; _bytePositionInLine++; _tokenType = JsonTokenType.PropertyName; return true; } private bool ConsumeString() { ReadOnlySpan<byte> readOnlySpan = _buffer.Slice(_consumed + 1); int num = readOnlySpan.IndexOfQuoteOrAnyControlOrBackSlash(); if (num >= 0) { if (readOnlySpan[num] == 34) { _bytePositionInLine += num + 2; ValueSpan = readOnlySpan.Slice(0, num); ValueIsEscaped = false; _tokenType = JsonTokenType.String; _consumed += num + 2; return true; } return ConsumeStringAndValidate(readOnlySpan, num); } if (IsLastSpan) { _bytePositionInLine += readOnlySpan.Length + 1; ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.EndOfStringNotFound, 0, default(ReadOnlySpan<byte>)); } return false; } private bool ConsumeStringAndValidate(ReadOnlySpan<byte> data, int idx) { long bytePositionInLine = _bytePositionInLine; long lineNumber = _lineNumber; _bytePositionInLine += idx + 1; bool flag = false; while (true) { byte b; if (idx < data.Length) { b = data[idx]; switch (b) { case 34: break; case 92: goto IL_0044; default: goto IL_004b; } if (!flag) break; flag = false; goto IL_00bd; } goto IL_00de; IL_00de: if (idx < data.Length) break; if (IsLastSpan) ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.EndOfStringNotFound, 0, default(ReadOnlySpan<byte>)); _lineNumber = lineNumber; _bytePositionInLine = bytePositionInLine; return false; IL_004b: if (flag) { if (JsonConstants.EscapableChars.IndexOf(b) == -1) ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.InvalidCharacterAfterEscapeWithinString, b, default(ReadOnlySpan<byte>)); if (b == 117) { _bytePositionInLine++; if (!ValidateHexDigits(data, idx + 1)) { idx = data.Length; goto IL_00de; } idx += 4; } flag = false; } else if (b < 32) { ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.InvalidCharacterWithinString, b, default(ReadOnlySpan<byte>)); } goto IL_00bd; IL_0044: flag = !flag; goto IL_00bd; IL_00bd: _bytePositionInLine++; idx++; } _bytePositionInLine++; ValueSpan = data.Slice(0, idx); ValueIsEscaped = true; _tokenType = JsonTokenType.String; _consumed += idx + 2; return true; } private bool ValidateHexDigits(ReadOnlySpan<byte> data, int idx) { for (int i = idx; i < data.Length; i++) { byte nextByte = data[i]; if (!JsonReaderHelper.IsHexDigit(nextByte)) ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.InvalidHexCharacterWithinString, nextByte, default(ReadOnlySpan<byte>)); if (i - idx >= 3) return true; _bytePositionInLine++; } return false; } private bool TryGetNumber(ReadOnlySpan<byte> data, out int consumed) { consumed = 0; int i = 0; if (ConsumeNegativeSign(ref data, ref i) == ConsumeNumberResult.NeedMoreData) return false; byte b = data[i]; if (b == 48) { switch (ConsumeZero(ref data, ref i)) { case ConsumeNumberResult.NeedMoreData: return false; case ConsumeNumberResult.Success: goto IL_014b; } b = data[i]; } else { i++; switch (ConsumeIntegerDigits(ref data, ref i)) { case ConsumeNumberResult.NeedMoreData: return false; case ConsumeNumberResult.Success: goto IL_014b; } b = data[i]; if (b != 46 && b != 69 && b != 101) { _bytePositionInLine += i; ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.ExpectedEndOfDigitNotFound, b, default(ReadOnlySpan<byte>)); } } if (b == 46) { i++; switch (ConsumeDecimalDigits(ref data, ref i)) { case ConsumeNumberResult.NeedMoreData: return false; case ConsumeNumberResult.Success: goto IL_014b; } b = data[i]; if (b != 69 && b != 101) { _bytePositionInLine += i; ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.ExpectedNextDigitEValueNotFound, b, default(ReadOnlySpan<byte>)); } } i++; if (ConsumeSign(ref data, ref i) == ConsumeNumberResult.NeedMoreData) return false; i++; switch (ConsumeIntegerDigits(ref data, ref i)) { case ConsumeNumberResult.NeedMoreData: return false; default: _bytePositionInLine += i; ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.ExpectedEndOfDigitNotFound, data[i], default(ReadOnlySpan<byte>)); break; case ConsumeNumberResult.Success: break; } goto IL_014b; IL_014b: ValueSpan = data.Slice(0, i); consumed = i; return true; } private ConsumeNumberResult ConsumeNegativeSign(ref ReadOnlySpan<byte> data, [System.Runtime.CompilerServices.ScopedRef] ref int i) { byte b = data[i]; if (b == 45) { i++; if (i >= data.Length) { if (IsLastSpan) { _bytePositionInLine += i; ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.RequiredDigitNotFoundEndOfData, 0, default(ReadOnlySpan<byte>)); } return ConsumeNumberResult.NeedMoreData; } b = data[i]; if (!JsonHelpers.IsDigit(b)) { _bytePositionInLine += i; ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.RequiredDigitNotFoundAfterSign, b, default(ReadOnlySpan<byte>)); } } return ConsumeNumberResult.OperationIncomplete; } private ConsumeNumberResult ConsumeZero(ref ReadOnlySpan<byte> data, [System.Runtime.CompilerServices.ScopedRef] ref int i) { i++; if (i >= data.Length) { if (IsLastSpan) return ConsumeNumberResult.Success; return ConsumeNumberResult.NeedMoreData; } byte value = data[i]; if (JsonConstants.Delimiters.IndexOf(value) >= 0) return ConsumeNumberResult.Success; value = data[i]; if (value != 46 && value != 69 && value != 101) { _bytePositionInLine += i; ThrowHelper.ThrowJsonReaderException(ref this, JsonHelpers.IsInRangeInclusive(value, 48, 57) ? ExceptionResource.InvalidLeadingZeroInNumber : ExceptionResource.ExpectedEndOfDigitNotFound, value, default(ReadOnlySpan<byte>)); } return ConsumeNumberResult.OperationIncomplete; } private ConsumeNumberResult ConsumeIntegerDigits(ref ReadOnlySpan<byte> data, [System.Runtime.CompilerServices.ScopedRef] ref int i) { byte value = 0; while (i < data.Length) { value = data[i]; if (!JsonHelpers.IsDigit(value)) break; i++; } if (i >= data.Length) { if (IsLastSpan) return ConsumeNumberResult.Success; return ConsumeNumberResult.NeedMoreData; } if (JsonConstants.Delimiters.IndexOf(value) >= 0) return ConsumeNumberResult.Success; return ConsumeNumberResult.OperationIncomplete; } private ConsumeNumberResult ConsumeDecimalDigits(ref ReadOnlySpan<byte> data, [System.Runtime.CompilerServices.ScopedRef] ref int i) { if (i >= data.Length) { if (IsLastSpan) { _bytePositionInLine += i; ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.RequiredDigitNotFoundEndOfData, 0, default(ReadOnlySpan<byte>)); } return ConsumeNumberResult.NeedMoreData; } byte b = data[i]; if (!JsonHelpers.IsDigit(b)) { _bytePositionInLine += i; ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.RequiredDigitNotFoundAfterDecimal, b, default(ReadOnlySpan<byte>)); } i++; return ConsumeIntegerDigits(ref data, ref i); } private ConsumeNumberResult ConsumeSign(ref ReadOnlySpan<byte> data, [System.Runtime.CompilerServices.ScopedRef] ref int i) { if (i >= data.Length) { if (IsLastSpan) { _bytePositionInLine += i; ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.RequiredDigitNotFoundEndOfData, 0, default(ReadOnlySpan<byte>)); } return ConsumeNumberResult.NeedMoreData; } byte b = data[i]; if (b == 43 || b == 45) { i++; if (i >= data.Length) { if (IsLastSpan) { _bytePositionInLine += i; ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.RequiredDigitNotFoundEndOfData, 0, default(ReadOnlySpan<byte>)); } return ConsumeNumberResult.NeedMoreData; } b = data[i]; } if (!JsonHelpers.IsDigit(b)) { _bytePositionInLine += i; ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.RequiredDigitNotFoundAfterSign, b, default(ReadOnlySpan<byte>)); } return ConsumeNumberResult.OperationIncomplete; } private bool ConsumeNextTokenOrRollback(byte marker) { int consumed = _consumed; long bytePositionInLine = _bytePositionInLine; long lineNumber = _lineNumber; JsonTokenType tokenType = _tokenType; bool trailingCommaBeforeComment = _trailingCommaBeforeComment; switch (ConsumeNextToken(marker)) { case ConsumeTokenResult.Success: return true; case ConsumeTokenResult.NotEnoughDataRollBackState: _consumed = consumed; _tokenType = tokenType; _bytePositionInLine = bytePositionInLine; _lineNumber = lineNumber; _trailingCommaBeforeComment = trailingCommaBeforeComment; break; } return false; } private ConsumeTokenResult ConsumeNextToken(byte marker) { if (_readerOptions.CommentHandling != 0) { if (_readerOptions.CommentHandling != JsonCommentHandling.Allow) return ConsumeNextTokenUntilAfterAllCommentsAreSkipped(marker); if (marker == 47) { if (!ConsumeComment()) return ConsumeTokenResult.NotEnoughDataRollBackState; return ConsumeTokenResult.Success; } if (_tokenType == JsonTokenType.Comment) return ConsumeNextTokenFromLastNonCommentToken(); } if (_bitStack.CurrentDepth == 0) { if (_readerOptions.AllowMultipleValues) { if (!ReadFirstToken(marker)) return ConsumeTokenResult.NotEnoughDataRollBackState; return ConsumeTokenResult.Success; } ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.ExpectedEndAfterSingleJson, marker, default(ReadOnlySpan<byte>)); } switch (marker) { case 44: { _consumed++; _bytePositionInLine++; if (_consumed >= (uint)_buffer.Length) { if (IsLastSpan) { _consumed--; _bytePositionInLine--; ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.ExpectedStartOfPropertyOrValueNotFound, 0, default(ReadOnlySpan<byte>)); } return ConsumeTokenResult.NotEnoughDataRollBackState; } byte b = _buffer[_consumed]; if (b <= 32) { SkipWhiteSpace(); if (!HasMoreData(ExceptionResource.ExpectedStartOfPropertyOrValueNotFound)) return ConsumeTokenResult.NotEnoughDataRollBackState; b = _buffer[_consumed]; } TokenStartIndex = _consumed; if (_readerOptions.CommentHandling == JsonCommentHandling.Allow && b == 47) { _trailingCommaBeforeComment = true; if (!ConsumeComment()) return ConsumeTokenResult.NotEnoughDataRollBackState; return ConsumeTokenResult.Success; } if (_inObject) { switch (b) { case 125: if (_readerOptions.AllowTrailingCommas) { EndObject(); return ConsumeTokenResult.Success; } ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.TrailingCommaNotAllowedBeforeObjectEnd, 0, default(ReadOnlySpan<byte>)); goto default; default: ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.ExpectedStartOfPropertyNotFound, b, default(ReadOnlySpan<byte>)); break; case 34: break; } if (!ConsumePropertyName()) return ConsumeTokenResult.NotEnoughDataRollBackState; return ConsumeTokenResult.Success; } if (b == 93) { if (_readerOptions.AllowTrailingCommas) { EndArray(); return ConsumeTokenResult.Success; } ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.TrailingCommaNotAllowedBeforeArrayEnd, 0, default(ReadOnlySpan<byte>)); } if (!ConsumeValue(b)) return ConsumeTokenResult.NotEnoughDataRollBackState; return ConsumeTokenResult.Success; } case 125: EndObject(); break; case 93: EndArray(); break; default: ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.FoundInvalidCharacter, marker, default(ReadOnlySpan<byte>)); break; } return ConsumeTokenResult.Success; } private ConsumeTokenResult ConsumeNextTokenFromLastNonCommentToken() { if (JsonReaderHelper.IsTokenTypePrimitive(_previousTokenType)) _tokenType = (_inObject ? JsonTokenType.StartObject : JsonTokenType.StartArray); else _tokenType = _previousTokenType; if (HasMoreData()) { byte b = _buffer[_consumed]; if (b <= 32) { SkipWhiteSpace(); if (!HasMoreData()) goto IL_035d; b = _buffer[_consumed]; } if (_bitStack.CurrentDepth == 0 && _tokenType != 0) { if (_readerOptions.AllowMultipleValues) { if (!ReadFirstToken(b)) return ConsumeTokenResult.NotEnoughDataRollBackState; return ConsumeTokenResult.Success; } ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.ExpectedEndAfterSingleJson, b, default(ReadOnlySpan<byte>)); } TokenStartIndex = _consumed; switch (b) { case 44: if ((int)_previousTokenType <= 1 || _previousTokenType == JsonTokenType.StartArray || _trailingCommaBeforeComment) ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.ExpectedStartOfPropertyOrValueAfterComment, b, default(ReadOnlySpan<byte>)); _consumed++; _bytePositionInLine++; if (_consumed >= (uint)_buffer.Length) { if (IsLastSpan) { _consumed--; _bytePositionInLine--; ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.ExpectedStartOfPropertyOrValueNotFound, 0, default(ReadOnlySpan<byte>)); } break; } b = _buffer[_consumed]; if (b <= 32) { SkipWhiteSpace(); if (!HasMoreData(ExceptionResource.ExpectedStartOfPropertyOrValueNotFound)) break; b = _buffer[_consumed]; } TokenStartIndex = _consumed; if (b == 47) { _trailingCommaBeforeComment = true; if (!ConsumeComment()) break; } else if (_inObject) { switch (b) { case 125: if (_readerOptions.AllowTrailingCommas) goto IL_01ec; ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.TrailingCommaNotAllowedBeforeObjectEnd, 0, default(ReadOnlySpan<byte>)); goto default; default: ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.ExpectedStartOfPropertyNotFound, b, default(ReadOnlySpan<byte>)); break; case 34: break; } if (!ConsumePropertyName()) break; } else { if (b == 93) { if (_readerOptions.AllowTrailingCommas) { EndArray(); goto IL_035b; } ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.TrailingCommaNotAllowedBeforeArrayEnd, 0, default(ReadOnlySpan<byte>)); } if (!ConsumeValue(b)) break; } goto IL_035b; case 125: EndObject(); goto IL_035b; case 93: EndArray(); goto IL_035b; default: { if (_tokenType == JsonTokenType.None) { if (!ReadFirstToken(b)) break; } else if (_tokenType == JsonTokenType.StartObject) { if (b != 34) ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.ExpectedStartOfPropertyNotFound, b, default(ReadOnlySpan<byte>)); int consumed = _consumed; long bytePositionInLine = _bytePositionInLine; long lineNumber = _lineNumber; if (!ConsumePropertyName()) { _consumed = consumed; _tokenType = JsonTokenType.StartObject; _bytePositionInLine = bytePositionInLine; _lineNumber = lineNumber; break; } } else if (_tokenType == JsonTokenType.StartArray) { if (!ConsumeValue(b)) break; } else if (_tokenType == JsonTokenType.PropertyName) { if (!ConsumeValue(b)) break; } else if (_inObject) { if (b != 34) ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.ExpectedStartOfPropertyNotFound, b, default(ReadOnlySpan<byte>)); if (!ConsumePropertyName()) break; } else if (!ConsumeValue(b)) { break; } goto IL_035b; } IL_035b: return ConsumeTokenResult.Success; IL_01ec: EndObject(); goto IL_035b; } } goto IL_035d; IL_035d: return ConsumeTokenResult.NotEnoughDataRollBackState; } private bool SkipAllComments([System.Runtime.CompilerServices.ScopedRef] ref byte marker) { while (true) { if (marker != 47) return true; if (!SkipComment() || !HasMoreData()) break; marker = _buffer[_consumed]; if (marker <= 32) { SkipWhiteSpace(); if (!HasMoreData()) break; marker = _buffer[_consumed]; } } return false; } private bool SkipAllComments([System.Runtime.CompilerServices.ScopedRef] ref byte marker, ExceptionResource resource) { while (true) { if (marker != 47) return true; if (!SkipComment() || !HasMoreData(resource)) break; marker = _buffer[_consumed]; if (marker <= 32) { SkipWhiteSpace(); if (!HasMoreData(resource)) break; marker = _buffer[_consumed]; } } return false; } private ConsumeTokenResult ConsumeNextTokenUntilAfterAllCommentsAreSkipped(byte marker) { if (SkipAllComments(ref marker)) { TokenStartIndex = _consumed; if (_tokenType == JsonTokenType.StartObject) { switch (marker) { case 125: break; default: ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.ExpectedStartOfPropertyNotFound, marker, default(ReadOnlySpan<byte>)); goto IL_004a; case 34: goto IL_004a; } EndObject(); } else if (_tokenType == JsonTokenType.StartArray) { if (marker == 93) EndArray(); else if (!ConsumeValue(marker)) { goto IL_029b; } } else if (_tokenType == JsonTokenType.PropertyName) { if (!ConsumeValue(marker)) goto IL_029b; } else if (_bitStack.CurrentDepth != 0) { switch (marker) { case 44: _consumed++; _bytePositionInLine++; if (_consumed >= (uint)_buffer.Length) { if (IsLastSpan) { _consumed--; _bytePositionInLine--; ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.ExpectedStartOfPropertyOrValueNotFound, 0, default(ReadOnlySpan<byte>)); } return ConsumeTokenResult.NotEnoughDataRollBackState; } marker = _buffer[_consumed]; if (marker <= 32) { SkipWhiteSpace(); if (!HasMoreData(ExceptionResource.ExpectedStartOfPropertyOrValueNotFound)) return ConsumeTokenResult.NotEnoughDataRollBackState; marker = _buffer[_consumed]; } if (!SkipAllComments(ref marker, ExceptionResource.ExpectedStartOfPropertyOrValueNotFound)) return ConsumeTokenResult.NotEnoughDataRollBackState; TokenStartIndex = _consumed; if (!_inObject) { if (marker == 93) { if (_readerOptions.AllowTrailingCommas) { EndArray(); break; } ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.TrailingCommaNotAllowedBeforeArrayEnd, 0, default(ReadOnlySpan<byte>)); } if (!ConsumeValue(marker)) return ConsumeTokenResult.NotEnoughDataRollBackState; return ConsumeTokenResult.Success; } switch (marker) { case 125: if (_readerOptions.AllowTrailingCommas) break; ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.TrailingCommaNotAllowedBeforeObjectEnd, 0, default(ReadOnlySpan<byte>)); goto default; default: ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.ExpectedStartOfPropertyNotFound, marker, default(ReadOnlySpan<byte>)); goto case 34; case 34: if (!ConsumePropertyName()) return ConsumeTokenResult.NotEnoughDataRollBackState; return ConsumeTokenResult.Success; } EndObject(); break; case 125: EndObject(); break; case 93: EndArray(); break; default: ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.FoundInvalidCharacter, marker, default(ReadOnlySpan<byte>)); break; } } else { if (_readerOptions.AllowMultipleValues) { if (!ReadFirstToken(marker)) return ConsumeTokenResult.NotEnoughDataRollBackState; return ConsumeTokenResult.Success; } ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.ExpectedEndAfterSingleJson, marker, default(ReadOnlySpan<byte>)); } goto IL_0299; } goto IL_029b; IL_029b: return ConsumeTokenResult.IncompleteNoRollBackNecessary; IL_004a: int consumed = _consumed; long bytePositionInLine = _bytePositionInLine; long lineNumber = _lineNumber; if (ConsumePropertyName()) goto IL_0299; _consumed = consumed; _tokenType = JsonTokenType.StartObject; _bytePositionInLine = bytePositionInLine; _lineNumber = lineNumber; goto IL_029b; IL_0299: return ConsumeTokenResult.Success; } private bool SkipComment() { ReadOnlySpan<byte> readOnlySpan = _buffer.Slice(_consumed + 1); if (readOnlySpan.Length > 0) { int idx; switch (readOnlySpan[0]) { case 47: return SkipSingleLineComment(readOnlySpan.Slice(1), out idx); case 42: return SkipMultiLineComment(readOnlySpan.Slice(1), out idx); } ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.ExpectedStartOfValueNotFound, 47, default(ReadOnlySpan<byte>)); } if (IsLastSpan) ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.ExpectedStartOfValueNotFound, 47, default(ReadOnlySpan<byte>)); return false; } private bool SkipSingleLineComment(ReadOnlySpan<byte> localBuffer, out int idx) { idx = FindLineSeparator(localBuffer); int num; if (idx != -1) { num = idx; if (localBuffer[idx] != 10) { if (idx < localBuffer.Length - 1) { if (localBuffer[idx + 1] == 10) num++; } else if (!IsLastSpan) { return false; } } num++; _bytePositionInLine = 0; _lineNumber++; } else { if (!IsLastSpan) return false; idx = localBuffer.Length; num = idx; _bytePositionInLine += 2 + localBuffer.Length; } _consumed += 2 + num; return true; } private int FindLineSeparator(ReadOnlySpan<byte> localBuffer) { int num = 0; while (true) { int num2 = localBuffer.IndexOfAny<byte>(10, 13, 226); if (num2 == -1) return -1; num += num2; if (localBuffer[num2] != 226) break; num++; localBuffer = localBuffer.Slice(num2 + 1); ThrowOnDangerousLineSeparator(localBuffer); } return num; } private void ThrowOnDangerousLineSeparator(ReadOnlySpan<byte> localBuffer) { if (localBuffer.Length >= 2) { byte b = localBuffer[1]; if (localBuffer[0] == 128 && (b == 168 || b == 169)) ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.UnexpectedEndOfLineSeparator, 0, default(ReadOnlySpan<byte>)); } } private bool SkipMultiLineComment(ReadOnlySpan<byte> localBuffer, out int idx) { idx = 0; while (true) { int num = localBuffer.Slice(idx).IndexOf<byte>(47); switch (num) { case -1: if (IsLastSpan) ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.EndOfCommentNotFound, 0, default(ReadOnlySpan<byte>)); return false; default: if (localBuffer[num + idx - 1] == 42) { idx += num - 1; _consumed += 4 + idx; (int, int) valueTuple = JsonReaderHelper.CountNewLines(localBuffer.Slice(0, idx)); int item = valueTuple.Item1; int item2 = valueTuple.Item2; _lineNumber += item; if (item2 != -1) _bytePositionInLine = idx - item2 + 1; else _bytePositionInLine += 4 + idx; return true; } break; case 0: break; } idx += num + 1; } } private bool ConsumeComment() { ReadOnlySpan<byte> readOnlySpan = _buffer.Slice(_consumed + 1); if (readOnlySpan.Length > 0) { byte b = readOnlySpan[0]; switch (b) { case 47: return ConsumeSingleLineComment(readOnlySpan.Slice(1), _consumed); case 42: return ConsumeMultiLineComment(readOnlySpan.Slice(1), _consumed); } ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.InvalidCharacterAtStartOfComment, b, default(ReadOnlySpan<byte>)); } if (IsLastSpan) ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.UnexpectedEndOfDataWhileReadingComment, 0, default(ReadOnlySpan<byte>)); return false; } private bool ConsumeSingleLineComment(ReadOnlySpan<byte> localBuffer, int previousConsumed) { if (!SkipSingleLineComment(localBuffer, out int idx)) return false; ValueSpan = _buffer.Slice(previousConsumed + 2, idx); if (_tokenType != JsonTokenType.Comment) _previousTokenType = _tokenType; _tokenType = JsonTokenType.Comment; return true; } private bool ConsumeMultiLineComment(ReadOnlySpan<byte> localBuffer, int previousConsumed) { if (!SkipMultiLineComment(localBuffer, out int idx)) return false; ValueSpan = _buffer.Slice(previousConsumed + 2, idx); if (_tokenType != JsonTokenType.Comment) _previousTokenType = _tokenType; _tokenType = JsonTokenType.Comment; return true; } private ReadOnlySpan<byte> GetUnescapedSpan() { ReadOnlySpan<byte> readOnlySpan; if (!HasValueSequence) readOnlySpan = ValueSpan; else { ReadOnlySequence<byte> sequence = ValueSequence; readOnlySpan = ref sequence.ToArray(); } ReadOnlySpan<byte> readOnlySpan2 = readOnlySpan; if (ValueIsEscaped) readOnlySpan2 = JsonReaderHelper.GetUnescapedSpan(readOnlySpan2); return readOnlySpan2; } public Utf8JsonReader(ReadOnlySequence<byte> jsonData, bool isFinalBlock, JsonReaderState state) { ReadOnlyMemory<byte> memory = jsonData.First; _buffer = memory.Span; _isFinalBlock = isFinalBlock; _isInputSequence = true; _lineNumber = state._lineNumber; _bytePositionInLine = state._bytePositionInLine; _inObject = state._inObject; _isNotPrimitive = state._isNotPrimitive; ValueIsEscaped = state._valueIsEscaped; _trailingCommaBeforeComment = state._trailingCommaBeforeComment; _tokenType = state._tokenType; _previousTokenType = state._previousTokenType; _readerOptions = state._readerOptions; if (_readerOptions.MaxDepth == 0) _readerOptions.MaxDepth = 64; _bitStack = state._bitStack; _consumed = 0; TokenStartIndex = 0; _totalConsumed = 0; ValueSpan = ReadOnlySpan<byte>.Empty; _sequence = jsonData; HasValueSequence = false; ValueSequence = ReadOnlySequence<byte>.Empty; if (jsonData.IsSingleSegment) { _nextPosition = default(SequencePosition); _currentPosition = jsonData.Start; _isLastSegment = isFinalBlock; _isMultiSegment = false; } else { _currentPosition = jsonData.Start; _nextPosition = _currentPosition; bool flag = _buffer.Length == 0; if (flag) { SequencePosition nextPosition = _nextPosition; ReadOnlyMemory<byte> memory2; while (jsonData.TryGet(ref _nextPosition, out memory2, true)) { _currentPosition = nextPosition; if (memory2.Length != 0) { _buffer = memory2.Span; break; } nextPosition = _nextPosition; } } _isLastSegment = (!jsonData.TryGet(ref _nextPosition, out memory, !flag) & isFinalBlock); _isMultiSegment = true; } } public Utf8JsonReader(ReadOnlySequence<byte> jsonData, JsonReaderOptions options = default(JsonReaderOptions)) { this = new Utf8JsonReader(jsonData, true, new JsonReaderState(options)); } private bool ReadMultiSegment() { bool flag = false; HasValueSequence = false; ValueIsEscaped = false; ValueSpan = default(ReadOnlySpan<byte>); ValueSequence = default(ReadOnlySequence<byte>); if (HasMoreDataMultiSegment()) { byte b = _buffer[_consumed]; if (b <= 32) { SkipWhiteSpaceMultiSegment(); if (!HasMoreDataMultiSegment()) goto IL_0173; b = _buffer[_consumed]; } TokenStartIndex = BytesConsumed; if (_tokenType != 0) { if (b == 47) flag = ConsumeNextTokenOrRollbackMultiSegment(b); else { if (_tokenType == JsonTokenType.StartObject) { switch (b) { case 125: break; default: ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.ExpectedStartOfPropertyNotFound, b, default(ReadOnlySpan<byte>)); goto case 34; case 34: { long totalConsumed = _totalConsumed; int consumed = _consumed; long bytePositionInLine = _bytePositionInLine; long lineNumber = _lineNumber; SequencePosition currentPosition = _currentPosition; flag = ConsumePropertyNameMultiSegment(); if (!flag) { _consumed = consumed; _tokenType = JsonTokenType.StartObject; _bytePositionInLine = bytePositionInLine; _lineNumber = lineNumber; _totalConsumed = totalConsumed; _currentPosition = currentPosition; } goto IL_0173; } } EndObject(); goto IL_0171; } if (_tokenType != JsonTokenType.StartArray) flag = ((_tokenType != JsonTokenType.PropertyName) ? ConsumeNextTokenOrRollbackMultiSegment(b) : ConsumeValueMultiSegment(b)); else { if (b == 93) { EndArray(); goto IL_0171; } flag = ConsumeValueMultiSegment(b); } } } else flag = ReadFirstTokenMultiSegment(b); } goto IL_0173; IL_0171: flag = true; goto IL_0173; IL_0173: return flag; } private bool ValidateStateAtEndOfData() { if (_bitStack.CurrentDepth != 0) ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.ZeroDepthAtEnd, 0, default(ReadOnlySpan<byte>)); if (_readerOptions.CommentHandling == JsonCommentHandling.Allow && _tokenType == JsonTokenType.Comment) return false; if (_tokenType != JsonTokenType.EndArray && _tokenType != JsonTokenType.EndObject) ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.InvalidEndOfJsonNonPrimitive, 0, default(ReadOnlySpan<byte>)); return true; } [MethodImpl(MethodImplOptions.AggressiveInlining)] private bool HasMoreDataMultiSegment() { if (_consumed >= (uint)_buffer.Length) { if (_isNotPrimitive && IsLastSpan && !ValidateStateAtEndOfData()) return false; if (!GetNextSpan()) { if (_isNotPrimitive && IsLastSpan) ValidateStateAtEndOfData(); return false; } } return true; } [MethodImpl(MethodImplOptions.AggressiveInlining)] private bool HasMoreDataMultiSegment(ExceptionResource resource) { if (_consumed >= (uint)_buffer.Length) { if (IsLastSpan) ThrowHelper.ThrowJsonReaderException(ref this, resource, 0, default(ReadOnlySpan<byte>)); if (!GetNextSpan()) { if (IsLastSpan) ThrowHelper.ThrowJsonReaderException(ref this, resource, 0, default(ReadOnlySpan<byte>)); return false; } } return true; } private bool GetNextSpan() { ReadOnlyMemory<byte> memory; while (true) { SequencePosition currentPosition = _currentPosition; _currentPosition = _nextPosition; if (!_sequence.TryGet(ref _nextPosition, out memory, true)) { _currentPosition = currentPosition; _isLastSegment = true; return false; } if (memory.Length != 0) break; _currentPosition = currentPosition; } if (_isFinalBlock) _isLastSegment = !_sequence.TryGet(ref _nextPosition, out ReadOnlyMemory<byte> _, false); _buffer = memory.Span; _totalConsumed += _consumed; _consumed = 0; return true; } private bool ReadFirstTokenMultiSegment(byte first) { switch (first) { case 123: _bitStack.SetFirstBit(); _tokenType = JsonTokenType.StartObject; ValueSpan = _buffer.Slice(_consumed, 1); _consumed++; _bytePositionInLine++; _inObject = true; _isNotPrimitive = true; break; case 91: _bitStack.ResetFirstBit(); _tokenType = JsonTokenType.StartArray; ValueSpan = _buffer.Slice(_consumed, 1); _consumed++; _bytePositionInLine++; _isNotPrimitive = true; break; default: { if (JsonHelpers.IsDigit(first) || first == 45) { if (!TryGetNumberMultiSegment(_buffer.Slice(_consumed), out int consumed)) return false; _tokenType = JsonTokenType.Number; _consumed += consumed; } else if (!ConsumeValueMultiSegment(first)) { return false; } JsonTokenType tokenType = _tokenType; bool flag = _isNotPrimitive = ((tokenType == JsonTokenType.StartObject || tokenType == JsonTokenType.StartArray) ? true : false); break; } } return true; } private void SkipWhiteSpaceMultiSegment() { do { SkipWhiteSpace(); } while (_consumed >= _buffer.Length && GetNextSpan()); } private bool ConsumeValueMultiSegment(byte marker) { SequencePosition currentPosition2; while (true) { _trailingCommaBeforeComment = false; switch (marker) { case 34: return ConsumeStringMultiSegment(); case 123: StartObject(); goto IL_01d5; case 91: StartArray(); goto IL_01d5; default: { if (!JsonHelpers.IsDigit(marker)) { switch (marker) { case 45: break; case 102: return ConsumeLiteralMultiSegment(JsonConstants.FalseValue, JsonTokenType.False); case 116: return ConsumeLiteralMultiSegment(JsonConstants.TrueValue, JsonTokenType.True); case 110: return ConsumeLiteralMultiSegment(JsonConstants.NullValue, JsonTokenType.Null); default: goto IL_0080; } } return ConsumeNumberMultiSegment(); } IL_01c2: ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.ExpectedStartOfValueNotFound, marker, default(ReadOnlySpan<byte>)); goto IL_01d5; IL_0080: switch (_readerOptions.CommentHandling) { case JsonCommentHandling.Allow: break; default: goto IL_00b8; case JsonCommentHandling.Disallow: goto IL_01c2; } if (marker == 47) { SequencePosition currentPosition = _currentPosition; if (!SkipOrConsumeCommentMultiSegmentWithRollback()) { _currentPosition = currentPosition; return false; } return true; } goto IL_01c2; IL_00b8: if (marker == 47) break; goto IL_01c2; IL_01d5: return true; } currentPosition2 = _currentPosition; if (!SkipCommentMultiSegment(out int _)) break; if (_consumed >= (uint)_buffer.Length) { if (_isNotPrimitive && IsLastSpan && _tokenType != JsonTokenType.EndArray && _tokenType != JsonTokenType.EndObject) ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.InvalidEndOfJsonNonPrimitive, 0, default(ReadOnlySpan<byte>)); if (!GetNextSpan()) { if (_isNotPrimitive && IsLastSpan && _tokenType != JsonTokenType.EndArray && _tokenType != JsonTokenType.EndObject) ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.InvalidEndOfJsonNonPrimitive, 0, default(ReadOnlySpan<byte>)); _currentPosition = currentPosition2; return false; } } marker = _buffer[_consumed]; if (marker <= 32) { SkipWhiteSpaceMultiSegment(); if (!HasMoreDataMultiSegment()) { _currentPosition = currentPosition2; return false; } marker = _buffer[_consumed]; } TokenStartIndex = BytesConsumed; } _currentPosition = currentPosition2; return false; } private bool ConsumeLiteralMultiSegment(ReadOnlySpan<byte> literal, JsonTokenType tokenType) { ReadOnlySpan<byte> span = _buffer.Slice(_consumed); int consumed = literal.Length; if (!span.StartsWith(literal)) { int consumed2 = _consumed; if (!CheckLiteralMultiSegment(span, literal, out consumed)) { _consumed = consumed2; return false; } } else { ValueSpan = span.Slice(0, literal.Length); HasValueSequence = false; } _tokenType = tokenType; _consumed += consumed; _bytePositionInLine += consumed; return true; } private unsafe bool CheckLiteralMultiSegment(ReadOnlySpan<byte> span, ReadOnlySpan<byte> literal, out int consumed) { Span<byte> destination = new Span<byte>(stackalloc byte[5], 5); int num = 0; long totalConsumed = _totalConsumed; SequencePosition currentPosition = _currentPosition; ReadOnlySpan<byte> readOnlySpan; if (span.Length >= literal.Length || IsLastSpan) { _bytePositionInLine += FindMismatch(span, literal); int num2 = Math.Min(span.Length, (int)_bytePositionInLine + 1); readOnlySpan = span.Slice(0, num2); readOnlySpan.CopyTo(destination); num += num2; } else if (!literal.StartsWith(span)) { _bytePositionInLine += FindMismatch(span, literal); int num3 = Math.Min(span.Length, (int)_bytePositionInLine + 1); readOnlySpan = span.Slice(0, num3); readOnlySpan.CopyTo(destination); num += num3; } else { ReadOnlySpan<byte> readOnlySpan2 = literal.Slice(span.Length); SequencePosition currentPosition2 = _currentPosition; int consumed2 = _consumed; int num4 = literal.Length - readOnlySpan2.Length; while (true) { _totalConsumed += num4; _bytePositionInLine += num4; if (!GetNextSpan()) { _totalConsumed = totalConsumed; consumed = 0; _currentPosition = currentPosition; if (IsLastSpan) break; return false; } int num5 = Math.Min(span.Length, destination.Length - num); readOnlySpan = span.Slice(0, num5); readOnlySpan.CopyTo(destination.Slice(num)); num += num5; span = _buffer; if (span.StartsWith(readOnlySpan2)) { HasValueSequence = true; SequencePosition start = new SequencePosition(currentPosition2.GetObject(), currentPosition2.GetInteger() + consumed2); SequencePosition end = new SequencePosition(_currentPosition.GetObject(), _currentPosition.GetInteger() + readOnlySpan2.Length); ValueSequence = _sequence.Slice(start, end); consumed = readOnlySpan2.Length; return true; } if (!readOnlySpan2.StartsWith(span)) { _bytePositionInLine += FindMismatch(span, readOnlySpan2); num5 = Math.Min(span.Length, (int)_bytePositionInLine + 1); readOnlySpan = span.Slice(0, num5); readOnlySpan.CopyTo(destination.Slice(num)); num += num5; break; } readOnlySpan2 = readOnlySpan2.Slice(span.Length); num4 = span.Length; } } _totalConsumed = totalConsumed; consumed = 0; _currentPosition = currentPosition; throw GetInvalidLiteralMultiSegment(destination.Slice(0, num).ToArray()); } private static int FindMismatch(ReadOnlySpan<byte> span, ReadOnlySpan<byte> literal) { int num = Math.Min(span.Length, literal.Length); int i; for (i = 0; i < num && span[i] == literal[i]; i++) { } return i; } private JsonException GetInvalidLiteralMultiSegment(ReadOnlySpan<byte> span) { ExceptionResource resource; switch (span[0]) { case 116: resource = ExceptionResource.ExpectedTrue; break; case 102: resource = ExceptionResource.ExpectedFalse; break; default: resource = ExceptionResource.ExpectedNull; break; } return ThrowHelper.GetJsonReaderException(ref this, resource, 0, span); } private bool ConsumeNumberMultiSegment() { if (!TryGetNumberMultiSegment(_buffer.Slice(_consumed), out int consumed)) return false; _tokenType = JsonTokenType.Number; _consumed += consumed; if (_consumed >= (uint)_buffer.Length && _isNotPrimitive) ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.ExpectedEndOfDigitNotFound, _buffer[_consumed - 1], default(ReadOnlySpan<byte>)); return true; } private bool ConsumePropertyNameMultiSegment() { _trailingCommaBeforeComment = false; if (!ConsumeStringMultiSegment()) return false; if (!HasMoreDataMultiSegment(ExceptionResource.ExpectedValueAfterPropertyNameNotFound)) return false; byte b = _buffer[_consumed]; if (b <= 32) { SkipWhiteSpaceMultiSegment(); if (!HasMoreDataMultiSegment(ExceptionResource.ExpectedValueAfterPropertyNameNotFound)) return false; b = _buffer[_consumed]; } if (b != 58) ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.ExpectedSeparatorAfterPropertyNameNotFound, b, default(ReadOnlySpan<byte>)); _consumed++; _bytePositionInLine++; _tokenType = JsonTokenType.PropertyName; return true; } private bool ConsumeStringMultiSegment() { ReadOnlySpan<byte> readOnlySpan = _buffer.Slice(_consumed + 1); int num = readOnlySpan.IndexOfQuoteOrAnyControlOrBackSlash(); if (num >= 0) { if (readOnlySpan[num] == 34) { _bytePositionInLine += num + 2; ValueSpan = readOnlySpan.Slice(0, num); HasValueSequence = false; ValueIsEscaped = false; _tokenType = JsonTokenType.String; _consumed += num + 2; return true; } return ConsumeStringAndValidateMultiSegment(readOnlySpan, num); } if (IsLastSpan) { _bytePositionInLine += readOnlySpan.Length + 1; ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.EndOfStringNotFound, 0, default(ReadOnlySpan<byte>)); } return ConsumeStringNextSegment(); } private bool ConsumeStringNextSegment() { PartialStateForRollback state = CaptureState(); HasValueSequence = true; int num = _buffer.Length - _consumed; ReadOnlySpan<byte> buffer; int num2; while (true) { if (!GetNextSpan()) { if (IsLastSpan) { _bytePositionInLine += num; RollBackState(ref state, true); ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.EndOfStringNotFound, 0, default(ReadOnlySpan<byte>)); } RollBackState(ref state, false); return false; } buffer = _buffer; num2 = buffer.IndexOfQuoteOrAnyControlOrBackSlash(); if (num2 >= 0) break; _totalConsumed += buffer.Length; _bytePositionInLine += buffer.Length; } SequencePosition end; if (buffer[num2] == 34) { end = new SequencePosition(_currentPosition.GetObject(), _currentPosition.GetInteger() + num2); _bytePositionInLine += num + num2 + 1; _totalConsumed += num; _consumed = num2 + 1; ValueIsEscaped = false; } else { _bytePositionInLine += num + num2; ValueIsEscaped = true; bool flag = false; while (true) { if (num2 >= buffer.Length) { if (!GetNextSpan()) { if (IsLastSpan) { RollBackState(ref state, true); ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.EndOfStringNotFound, 0, default(ReadOnlySpan<byte>)); } RollBackState(ref state, false); return false; } _totalConsumed += buffer.Length; buffer = _buffer; num2 = 0; continue; } byte b = buffer[num2]; switch (b) { case 34: break; case 92: goto IL_012e; default: goto IL_013a; } if (!flag) break; flag = false; goto IL_027b; IL_012e: flag = !flag; goto IL_027b; IL_013a: if (flag) { if (JsonConstants.EscapableChars.IndexOf(b) == -1) { RollBackState(ref state, true); ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.InvalidCharacterAfterEscapeWithinString, b, default(ReadOnlySpan<byte>)); } if (b == 117) { _bytePositionInLine++; int num3 = 0; int num4 = num2 + 1; while (true) { if (num4 < buffer.Length) { byte nextByte = buffer[num4]; if (!JsonReaderHelper.IsHexDigit(nextByte)) { RollBackState(ref state, true); ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.InvalidHexCharacterWithinString, nextByte, default(ReadOnlySpan<byte>)); } num3++; _bytePositionInLine++; if (num3 >= 4) break; num4++; } else { if (!GetNextSpan()) { if (IsLastSpan) { RollBackState(ref state, true); ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.EndOfStringNotFound, 0, default(ReadOnlySpan<byte>)); } RollBackState(ref state, false); return false; } _totalConsumed += buffer.Length; buffer = _buffer; num4 = 0; } } flag = false; num2 = num4 + 1; continue; } flag = false; } else if (b < 32) { RollBackState(ref state, true); ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.InvalidCharacterWithinString, b, default(ReadOnlySpan<byte>)); } goto IL_027b; IL_027b: _bytePositionInLine++; num2++; } _bytePositionInLine++; _consumed = num2 + 1; _totalConsumed += num; end = new SequencePosition(_currentPosition.GetObject(), _currentPosition.GetInteger() + num2); } SequencePosition startPosition = state.GetStartPosition(1); ValueSequence = _sequence.Slice(startPosition, end); _tokenType = JsonTokenType.String; return true; } private bool ConsumeStringAndValidateMultiSegment(ReadOnlySpan<byte> data, int idx) { PartialStateForRollback state = CaptureState(); HasValueSequence = false; int num = _buffer.Length - _consumed; _bytePositionInLine += idx + 1; bool flag = false; while (true) { if (idx < data.Length) { byte b = data[idx]; switch (b) { case 34: if (!flag) { if (HasValueSequence) { _bytePositionInLine++; _consumed = idx + 1; _totalConsumed += num; SequencePosition end = new SequencePosition(_currentPosition.GetObject(), _currentPosition.GetInteger() + idx); SequencePosition startPosition = state.GetStartPosition(1); ValueSequence = _sequence.Slice(startPosition, end); } else { _bytePositionInLine++; _consumed += idx + 2; ValueSpan = data.Slice(0, idx); } ValueIsEscaped = true; _tokenType = JsonTokenType.String; return true; } flag = false; goto IL_01b3; case 92: flag = !flag; goto IL_01b3; default: { if (flag) { if (JsonConstants.EscapableChars.IndexOf(b) == -1) { RollBackState(ref state, true); ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.InvalidCharacterAfterEscapeWithinString, b, default(ReadOnlySpan<byte>)); } if (b == 117) { _bytePositionInLine++; int num2 = 0; int num3 = idx + 1; while (true) { if (num3 < data.Length) { byte nextByte = data[num3]; if (!JsonReaderHelper.IsHexDigit(nextByte)) { RollBackState(ref state, true); ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.InvalidHexCharacterWithinString, nextByte, default(ReadOnlySpan<byte>)); } num2++; _bytePositionInLine++; if (num2 >= 4) break; num3++; } else { if (!GetNextSpan()) { if (IsLastSpan) { RollBackState(ref state, true); ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.EndOfStringNotFound, 0, default(ReadOnlySpan<byte>)); } RollBackState(ref state, false); return false; } if (HasValueSequence) _totalConsumed += data.Length; data = _buffer; num3 = 0; HasValueSequence = true; } } flag = false; idx = num3 + 1; break; } flag = false; } else if (b < 32) { RollBackState(ref state, true); ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.InvalidCharacterWithinString, b, default(ReadOnlySpan<byte>)); } goto IL_01b3; } IL_01b3: _bytePositionInLine++; idx++; break; } } else { if (!GetNextSpan()) break; if (HasValueSequence) _totalConsumed += data.Length; data = _buffer; idx = 0; HasValueSequence = true; } } if (IsLastSpan) { RollBackState(ref state, true); ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.EndOfStringNotFound, 0, default(ReadOnlySpan<byte>)); } RollBackState(ref state, false); return false; } private void RollBackState([In] [System.Runtime.CompilerServices.ScopedRef] [System.Runtime.CompilerServices.IsReadOnly] ref PartialStateForRollback state, bool isError = false) { _totalConsumed = state._prevTotalConsumed; if (!isError) _bytePositionInLine = state._prevBytePositionInLine; _consumed = state._prevConsumed; _currentPosition = state._prevCurrentPosition; } private bool TryGetNumberMultiSegment(ReadOnlySpan<byte> data, out int consumed) { PartialStateForRollback rollBackState = CaptureState(); consumed = 0; int i = 0; if (ConsumeNegativeSignMultiSegment(ref data, ref i, ref rollBackState) == ConsumeNumberResult.NeedMoreData) { RollBackState(ref rollBackState, false); return false; } byte b = data[i]; if (b == 48) { switch (ConsumeZeroMultiSegment(ref data, ref i, ref rollBackState)) { case ConsumeNumberResult.NeedMoreData: RollBackState(ref rollBackState, false); return false; case ConsumeNumberResult.Success: goto IL_01aa; } b = data[i]; } else { switch (ConsumeIntegerDigitsMultiSegment(ref data, ref i)) { case ConsumeNumberResult.NeedMoreData: RollBackState(ref rollBackState, false); return false; case ConsumeNumberResult.Success: goto IL_01aa; } b = data[i]; if (b != 46 && b != 69 && b != 101) { RollBackState(ref rollBackState, true); ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.ExpectedEndOfDigitNotFound, b, default(ReadOnlySpan<byte>)); } } if (b == 46) { i++; _bytePositionInLine++; switch (ConsumeDecimalDigitsMultiSegment(ref data, ref i, ref rollBackState)) { case ConsumeNumberResult.NeedMoreData: RollBackState(ref rollBackState, false); return false; case ConsumeNumberResult.Success: goto IL_01aa; } b = data[i]; if (b != 69 && b != 101) { RollBackState(ref rollBackState, true); ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.ExpectedNextDigitEValueNotFound, b, default(ReadOnlySpan<byte>)); } } i++; _bytePositionInLine++; if (ConsumeSignMultiSegment(ref data, ref i, ref rollBackState) == ConsumeNumberResult.NeedMoreData) { RollBackState(ref rollBackState, false); return false; } i++; _bytePositionInLine++; switch (ConsumeIntegerDigitsMultiSegment(ref data, ref i)) { case ConsumeNumberResult.NeedMoreData: RollBackState(ref rollBackState, false); return false; default: RollBackState(ref rollBackState, true); ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.ExpectedEndOfDigitNotFound, data[i], default(ReadOnlySpan<byte>)); break; case ConsumeNumberResult.Success: break; } goto IL_01aa; IL_01aa: if (HasValueSequence) { SequencePosition startPosition = rollBackState.GetStartPosition(0); SequencePosition end = new SequencePosition(_currentPosition.GetObject(), _currentPosition.GetInteger() + i); ValueSequence = _sequence.Slice(startPosition, end); consumed = i; } else { ValueSpan = data.Slice(0, i); consumed = i; } return true; } private ConsumeNumberResult ConsumeNegativeSignMultiSegment(ref ReadOnlySpan<byte> data, [System.Runtime.CompilerServices.ScopedRef] ref int i, [In] [System.Runtime.CompilerServices.ScopedRef] [System.Runtime.CompilerServices.IsReadOnly] ref PartialStateForRollback rollBackState) { byte b = data[i]; if (b == 45) { i++; _bytePositionInLine++; if (i >= data.Length) { if (IsLastSpan) { RollBackState(ref rollBackState, true); ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.RequiredDigitNotFoundEndOfData, 0, default(ReadOnlySpan<byte>)); } if (!GetNextSpan()) { if (IsLastSpan) { RollBackState(ref rollBackState, true); ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.RequiredDigitNotFoundEndOfData, 0, default(ReadOnlySpan<byte>)); } return ConsumeNumberResult.NeedMoreData; } _totalConsumed += i; HasValueSequence = true; i = 0; data = _buffer; } b = data[i]; if (!JsonHelpers.IsDigit(b)) { RollBackState(ref rollBackState, true); ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.RequiredDigitNotFoundAfterSign, b, default(ReadOnlySpan<byte>)); } } return ConsumeNumberResult.OperationIncomplete; } private ConsumeNumberResult ConsumeZeroMultiSegment(ref ReadOnlySpan<byte> data, [System.Runtime.CompilerServices.ScopedRef] ref int i, [In] [System.Runtime.CompilerServices.ScopedRef] [System.Runtime.CompilerServices.IsReadOnly] ref PartialStateForRollback rollBackState) { i++; _bytePositionInLine++; byte value; if (i < data.Length) { value = data[i]; if (JsonConstants.Delimiters.IndexOf(value) >= 0) return ConsumeNumberResult.Success; } else { if (IsLastSpan) return ConsumeNumberResult.Success; if (!GetNextSpan()) { if (IsLastSpan) return ConsumeNumberResult.Success; return ConsumeNumberResult.NeedMoreData; } _totalConsumed += i; HasValueSequence = true; i = 0; data = _buffer; value = data[i]; if (JsonConstants.Delimiters.IndexOf(value) >= 0) return ConsumeNumberResult.Success; } value = data[i]; if (value != 46 && value != 69 && value != 101) { RollBackState(ref rollBackState, true); ThrowHelper.ThrowJsonReaderException(ref this, JsonHelpers.IsInRangeInclusive(value, 48, 57) ? ExceptionResource.InvalidLeadingZeroInNumber : ExceptionResource.ExpectedEndOfDigitNotFound, value, default(ReadOnlySpan<byte>)); } return ConsumeNumberResult.OperationIncomplete; } private ConsumeNumberResult ConsumeIntegerDigitsMultiSegment(ref ReadOnlySpan<byte> data, [System.Runtime.CompilerServices.ScopedRef] ref int i) { byte value = 0; int num = 0; while (i < data.Length) { value = data[i]; if (!JsonHelpers.IsDigit(value)) break; num++; i++; } if (i >= data.Length) { if (IsLastSpan) { _bytePositionInLine += num; return ConsumeNumberResult.Success; } while (true) { if (!GetNextSpan()) { if (IsLastSpan) { _bytePositionInLine += num; return ConsumeNumberResult.Success; } return ConsumeNumberResult.NeedMoreData; } _totalConsumed += i; _bytePositionInLine += num; num = 0; HasValueSequence = true; i = 0; data = _buffer; while (i < data.Length) { value = data[i]; if (!JsonHelpers.IsDigit(value)) break; i++; } _bytePositionInLine += i; if (i < data.Length) break; if (IsLastSpan) return ConsumeNumberResult.Success; } } else _bytePositionInLine += num; if (JsonConstants.Delimiters.IndexOf(value) >= 0) return ConsumeNumberResult.Success; return ConsumeNumberResult.OperationIncomplete; } private ConsumeNumberResult ConsumeDecimalDigitsMultiSegment(ref ReadOnlySpan<byte> data, [System.Runtime.CompilerServices.ScopedRef] ref int i, [In] [System.Runtime.CompilerServices.ScopedRef] [System.Runtime.CompilerServices.IsReadOnly] ref PartialStateForRollback rollBackState) { if (i >= data.Length) { if (IsLastSpan) { RollBackState(ref rollBackState, true); ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.RequiredDigitNotFoundEndOfData, 0, default(ReadOnlySpan<byte>)); } if (!GetNextSpan()) { if (IsLastSpan) { RollBackState(ref rollBackState, true); ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.RequiredDigitNotFoundEndOfData, 0, default(ReadOnlySpan<byte>)); } return ConsumeNumberResult.NeedMoreData; } _totalConsumed += i; HasValueSequence = true; i = 0; data = _buffer; } byte b = data[i]; if (!JsonHelpers.IsDigit(b)) { RollBackState(ref rollBackState, true); ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.RequiredDigitNotFoundAfterDecimal, b, default(ReadOnlySpan<byte>)); } i++; _bytePositionInLine++; return ConsumeIntegerDigitsMultiSegment(ref data, ref i); } private ConsumeNumberResult ConsumeSignMultiSegment(ref ReadOnlySpan<byte> data, [System.Runtime.CompilerServices.ScopedRef] ref int i, [In] [System.Runtime.CompilerServices.ScopedRef] [System.Runtime.CompilerServices.IsReadOnly] ref PartialStateForRollback rollBackState) { if (i >= data.Length) { if (IsLastSpan) { RollBackState(ref rollBackState, true); ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.RequiredDigitNotFoundEndOfData, 0, default(ReadOnlySpan<byte>)); } if (!GetNextSpan()) { if (IsLastSpan) { RollBackState(ref rollBackState, true); ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.RequiredDigitNotFoundEndOfData, 0, default(ReadOnlySpan<byte>)); } return ConsumeNumberResult.NeedMoreData; } _totalConsumed += i; HasValueSequence = true; i = 0; data = _buffer; } byte b = data[i]; if (b == 43 || b == 45) { i++; _bytePositionInLine++; if (i >= data.Length) { if (IsLastSpan) { RollBackState(ref rollBackState, true); ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.RequiredDigitNotFoundEndOfData, 0, default(ReadOnlySpan<byte>)); } if (!GetNextSpan()) { if (IsLastSpan) { RollBackState(ref rollBackState, true); ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.RequiredDigitNotFoundEndOfData, 0, default(ReadOnlySpan<byte>)); } return ConsumeNumberResult.NeedMoreData; } _totalConsumed += i; HasValueSequence = true; i = 0; data = _buffer; } b = data[i]; } if (!JsonHelpers.IsDigit(b)) { RollBackState(ref rollBackState, true); ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.RequiredDigitNotFoundAfterSign, b, default(ReadOnlySpan<byte>)); } return ConsumeNumberResult.OperationIncomplete; } private bool ConsumeNextTokenOrRollbackMultiSegment(byte marker) { long totalConsumed = _totalConsumed; int consumed = _consumed; long bytePositionInLine = _bytePositionInLine; long lineNumber = _lineNumber; JsonTokenType tokenType = _tokenType; SequencePosition currentPosition = _currentPosition; bool trailingCommaBeforeComment = _trailingCommaBeforeComment; switch (ConsumeNextTokenMultiSegment(marker)) { case ConsumeTokenResult.Success: return true; case ConsumeTokenResult.NotEnoughDataRollBackState: _consumed = consumed; _tokenType = tokenType; _bytePositionInLine = bytePositionInLine; _lineNumber = lineNumber; _totalConsumed = totalConsumed; _currentPosition = currentPosition; _trailingCommaBeforeComment = trailingCommaBeforeComment; break; } return false; } private ConsumeTokenResult ConsumeNextTokenMultiSegment(byte marker) { if (_readerOptions.CommentHandling != 0) { if (_readerOptions.CommentHandling != JsonCommentHandling.Allow) return ConsumeNextTokenUntilAfterAllCommentsAreSkippedMultiSegment(marker); if (marker == 47) { if (!SkipOrConsumeCommentMultiSegmentWithRollback()) return ConsumeTokenResult.NotEnoughDataRollBackState; return ConsumeTokenResult.Success; } if (_tokenType == JsonTokenType.Comment) return ConsumeNextTokenFromLastNonCommentTokenMultiSegment(); } if (_bitStack.CurrentDepth == 0) { if (_readerOptions.AllowMultipleValues) { if (!ReadFirstTokenMultiSegment(marker)) return ConsumeTokenResult.NotEnoughDataRollBackState; return ConsumeTokenResult.Success; } ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.ExpectedEndAfterSingleJson, marker, default(ReadOnlySpan<byte>)); } switch (marker) { case 44: { _consumed++; _bytePositionInLine++; if (_consumed >= (uint)_buffer.Length) { if (IsLastSpan) { _consumed--; _bytePositionInLine--; ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.ExpectedStartOfPropertyOrValueNotFound, 0, default(ReadOnlySpan<byte>)); } if (!GetNextSpan()) { if (IsLastSpan) { _consumed--; _bytePositionInLine--; ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.ExpectedStartOfPropertyOrValueNotFound, 0, default(ReadOnlySpan<byte>)); } return ConsumeTokenResult.NotEnoughDataRollBackState; } } byte b = _buffer[_consumed]; if (b <= 32) { SkipWhiteSpaceMultiSegment(); if (!HasMoreDataMultiSegment(ExceptionResource.ExpectedStartOfPropertyOrValueNotFound)) return ConsumeTokenResult.NotEnoughDataRollBackState; b = _buffer[_consumed]; } TokenStartIndex = BytesConsumed; if (_readerOptions.CommentHandling == JsonCommentHandling.Allow && b == 47) { _trailingCommaBeforeComment = true; if (!SkipOrConsumeCommentMultiSegmentWithRollback()) return ConsumeTokenResult.NotEnoughDataRollBackState; return ConsumeTokenResult.Success; } if (_inObject) { switch (b) { case 125: if (_readerOptions.AllowTrailingCommas) { EndObject(); return ConsumeTokenResult.Success; } ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.TrailingCommaNotAllowedBeforeObjectEnd, 0, default(ReadOnlySpan<byte>)); goto default; default: ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.ExpectedStartOfPropertyNotFound, b, default(ReadOnlySpan<byte>)); break; case 34: break; } if (!ConsumePropertyNameMultiSegment()) return ConsumeTokenResult.NotEnoughDataRollBackState; return ConsumeTokenResult.Success; } if (b == 93) { if (_readerOptions.AllowTrailingCommas) { EndArray(); return ConsumeTokenResult.Success; } ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.TrailingCommaNotAllowedBeforeArrayEnd, 0, default(ReadOnlySpan<byte>)); } if (!ConsumeValueMultiSegment(b)) return ConsumeTokenResult.NotEnoughDataRollBackState; return ConsumeTokenResult.Success; } case 125: EndObject(); break; case 93: EndArray(); break; default: ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.FoundInvalidCharacter, marker, default(ReadOnlySpan<byte>)); break; } return ConsumeTokenResult.Success; } private ConsumeTokenResult ConsumeNextTokenFromLastNonCommentTokenMultiSegment() { if (JsonReaderHelper.IsTokenTypePrimitive(_previousTokenType)) _tokenType = (_inObject ? JsonTokenType.StartObject : JsonTokenType.StartArray); else _tokenType = _previousTokenType; if (HasMoreDataMultiSegment()) { byte b = _buffer[_consumed]; if (b <= 32) { SkipWhiteSpaceMultiSegment(); if (!HasMoreDataMultiSegment()) goto IL_03ad; b = _buffer[_consumed]; } if (_bitStack.CurrentDepth == 0 && _tokenType != 0) { if (_readerOptions.AllowMultipleValues) { if (!ReadFirstTokenMultiSegment(b)) return ConsumeTokenResult.NotEnoughDataRollBackState; return ConsumeTokenResult.Success; } ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.ExpectedEndAfterSingleJson, b, default(ReadOnlySpan<byte>)); } TokenStartIndex = BytesConsumed; switch (b) { case 44: if ((int)_previousTokenType <= 1 || _previousTokenType == JsonTokenType.StartArray || _trailingCommaBeforeComment) ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.ExpectedStartOfPropertyOrValueAfterComment, b, default(ReadOnlySpan<byte>)); _consumed++; _bytePositionInLine++; if (_consumed >= (uint)_buffer.Length) { if (IsLastSpan) { _consumed--; _bytePositionInLine--; ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.ExpectedStartOfPropertyOrValueNotFound, 0, default(ReadOnlySpan<byte>)); } if (!GetNextSpan()) { if (IsLastSpan) { _consumed--; _bytePositionInLine--; ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.ExpectedStartOfPropertyOrValueNotFound, 0, default(ReadOnlySpan<byte>)); } break; } } b = _buffer[_consumed]; if (b <= 32) { SkipWhiteSpaceMultiSegment(); if (!HasMoreDataMultiSegment(ExceptionResource.ExpectedStartOfPropertyOrValueNotFound)) break; b = _buffer[_consumed]; } TokenStartIndex = BytesConsumed; if (b == 47) { _trailingCommaBeforeComment = true; if (!SkipOrConsumeCommentMultiSegmentWithRollback()) break; } else if (_inObject) { switch (b) { case 125: if (_readerOptions.AllowTrailingCommas) goto IL_0229; ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.TrailingCommaNotAllowedBeforeObjectEnd, 0, default(ReadOnlySpan<byte>)); goto default; default: ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.ExpectedStartOfPropertyNotFound, b, default(ReadOnlySpan<byte>)); break; case 34: break; } if (!ConsumePropertyNameMultiSegment()) break; } else { if (b == 93) { if (_readerOptions.AllowTrailingCommas) { EndArray(); goto IL_03ab; } ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.TrailingCommaNotAllowedBeforeArrayEnd, 0, default(ReadOnlySpan<byte>)); } if (!ConsumeValueMultiSegment(b)) break; } goto IL_03ab; case 125: EndObject(); goto IL_03ab; case 93: EndArray(); goto IL_03ab; default: { if (_tokenType == JsonTokenType.None) { if (!ReadFirstTokenMultiSegment(b)) break; } else if (_tokenType == JsonTokenType.StartObject) { if (b != 34) ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.ExpectedStartOfPropertyNotFound, b, default(ReadOnlySpan<byte>)); long totalConsumed = _totalConsumed; int consumed = _consumed; long bytePositionInLine = _bytePositionInLine; long lineNumber = _lineNumber; if (!ConsumePropertyNameMultiSegment()) { _consumed = consumed; _tokenType = JsonTokenType.StartObject; _bytePositionInLine = bytePositionInLine; _lineNumber = lineNumber; _totalConsumed = totalConsumed; break; } } else if (_tokenType == JsonTokenType.StartArray) { if (!ConsumeValueMultiSegment(b)) break; } else if (_tokenType == JsonTokenType.PropertyName) { if (!ConsumeValueMultiSegment(b)) break; } else if (_inObject) { if (b != 34) ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.ExpectedStartOfPropertyNotFound, b, default(ReadOnlySpan<byte>)); if (!ConsumePropertyNameMultiSegment()) break; } else if (!ConsumeValueMultiSegment(b)) { break; } goto IL_03ab; } IL_03ab: return ConsumeTokenResult.Success; IL_0229: EndObject(); goto IL_03ab; } } goto IL_03ad; IL_03ad: return ConsumeTokenResult.NotEnoughDataRollBackState; } private bool SkipAllCommentsMultiSegment([System.Runtime.CompilerServices.ScopedRef] ref byte marker) { while (true) { if (marker != 47) return true; if (!SkipOrConsumeCommentMultiSegmentWithRollback() || !HasMoreDataMultiSegment()) break; marker = _buffer[_consumed]; if (marker <= 32) { SkipWhiteSpaceMultiSegment(); if (!HasMoreDataMultiSegment()) break; marker = _buffer[_consumed]; } } return false; } private bool SkipAllCommentsMultiSegment([System.Runtime.CompilerServices.ScopedRef] ref byte marker, ExceptionResource resource) { while (true) { if (marker != 47) return true; if (!SkipOrConsumeCommentMultiSegmentWithRollback() || !HasMoreDataMultiSegment(resource)) break; marker = _buffer[_consumed]; if (marker <= 32) { SkipWhiteSpaceMultiSegment(); if (!HasMoreDataMultiSegment(resource)) break; marker = _buffer[_consumed]; } } return false; } private ConsumeTokenResult ConsumeNextTokenUntilAfterAllCommentsAreSkippedMultiSegment(byte marker) { if (SkipAllCommentsMultiSegment(ref marker)) { TokenStartIndex = BytesConsumed; if (_tokenType == JsonTokenType.StartObject) { switch (marker) { case 125: break; default: ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.ExpectedStartOfPropertyNotFound, marker, default(ReadOnlySpan<byte>)); goto IL_004d; case 34: goto IL_004d; } EndObject(); } else if (_tokenType == JsonTokenType.StartArray) { if (marker == 93) EndArray(); else if (!ConsumeValueMultiSegment(marker)) { goto IL_0301; } } else if (_tokenType == JsonTokenType.PropertyName) { if (!ConsumeValueMultiSegment(marker)) goto IL_0301; } else if (_bitStack.CurrentDepth != 0) { switch (marker) { case 44: _consumed++; _bytePositionInLine++; if (_consumed >= (uint)_buffer.Length) { if (IsLastSpan) { _consumed--; _bytePositionInLine--; ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.ExpectedStartOfPropertyOrValueNotFound, 0, default(ReadOnlySpan<byte>)); } if (!GetNextSpan()) { if (IsLastSpan) { _consumed--; _bytePositionInLine--; ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.ExpectedStartOfPropertyOrValueNotFound, 0, default(ReadOnlySpan<byte>)); } return ConsumeTokenResult.NotEnoughDataRollBackState; } } marker = _buffer[_consumed]; if (marker <= 32) { SkipWhiteSpaceMultiSegment(); if (!HasMoreDataMultiSegment(ExceptionResource.ExpectedStartOfPropertyOrValueNotFound)) return ConsumeTokenResult.NotEnoughDataRollBackState; marker = _buffer[_consumed]; } if (!SkipAllCommentsMultiSegment(ref marker, ExceptionResource.ExpectedStartOfPropertyOrValueNotFound)) return ConsumeTokenResult.NotEnoughDataRollBackState; TokenStartIndex = BytesConsumed; if (!_inObject) { if (marker == 93) { if (_readerOptions.AllowTrailingCommas) { EndArray(); break; } ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.TrailingCommaNotAllowedBeforeArrayEnd, 0, default(ReadOnlySpan<byte>)); } if (!ConsumeValueMultiSegment(marker)) return ConsumeTokenResult.NotEnoughDataRollBackState; return ConsumeTokenResult.Success; } switch (marker) { case 125: if (_readerOptions.AllowTrailingCommas) break; ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.TrailingCommaNotAllowedBeforeObjectEnd, 0, default(ReadOnlySpan<byte>)); goto default; default: ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.ExpectedStartOfPropertyNotFound, marker, default(ReadOnlySpan<byte>)); goto case 34; case 34: if (!ConsumePropertyNameMultiSegment()) return ConsumeTokenResult.NotEnoughDataRollBackState; return ConsumeTokenResult.Success; } EndObject(); break; case 125: EndObject(); break; case 93: EndArray(); break; default: ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.FoundInvalidCharacter, marker, default(ReadOnlySpan<byte>)); break; } } else { if (_readerOptions.AllowMultipleValues) { if (!ReadFirstTokenMultiSegment(marker)) return ConsumeTokenResult.NotEnoughDataRollBackState; return ConsumeTokenResult.Success; } ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.ExpectedEndAfterSingleJson, marker, default(ReadOnlySpan<byte>)); } goto IL_02ff; } goto IL_0301; IL_0301: return ConsumeTokenResult.IncompleteNoRollBackNecessary; IL_004d: long totalConsumed = _totalConsumed; int consumed = _consumed; long bytePositionInLine = _bytePositionInLine; long lineNumber = _lineNumber; SequencePosition currentPosition = _currentPosition; if (ConsumePropertyNameMultiSegment()) goto IL_02ff; _consumed = consumed; _tokenType = JsonTokenType.StartObject; _bytePositionInLine = bytePositionInLine; _lineNumber = lineNumber; _totalConsumed = totalConsumed; _currentPosition = currentPosition; goto IL_0301; IL_02ff: return ConsumeTokenResult.Success; } private bool SkipOrConsumeCommentMultiSegmentWithRollback() { long bytesConsumed = BytesConsumed; SequencePosition start = new SequencePosition(_currentPosition.GetObject(), _currentPosition.GetInteger() + _consumed); int tailBytesToIgnore; bool num = SkipCommentMultiSegment(out tailBytesToIgnore); if (num) { if (_readerOptions.CommentHandling == JsonCommentHandling.Allow) { SequencePosition end = new SequencePosition(_currentPosition.GetObject(), _currentPosition.GetInteger() + _consumed); ReadOnlySequence<byte> valueSequence = _sequence.Slice(start, end); valueSequence = valueSequence.Slice(2, valueSequence.Length - 2 - tailBytesToIgnore); HasValueSequence = !valueSequence.IsSingleSegment; if (HasValueSequence) ValueSequence = valueSequence; else ValueSpan = valueSequence.First.Span; if (_tokenType != JsonTokenType.Comment) _previousTokenType = _tokenType; _tokenType = JsonTokenType.Comment; return num; } } else { _totalConsumed = bytesConsumed; _consumed = 0; } return num; } private bool SkipCommentMultiSegment(out int tailBytesToIgnore) { _consumed++; _bytePositionInLine++; ReadOnlySpan<byte> localBuffer = _buffer.Slice(_consumed); if (localBuffer.Length == 0) { if (IsLastSpan) ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.UnexpectedEndOfDataWhileReadingComment, 0, default(ReadOnlySpan<byte>)); if (!GetNextSpan()) { if (IsLastSpan) ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.UnexpectedEndOfDataWhileReadingComment, 0, default(ReadOnlySpan<byte>)); tailBytesToIgnore = 0; return false; } localBuffer = _buffer; } byte b = localBuffer[0]; if (b != 47 && b != 42) ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.InvalidCharacterAtStartOfComment, b, default(ReadOnlySpan<byte>)); bool flag = b == 42; _consumed++; _bytePositionInLine++; localBuffer = localBuffer.Slice(1); if (localBuffer.Length == 0) { if (IsLastSpan) { tailBytesToIgnore = 0; if (flag) ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.UnexpectedEndOfDataWhileReadingComment, 0, default(ReadOnlySpan<byte>)); return true; } if (!GetNextSpan()) { tailBytesToIgnore = 0; if (IsLastSpan) { if (flag) ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.UnexpectedEndOfDataWhileReadingComment, 0, default(ReadOnlySpan<byte>)); return true; } return false; } localBuffer = _buffer; } if (flag) { tailBytesToIgnore = 2; return SkipMultiLineCommentMultiSegment(localBuffer); } return SkipSingleLineCommentMultiSegment(localBuffer, out tailBytesToIgnore); } private bool SkipSingleLineCommentMultiSegment(ReadOnlySpan<byte> localBuffer, out int tailBytesToSkip) { bool flag = false; int dangerousLineSeparatorBytesConsumed = 0; tailBytesToSkip = 0; while (true) { if (flag) { if (localBuffer[0] == 10) { tailBytesToSkip++; _consumed++; } break; } int num = FindLineSeparatorMultiSegment(localBuffer, ref dangerousLineSeparatorBytesConsumed); if (num != -1) { tailBytesToSkip++; _consumed += num + 1; _bytePositionInLine += num + 1; if (localBuffer[num] == 10) break; if (num < localBuffer.Length - 1) { if (localBuffer[num + 1] == 10) { tailBytesToSkip++; _consumed++; _bytePositionInLine++; } break; } flag = true; } else { _consumed += localBuffer.Length; _bytePositionInLine += localBuffer.Length; } if (IsLastSpan) { if (flag) break; return true; } if (!GetNextSpan()) { if (IsLastSpan) { if (flag) break; return true; } return false; } localBuffer = _buffer; } _bytePositionInLine = 0; _lineNumber++; return true; } private int FindLineSeparatorMultiSegment(ReadOnlySpan<byte> localBuffer, [System.Runtime.CompilerServices.ScopedRef] ref int dangerousLineSeparatorBytesConsumed) { if (dangerousLineSeparatorBytesConsumed != 0) { ThrowOnDangerousLineSeparatorMultiSegment(localBuffer, ref dangerousLineSeparatorBytesConsumed); if (dangerousLineSeparatorBytesConsumed != 0) return -1; } int num = 0; do { int num2 = localBuffer.IndexOfAny<byte>(10, 13, 226); dangerousLineSeparatorBytesConsumed = 0; if (num2 == -1) return -1; if (localBuffer[num2] != 226) return num + num2; int num3 = num2 + 1; localBuffer = localBuffer.Slice(num3); num += num3; dangerousLineSeparatorBytesConsumed++; ThrowOnDangerousLineSeparatorMultiSegment(localBuffer, ref dangerousLineSeparatorBytesConsumed); } while (dangerousLineSeparatorBytesConsumed == 0); return -1; } private void ThrowOnDangerousLineSeparatorMultiSegment(ReadOnlySpan<byte> localBuffer, [System.Runtime.CompilerServices.ScopedRef] ref int dangerousLineSeparatorBytesConsumed) { if (!localBuffer.IsEmpty) { if (dangerousLineSeparatorBytesConsumed == 1) { if (localBuffer[0] != 128) { dangerousLineSeparatorBytesConsumed = 0; return; } localBuffer = localBuffer.Slice(1); dangerousLineSeparatorBytesConsumed++; if (localBuffer.IsEmpty) return; } if (dangerousLineSeparatorBytesConsumed == 2) { byte b = localBuffer[0]; if (b == 168 || b == 169) ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.UnexpectedEndOfLineSeparator, 0, default(ReadOnlySpan<byte>)); else dangerousLineSeparatorBytesConsumed = 0; } } } private bool SkipMultiLineCommentMultiSegment(ReadOnlySpan<byte> localBuffer) { bool flag = false; bool flag2 = false; while (true) { if (flag) { if (localBuffer[0] == 47) { _consumed++; _bytePositionInLine++; return true; } flag = false; } if (flag2) { if (localBuffer[0] == 10) { _consumed++; localBuffer = localBuffer.Slice(1); } flag2 = false; } int num = localBuffer.IndexOfAny<byte>(42, 10, 13); if (num != -1) { int num2 = num + 1; byte b = localBuffer[num]; localBuffer = localBuffer.Slice(num2); _consumed += num2; switch (b) { case 42: flag = true; _bytePositionInLine += num2; break; case 10: _bytePositionInLine = 0; _lineNumber++; break; default: _bytePositionInLine = 0; _lineNumber++; flag2 = true; break; } } else { _consumed += localBuffer.Length; _bytePositionInLine += localBuffer.Length; localBuffer = ReadOnlySpan<byte>.Empty; } if (localBuffer.IsEmpty) { if (IsLastSpan) ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.UnexpectedEndOfDataWhileReadingComment, 0, default(ReadOnlySpan<byte>)); if (!GetNextSpan()) { if (!IsLastSpan) break; ThrowHelper.ThrowJsonReaderException(ref this, ExceptionResource.UnexpectedEndOfDataWhileReadingComment, 0, default(ReadOnlySpan<byte>)); } localBuffer = _buffer; } } return false; } private PartialStateForRollback CaptureState() { return new PartialStateForRollback(_totalConsumed, _bytePositionInLine, _consumed, _currentPosition); } [System.Runtime.CompilerServices.NullableContext(2)] public string GetString() { if (TokenType == JsonTokenType.Null) return null; if (TokenType != JsonTokenType.String && TokenType != JsonTokenType.PropertyName) ThrowHelper.ThrowInvalidOperationException_ExpectedString(TokenType); ReadOnlySpan<byte> readOnlySpan; if (!HasValueSequence) readOnlySpan = ValueSpan; else { ReadOnlySequence<byte> sequence = ValueSequence; readOnlySpan = ref sequence.ToArray(); } ReadOnlySpan<byte> readOnlySpan2 = readOnlySpan; if (ValueIsEscaped) return JsonReaderHelper.GetUnescapedString(readOnlySpan2); return JsonReaderHelper.TranscodeHelper(readOnlySpan2); } [System.Runtime.CompilerServices.IsReadOnly] public int CopyString(Span<byte> utf8Destination) { JsonTokenType tokenType = _tokenType; if ((tokenType != JsonTokenType.PropertyName && tokenType != JsonTokenType.String) || 1 == 0) ThrowHelper.ThrowInvalidOperationException_ExpectedString(_tokenType); return CopyValue(utf8Destination); } [System.Runtime.CompilerServices.IsReadOnly] internal int CopyValue(Span<byte> utf8Destination) { int bytesWritten; if (ValueIsEscaped) { if (!TryCopyEscapedString(utf8Destination, out bytesWritten)) { utf8Destination.Slice(0, bytesWritten).Clear(); ThrowHelper.ThrowArgumentException_DestinationTooShort(); } } else if (HasValueSequence) { ReadOnlySequence<byte> source = ValueSequence; ref source.CopyTo(utf8Destination); bytesWritten = (int)source.Length; } else { ReadOnlySpan<byte> valueSpan = ValueSpan; valueSpan.CopyTo(utf8Destination); bytesWritten = valueSpan.Length; } JsonReaderHelper.ValidateUtf8(utf8Destination.Slice(0, bytesWritten)); return bytesWritten; } [System.Runtime.CompilerServices.IsReadOnly] public int CopyString(Span<char> destination) { JsonTokenType tokenType = _tokenType; if ((tokenType != JsonTokenType.PropertyName && tokenType != JsonTokenType.String) || 1 == 0) ThrowHelper.ThrowInvalidOperationException_ExpectedString(_tokenType); return CopyValue(destination); } [System.Runtime.CompilerServices.IsReadOnly] internal unsafe int CopyValue(Span<char> destination) { byte[] array = null; Span<byte> span; ReadOnlySpan<byte> utf8Unescaped; if (ValueIsEscaped) { int valueLength = ValueLength; span = ((valueLength > 256) ? ((Span<byte>)(array = ArrayPool<byte>.Shared.Rent(valueLength))) : new Span<byte>(stackalloc byte[256], 256)); Span<byte> destination2 = span; TryCopyEscapedString(destination2, out int bytesWritten); utf8Unescaped = destination2.Slice(0, bytesWritten); } else if (HasValueSequence) { ReadOnlySequence<byte> source = ValueSequence; int valueLength = checked((int)source.Length); span = ((valueLength > 256) ? ((Span<byte>)(array = ArrayPool<byte>.Shared.Rent(valueLength))) : new Span<byte>(stackalloc byte[256], 256)); Span<byte> destination3 = span; ref source.CopyTo(destination3); utf8Unescaped = destination3.Slice(0, valueLength); } else { utf8Unescaped = ValueSpan; } int result = JsonReaderHelper.TranscodeHelper(utf8Unescaped, destination); if (array != null) { span = new Span<byte>(array, 0, utf8Unescaped.Length); span.Clear(); ArrayPool<byte>.Shared.Return(array, false); } return result; } [System.Runtime.CompilerServices.IsReadOnly] private unsafe bool TryCopyEscapedString(Span<byte> destination, out int bytesWritten) { byte[] array = null; Span<byte> span; ReadOnlySpan<byte> source2; if (HasValueSequence) { ReadOnlySequence<byte> source = ValueSequence; int num = checked((int)source.Length); span = ((num > 256) ? ((Span<byte>)(array = ArrayPool<byte>.Shared.Rent(num))) : new Span<byte>(stackalloc byte[256], 256)); Span<byte> destination2 = span; ref source.CopyTo(destination2); source2 = destination2.Slice(0, num); } else source2 = ValueSpan; bool result = JsonReaderHelper.TryUnescape(source2, destination, out bytesWritten); if (array != null) { span = new Span<byte>(array, 0, source2.Length); span.Clear(); ArrayPool<byte>.Shared.Return(array, false); } return result; } [System.Runtime.CompilerServices.NullableContext(1)] public string GetComment() { if (TokenType != JsonTokenType.Comment) ThrowHelper.ThrowInvalidOperationException_ExpectedComment(TokenType); ReadOnlySpan<byte> utf8Unescaped; if (!HasValueSequence) utf8Unescaped = ValueSpan; else { ReadOnlySequence<byte> sequence = ValueSequence; utf8Unescaped = ref sequence.ToArray(); } return JsonReaderHelper.TranscodeHelper(utf8Unescaped); } public bool GetBoolean() { switch (TokenType) { case JsonTokenType.True: return true; default: ThrowHelper.ThrowInvalidOperationException_ExpectedBoolean(TokenType); break; case JsonTokenType.False: break; } return false; } [System.Runtime.CompilerServices.NullableContext(1)] public byte[] GetBytesFromBase64() { if (!TryGetBytesFromBase64(out byte[] value)) ThrowHelper.ThrowFormatException(DataType.Base64String); return value; } public byte GetByte() { if (!TryGetByte(out byte value)) ThrowHelper.ThrowFormatException(NumericType.Byte); return value; } internal byte GetByteWithQuotes() { ReadOnlySpan<byte> unescapedSpan = GetUnescapedSpan(); if (!TryGetByteCore(out byte value, unescapedSpan)) ThrowHelper.ThrowFormatException(NumericType.Byte); return value; } [CLSCompliant(false)] public sbyte GetSByte() { if (!TryGetSByte(out sbyte value)) ThrowHelper.ThrowFormatException(NumericType.SByte); return value; } internal sbyte GetSByteWithQuotes() { ReadOnlySpan<byte> unescapedSpan = GetUnescapedSpan(); if (!TryGetSByteCore(out sbyte value, unescapedSpan)) ThrowHelper.ThrowFormatException(NumericType.SByte); return value; } public short GetInt16() { if (!TryGetInt16(out short value)) ThrowHelper.ThrowFormatException(NumericType.Int16); return value; } internal short GetInt16WithQuotes() { ReadOnlySpan<byte> unescapedSpan = GetUnescapedSpan(); if (!TryGetInt16Core(out short value, unescapedSpan)) ThrowHelper.ThrowFormatException(NumericType.Int16); return value; } public int GetInt32() { if (!TryGetInt32(out int value)) ThrowHelper.ThrowFormatException(NumericType.Int32); return value; } internal int GetInt32WithQuotes() { ReadOnlySpan<byte> unescapedSpan = GetUnescapedSpan(); if (!TryGetInt32Core(out int value, unescapedSpan)) ThrowHelper.ThrowFormatException(NumericType.Int32); return value; } public long GetInt64() { if (!TryGetInt64(out long value)) ThrowHelper.ThrowFormatException(NumericType.Int64); return value; } internal long GetInt64WithQuotes() { ReadOnlySpan<byte> unescapedSpan = GetUnescapedSpan(); if (!TryGetInt64Core(out long value, unescapedSpan)) ThrowHelper.ThrowFormatException(NumericType.Int64); return value; } [CLSCompliant(false)] public ushort GetUInt16() { if (!TryGetUInt16(out ushort value)) ThrowHelper.ThrowFormatException(NumericType.UInt16); return value; } internal ushort GetUInt16WithQuotes() { ReadOnlySpan<byte> unescapedSpan = GetUnescapedSpan(); if (!TryGetUInt16Core(out ushort value, unescapedSpan)) ThrowHelper.ThrowFormatException(NumericType.UInt16); return value; } [CLSCompliant(false)] public uint GetUInt32() { if (!TryGetUInt32(out uint value)) ThrowHelper.ThrowFormatException(NumericType.UInt32); return value; } internal uint GetUInt32WithQuotes() { ReadOnlySpan<byte> unescapedSpan = GetUnescapedSpan(); if (!TryGetUInt32Core(out uint value, unescapedSpan)) ThrowHelper.ThrowFormatException(NumericType.UInt32); return value; } [CLSCompliant(false)] public ulong GetUInt64() { if (!TryGetUInt64(out ulong value)) ThrowHelper.ThrowFormatException(NumericType.UInt64); return value; } internal ulong GetUInt64WithQuotes() { ReadOnlySpan<byte> unescapedSpan = GetUnescapedSpan(); if (!TryGetUInt64Core(out ulong value, unescapedSpan)) ThrowHelper.ThrowFormatException(NumericType.UInt64); return value; } public float GetSingle() { if (!TryGetSingle(out float value)) ThrowHelper.ThrowFormatException(NumericType.Single); return value; } internal float GetSingleWithQuotes() { ReadOnlySpan<byte> unescapedSpan = GetUnescapedSpan(); if (JsonReaderHelper.TryGetFloatingPointConstant(unescapedSpan, out float value)) return value; if (!Utf8Parser.TryParse(unescapedSpan, out value, out int bytesConsumed, '') || unescapedSpan.Length != bytesConsumed || !JsonHelpers.IsFinite(value)) ThrowHelper.ThrowFormatException(NumericType.Single); return value; } internal float GetSingleFloatingPointConstant() { if (!JsonReaderHelper.TryGetFloatingPointConstant(GetUnescapedSpan(), out float value)) ThrowHelper.ThrowFormatException(NumericType.Single); return value; } public double GetDouble() { if (!TryGetDouble(out double value)) ThrowHelper.ThrowFormatException(NumericType.Double); return value; } internal double GetDoubleWithQuotes() { ReadOnlySpan<byte> unescapedSpan = GetUnescapedSpan(); if (JsonReaderHelper.TryGetFloatingPointConstant(unescapedSpan, out double value)) return value; if (!Utf8Parser.TryParse(unescapedSpan, out value, out int bytesConsumed, '') || unescapedSpan.Length != bytesConsumed || !JsonHelpers.IsFinite(value)) ThrowHelper.ThrowFormatException(NumericType.Double); return value; } internal double GetDoubleFloatingPointConstant() { if (!JsonReaderHelper.TryGetFloatingPointConstant(GetUnescapedSpan(), out double value)) ThrowHelper.ThrowFormatException(NumericType.Double); return value; } public decimal GetDecimal() { if (!TryGetDecimal(out decimal value)) ThrowHelper.ThrowFormatException(NumericType.Decimal); return value; } internal decimal GetDecimalWithQuotes() { ReadOnlySpan<byte> unescapedSpan = GetUnescapedSpan(); if (!TryGetDecimalCore(out decimal value, unescapedSpan)) ThrowHelper.ThrowFormatException(NumericType.Decimal); return value; } public DateTime GetDateTime() { if (!TryGetDateTime(out DateTime value)) ThrowHelper.ThrowFormatException(DataType.DateTime); return value; } internal DateTime GetDateTimeNoValidation() { if (!TryGetDateTimeCore(out DateTime value)) ThrowHelper.ThrowFormatException(DataType.DateTime); return value; } public DateTimeOffset GetDateTimeOffset() { if (!TryGetDateTimeOffset(out DateTimeOffset value)) ThrowHelper.ThrowFormatException(DataType.DateTimeOffset); return value; } internal DateTimeOffset GetDateTimeOffsetNoValidation() { if (!TryGetDateTimeOffsetCore(out DateTimeOffset value)) ThrowHelper.ThrowFormatException(DataType.DateTimeOffset); return value; } public Guid GetGuid() { if (!TryGetGuid(out Guid value)) ThrowHelper.ThrowFormatException(DataType.Guid); return value; } internal Guid GetGuidNoValidation() { if (!TryGetGuidCore(out Guid value)) ThrowHelper.ThrowFormatException(DataType.Guid); return value; } [System.Runtime.CompilerServices.NullableContext(2)] public bool TryGetBytesFromBase64([System.Diagnostics.CodeAnalysis.NotNullWhen(true)] out byte[] value) { if (TokenType != JsonTokenType.String) ThrowHelper.ThrowInvalidOperationException_ExpectedString(TokenType); ReadOnlySpan<byte> readOnlySpan; if (!HasValueSequence) readOnlySpan = ValueSpan; else { ReadOnlySequence<byte> sequence = ValueSequence; readOnlySpan = ref sequence.ToArray(); } ReadOnlySpan<byte> readOnlySpan2 = readOnlySpan; if (ValueIsEscaped) return JsonReaderHelper.TryGetUnescapedBase64Bytes(readOnlySpan2, out value); return JsonReaderHelper.TryDecodeBase64(readOnlySpan2, out value); } public bool TryGetByte(out byte value) { if (TokenType != JsonTokenType.Number) ThrowHelper.ThrowInvalidOperationException_ExpectedNumber(TokenType); ReadOnlySpan<byte> readOnlySpan; if (!HasValueSequence) readOnlySpan = ValueSpan; else { ReadOnlySequence<byte> sequence = ValueSequence; readOnlySpan = ref sequence.ToArray(); } ReadOnlySpan<byte> span = readOnlySpan; return TryGetByteCore(out value, span); } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static bool TryGetByteCore(out byte value, ReadOnlySpan<byte> span) { if (Utf8Parser.TryParse(span, out byte value2, out int bytesConsumed, '') && span.Length == bytesConsumed) { value = value2; return true; } value = 0; return false; } [CLSCompliant(false)] public bool TryGetSByte(out sbyte value) { if (TokenType != JsonTokenType.Number) ThrowHelper.ThrowInvalidOperationException_ExpectedNumber(TokenType); ReadOnlySpan<byte> readOnlySpan; if (!HasValueSequence) readOnlySpan = ValueSpan; else { ReadOnlySequence<byte> sequence = ValueSequence; readOnlySpan = ref sequence.ToArray(); } ReadOnlySpan<byte> span = readOnlySpan; return TryGetSByteCore(out value, span); } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static bool TryGetSByteCore(out sbyte value, ReadOnlySpan<byte> span) { if (Utf8Parser.TryParse(span, out sbyte value2, out int bytesConsumed, '') && span.Length == bytesConsumed) { value = value2; return true; } value = 0; return false; } public bool TryGetInt16(out short value) { if (TokenType != JsonTokenType.Number) ThrowHelper.ThrowInvalidOperationException_ExpectedNumber(TokenType); ReadOnlySpan<byte> readOnlySpan; if (!HasValueSequence) readOnlySpan = ValueSpan; else { ReadOnlySequence<byte> sequence = ValueSequence; readOnlySpan = ref sequence.ToArray(); } ReadOnlySpan<byte> span = readOnlySpan; return TryGetInt16Core(out value, span); } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static bool TryGetInt16Core(out short value, ReadOnlySpan<byte> span) { if (Utf8Parser.TryParse(span, out short value2, out int bytesConsumed, '') && span.Length == bytesConsumed) { value = value2; return true; } value = 0; return false; } public bool TryGetInt32(out int value) { if (TokenType != JsonTokenType.Number) ThrowHelper.ThrowInvalidOperationException_ExpectedNumber(TokenType); ReadOnlySpan<byte> readOnlySpan; if (!HasValueSequence) readOnlySpan = ValueSpan; else { ReadOnlySequence<byte> sequence = ValueSequence; readOnlySpan = ref sequence.ToArray(); } ReadOnlySpan<byte> span = readOnlySpan; return TryGetInt32Core(out value, span); } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static bool TryGetInt32Core(out int value, ReadOnlySpan<byte> span) { if (Utf8Parser.TryParse(span, out int value2, out int bytesConsumed, '') && span.Length == bytesConsumed) { value = value2; return true; } value = 0; return false; } public bool TryGetInt64(out long value) { if (TokenType != JsonTokenType.Number) ThrowHelper.ThrowInvalidOperationException_ExpectedNumber(TokenType); ReadOnlySpan<byte> readOnlySpan; if (!HasValueSequence) readOnlySpan = ValueSpan; else { ReadOnlySequence<byte> sequence = ValueSequence; readOnlySpan = ref sequence.ToArray(); } ReadOnlySpan<byte> span = readOnlySpan; return TryGetInt64Core(out value, span); } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static bool TryGetInt64Core(out long value, ReadOnlySpan<byte> span) { if (Utf8Parser.TryParse(span, out long value2, out int bytesConsumed, '') && span.Length == bytesConsumed) { value = value2; return true; } value = 0; return false; } [CLSCompliant(false)] public bool TryGetUInt16(out ushort value) { if (TokenType != JsonTokenType.Number) ThrowHelper.ThrowInvalidOperationException_ExpectedNumber(TokenType); ReadOnlySpan<byte> readOnlySpan; if (!HasValueSequence) readOnlySpan = ValueSpan; else { ReadOnlySequence<byte> sequence = ValueSequence; readOnlySpan = ref sequence.ToArray(); } ReadOnlySpan<byte> span = readOnlySpan; return TryGetUInt16Core(out value, span); } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static bool TryGetUInt16Core(out ushort value, ReadOnlySpan<byte> span) { if (Utf8Parser.TryParse(span, out ushort value2, out int bytesConsumed, '') && span.Length == bytesConsumed) { value = value2; return true; } value = 0; return false; } [CLSCompliant(false)] public bool TryGetUInt32(out uint value) { if (TokenType != JsonTokenType.Number) ThrowHelper.ThrowInvalidOperationException_ExpectedNumber(TokenType); ReadOnlySpan<byte> readOnlySpan; if (!HasValueSequence) readOnlySpan = ValueSpan; else { ReadOnlySequence<byte> sequence = ValueSequence; readOnlySpan = ref sequence.ToArray(); } ReadOnlySpan<byte> span = readOnlySpan; return TryGetUInt32Core(out value, span); } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static bool TryGetUInt32Core(out uint value, ReadOnlySpan<byte> span) { if (Utf8Parser.TryParse(span, out uint value2, out int bytesConsumed, '') && span.Length == bytesConsumed) { value = value2; return true; } value = 0; return false; } [CLSCompliant(false)] public bool TryGetUInt64(out ulong value) { if (TokenType != JsonTokenType.Number) ThrowHelper.ThrowInvalidOperationException_ExpectedNumber(TokenType); ReadOnlySpan<byte> readOnlySpan; if (!HasValueSequence) readOnlySpan = ValueSpan; else { ReadOnlySequence<byte> sequence = ValueSequence; readOnlySpan = ref sequence.ToArray(); } ReadOnlySpan<byte> span = readOnlySpan; return TryGetUInt64Core(out value, span); } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static bool TryGetUInt64Core(out ulong value, ReadOnlySpan<byte> span) { if (Utf8Parser.TryParse(span, out ulong value2, out int bytesConsumed, '') && span.Length == bytesConsumed) { value = value2; return true; } value = 0; return false; } public bool TryGetSingle(out float value) { if (TokenType != JsonTokenType.Number) ThrowHelper.ThrowInvalidOperationException_ExpectedNumber(TokenType); ReadOnlySpan<byte> readOnlySpan; if (!HasValueSequence) readOnlySpan = ValueSpan; else { ReadOnlySequence<byte> sequence = ValueSequence; readOnlySpan = ref sequence.ToArray(); } ReadOnlySpan<byte> source = readOnlySpan; if (Utf8Parser.TryParse(source, out float value2, out int bytesConsumed, '') && source.Length == bytesConsumed) { value = value2; return true; } value = 0; return false; } public bool TryGetDouble(out double value) { if (TokenType != JsonTokenType.Number) ThrowHelper.ThrowInvalidOperationException_ExpectedNumber(TokenType); ReadOnlySpan<byte> readOnlySpan; if (!HasValueSequence) readOnlySpan = ValueSpan; else { ReadOnlySequence<byte> sequence = ValueSequence; readOnlySpan = ref sequence.ToArray(); } ReadOnlySpan<byte> source = readOnlySpan; if (Utf8Parser.TryParse(source, out double value2, out int bytesConsumed, '') && source.Length == bytesConsumed) { value = value2; return true; } value = 0; return false; } public bool TryGetDecimal(out decimal value) { if (TokenType != JsonTokenType.Number) ThrowHelper.ThrowInvalidOperationException_ExpectedNumber(TokenType); ReadOnlySpan<byte> readOnlySpan; if (!HasValueSequence) readOnlySpan = ValueSpan; else { ReadOnlySequence<byte> sequence = ValueSequence; readOnlySpan = ref sequence.ToArray(); } ReadOnlySpan<byte> span = readOnlySpan; return TryGetDecimalCore(out value, span); } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static bool TryGetDecimalCore(out decimal value, ReadOnlySpan<byte> span) { if (Utf8Parser.TryParse(span, out decimal value2, out int bytesConsumed, '') && span.Length == bytesConsumed) { value = value2; return true; } value = default(decimal); return false; } public bool TryGetDateTime(out DateTime value) { if (TokenType != JsonTokenType.String) ThrowHelper.ThrowInvalidOperationException_ExpectedString(TokenType); return TryGetDateTimeCore(out value); } internal unsafe bool TryGetDateTimeCore(out DateTime value) { ReadOnlySpan<byte> source2; if (HasValueSequence) { ReadOnlySequence<byte> source = ValueSequence; long length = source.Length; if (!JsonHelpers.IsInRangeInclusive(length, 10, 252)) { value = default(DateTime); return false; } Span<byte> destination = new Span<byte>(stackalloc byte[252], 252); source = ValueSequence; ref source.CopyTo(destination); source2 = destination.Slice(0, (int)length); } else { if (!JsonHelpers.IsInRangeInclusive(ValueSpan.Length, 10, 252)) { value = default(DateTime); return false; } source2 = ValueSpan; } if (ValueIsEscaped) return JsonReaderHelper.TryGetEscapedDateTime(source2, out value); if (JsonHelpers.TryParseAsISO(source2, out DateTime value2)) { value = value2; return true; } value = default(DateTime); return false; } public bool TryGetDateTimeOffset(out DateTimeOffset value) { if (TokenType != JsonTokenType.String) ThrowHelper.ThrowInvalidOperationException_ExpectedString(TokenType); return TryGetDateTimeOffsetCore(out value); } internal unsafe bool TryGetDateTimeOffsetCore(out DateTimeOffset value) { ReadOnlySpan<byte> source2; if (HasValueSequence) { ReadOnlySequence<byte> source = ValueSequence; long length = source.Length; if (!JsonHelpers.IsInRangeInclusive(length, 10, 252)) { value = default(DateTimeOffset); return false; } Span<byte> destination = new Span<byte>(stackalloc byte[252], 252); source = ValueSequence; ref source.CopyTo(destination); source2 = destination.Slice(0, (int)length); } else { if (!JsonHelpers.IsInRangeInclusive(ValueSpan.Length, 10, 252)) { value = default(DateTimeOffset); return false; } source2 = ValueSpan; } if (ValueIsEscaped) return JsonReaderHelper.TryGetEscapedDateTimeOffset(source2, out value); if (JsonHelpers.TryParseAsISO(source2, out DateTimeOffset value2)) { value = value2; return true; } value = default(DateTimeOffset); return false; } public bool TryGetGuid(out Guid value) { if (TokenType != JsonTokenType.String) ThrowHelper.ThrowInvalidOperationException_ExpectedString(TokenType); return TryGetGuidCore(out value); } internal unsafe bool TryGetGuidCore(out Guid value) { ReadOnlySpan<byte> source2; if (HasValueSequence) { ReadOnlySequence<byte> source = ValueSequence; long length = source.Length; if (length > 216) { value = default(Guid); return false; } Span<byte> destination = new Span<byte>(stackalloc byte[216], 216); source = ValueSequence; ref source.CopyTo(destination); source2 = destination.Slice(0, (int)length); } else { if (ValueSpan.Length > 216) { value = default(Guid); return false; } source2 = ValueSpan; } if (ValueIsEscaped) return JsonReaderHelper.TryGetEscapedGuid(source2, out value); if (source2.Length == 36 && Utf8Parser.TryParse(source2, out Guid value2, out int _, 'D')) { value = value2; return true; } value = default(Guid); return false; } } }