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

JsonDocument

public sealed class JsonDocument : IDisposable
Provides a mechanism for examining the structural content of a JSON value without automatically instantiating data values.
using System.Buffers; using System.Buffers.Text; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.IO; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; namespace System.Text.Json { public sealed class JsonDocument : IDisposable { internal readonly struct DbRow { internal const int Size = 12; private readonly int _location; private readonly int _sizeOrLengthUnion; private readonly int _numberOfRowsAndTypeUnion; internal const int UnknownSize = -1; internal int Location => _location; internal int SizeOrLength => _sizeOrLengthUnion & 2147483647; internal bool IsUnknownSize => _sizeOrLengthUnion == -1; internal bool HasComplexChildren => _sizeOrLengthUnion < 0; internal int NumberOfRows => _numberOfRowsAndTypeUnion & 268435455; internal JsonTokenType TokenType => (JsonTokenType)((uint)_numberOfRowsAndTypeUnion >> 28); internal bool IsSimpleValue => (int)TokenType >= 5; internal DbRow(JsonTokenType jsonTokenType, int location, int sizeOrLength) { _location = location; _sizeOrLengthUnion = sizeOrLength; _numberOfRowsAndTypeUnion = (int)((uint)jsonTokenType << 28); } } private struct MetadataDb : IDisposable { private const int SizeOrLengthOffset = 4; private const int NumberOfRowsOffset = 8; private byte[] _data; private bool _convertToAlloc; private bool _isLocked; internal int Length { [System.Runtime.CompilerServices.IsReadOnly] get; private set; } private MetadataDb(byte[] initialDb, bool isLocked, bool convertToAlloc) { _data = initialDb; _isLocked = isLocked; _convertToAlloc = convertToAlloc; Length = 0; } internal MetadataDb(byte[] completeDb) { _data = completeDb; _isLocked = true; _convertToAlloc = false; Length = completeDb.Length; } internal static MetadataDb CreateRented(int payloadLength, bool convertToAlloc) { int num = payloadLength + 12; if (num > 1048576 && num <= 4194304) num = 1048576; return new MetadataDb(ArrayPool<byte>.Shared.Rent(num), false, convertToAlloc); } internal static MetadataDb CreateLocked(int payloadLength) { return new MetadataDb(new byte[payloadLength + 12], true, false); } public void Dispose() { byte[] array = Interlocked.Exchange(ref _data, null); if (array != null) { ArrayPool<byte>.Shared.Return(array, false); Length = 0; } } internal void CompleteAllocations() { if (!_isLocked) { if (_convertToAlloc) { byte[] data = _data; _data = _data.AsSpan(0, Length).ToArray(); _isLocked = true; _convertToAlloc = false; ArrayPool<byte>.Shared.Return(data, false); } else if (Length <= _data.Length / 2) { byte[] array = ArrayPool<byte>.Shared.Rent(Length); byte[] array2 = array; if (array.Length < _data.Length) { Buffer.BlockCopy(_data, 0, array, 0, Length); array2 = _data; _data = array; } ArrayPool<byte>.Shared.Return(array2, false); } } } internal void Append(JsonTokenType tokenType, int startLocation, int length) { if (Length >= _data.Length - 12) Enlarge(); DbRow value = new DbRow(tokenType, startLocation, length); MemoryMarshal.Write(_data.AsSpan(Length), ref value); Length += 12; } private void Enlarge() { byte[] data = _data; int num = data.Length * 2; if ((uint)num > 2147483591) num = 2147483591; if (num == data.Length) num = 2147483647; _data = ArrayPool<byte>.Shared.Rent(num); Buffer.BlockCopy(data, 0, _data, 0, data.Length); ArrayPool<byte>.Shared.Return(data, false); } [Conditional("DEBUG")] private void AssertValidIndex(int index) { } internal void SetLength(int index, int length) { MemoryMarshal.Write(_data.AsSpan(index + 4), ref length); } internal void SetNumberOfRows(int index, int numberOfRows) { Span<byte> span = _data.AsSpan(index + 8); int value = (MemoryMarshal.Read<int>(span) & -268435456) | numberOfRows; MemoryMarshal.Write(span, ref value); } internal void SetHasComplexChildren(int index) { Span<byte> span = _data.AsSpan(index + 4); int value = MemoryMarshal.Read<int>(span) | -2147483648; MemoryMarshal.Write(span, ref value); } internal int FindIndexOfFirstUnsetSizeOrLength(JsonTokenType lookupType) { return FindOpenElement(lookupType); } private int FindOpenElement(JsonTokenType lookupType) { Span<byte> span = _data.AsSpan(0, Length); for (int num = Length - 12; num >= 0; num -= 12) { DbRow dbRow = MemoryMarshal.Read<DbRow>(span.Slice(num)); if (dbRow.IsUnknownSize && dbRow.TokenType == lookupType) return num; } return -1; } internal DbRow Get(int index) { return MemoryMarshal.Read<DbRow>(_data.AsSpan(index)); } internal JsonTokenType GetJsonTokenType(int index) { return (JsonTokenType)(MemoryMarshal.Read<uint>(_data.AsSpan(index + 8)) >> 28); } internal MetadataDb CopySegment(int startIndex, int endIndex) { DbRow dbRow = Get(startIndex); int num = endIndex - startIndex; byte[] array = new byte[num]; _data.AsSpan(startIndex, num).CopyTo(array); Span<int> span = MemoryMarshal.Cast<byte, int>(array); int num2 = span[0]; if (dbRow.TokenType == JsonTokenType.String) num2--; for (int num3 = (num - 12) / 4; num3 >= 0; num3 -= 3) { span[num3] -= num2; } return new MetadataDb(array); } } private readonly struct StackRow { internal const int Size = 8; internal readonly int SizeOrLength; internal readonly int NumberOfRows; internal StackRow(int sizeOrLength = 0, int numberOfRows = -1) { SizeOrLength = sizeOrLength; NumberOfRows = numberOfRows; } } private struct StackRowStack : IDisposable { private byte[] _rentedBuffer; private int _topOfStack; public StackRowStack(int initialSize) { _rentedBuffer = ArrayPool<byte>.Shared.Rent(initialSize); _topOfStack = _rentedBuffer.Length; } public void Dispose() { byte[] rentedBuffer = _rentedBuffer; _rentedBuffer = null; _topOfStack = 0; if (rentedBuffer != null) ArrayPool<byte>.Shared.Return(rentedBuffer, false); } internal void Push(StackRow row) { if (_topOfStack < 8) Enlarge(); _topOfStack -= 8; MemoryMarshal.Write(_rentedBuffer.AsSpan(_topOfStack), ref row); } internal StackRow Pop() { StackRow result = MemoryMarshal.Read<StackRow>(_rentedBuffer.AsSpan(_topOfStack)); _topOfStack += 8; return result; } private void Enlarge() { byte[] rentedBuffer = _rentedBuffer; _rentedBuffer = ArrayPool<byte>.Shared.Rent(rentedBuffer.Length * 2); Buffer.BlockCopy(rentedBuffer, _topOfStack, _rentedBuffer, _rentedBuffer.Length - rentedBuffer.Length + _topOfStack, rentedBuffer.Length - _topOfStack); _topOfStack += _rentedBuffer.Length - rentedBuffer.Length; ArrayPool<byte>.Shared.Return(rentedBuffer, false); } } private ReadOnlyMemory<byte> _utf8Json; private MetadataDb _parsedData; private byte[] _extraRentedArrayPoolBytes; private PooledByteBufferWriter _extraPooledByteBufferWriter; private static JsonDocument s_nullLiteral; private static JsonDocument s_trueLiteral; private static JsonDocument s_falseLiteral; private const int UnseekableStreamInitialRentSize = 4096; internal bool IsDisposable { get; } public JsonElement RootElement => new JsonElement(this, 0); private JsonDocument(ReadOnlyMemory<byte> utf8Json, MetadataDb parsedData, byte[] extraRentedArrayPoolBytes = null, PooledByteBufferWriter extraPooledByteBufferWriter = null, bool isDisposable = true) { _utf8Json = utf8Json; _parsedData = parsedData; _extraRentedArrayPoolBytes = extraRentedArrayPoolBytes; _extraPooledByteBufferWriter = extraPooledByteBufferWriter; IsDisposable = isDisposable; } public void Dispose() { int length = _utf8Json.Length; if (length != 0 && IsDisposable) { _parsedData.Dispose(); _utf8Json = ReadOnlyMemory<byte>.Empty; if (_extraRentedArrayPoolBytes != null) { byte[] array = Interlocked.Exchange(ref _extraRentedArrayPoolBytes, null); if (array != null) { array.AsSpan(0, length).Clear(); ArrayPool<byte>.Shared.Return(array, false); } } else if (_extraPooledByteBufferWriter != null) { Interlocked.Exchange(ref _extraPooledByteBufferWriter, null)?.Dispose(); } } } [System.Runtime.CompilerServices.NullableContext(1)] public void WriteTo(Utf8JsonWriter writer) { if (writer == null) ThrowHelper.ThrowArgumentNullException("writer"); RootElement.WriteTo(writer); } internal JsonTokenType GetJsonTokenType(int index) { CheckNotDisposed(); return _parsedData.GetJsonTokenType(index); } internal bool ValueIsEscaped(int index, bool isPropertyName) { CheckNotDisposed(); int index2 = isPropertyName ? (index - 12) : index; return _parsedData.Get(index2).HasComplexChildren; } internal int GetArrayLength(int index) { CheckNotDisposed(); DbRow dbRow = _parsedData.Get(index); CheckExpectedType(JsonTokenType.StartArray, dbRow.TokenType); return dbRow.SizeOrLength; } internal int GetPropertyCount(int index) { CheckNotDisposed(); DbRow dbRow = _parsedData.Get(index); CheckExpectedType(JsonTokenType.StartObject, dbRow.TokenType); return dbRow.SizeOrLength; } internal JsonElement GetArrayIndexElement(int currentIndex, int arrayIndex) { CheckNotDisposed(); DbRow dbRow = _parsedData.Get(currentIndex); CheckExpectedType(JsonTokenType.StartArray, dbRow.TokenType); int sizeOrLength = dbRow.SizeOrLength; if ((uint)arrayIndex >= (uint)sizeOrLength) throw new IndexOutOfRangeException(); if (!dbRow.HasComplexChildren) return new JsonElement(this, currentIndex + (arrayIndex + 1) * 12); int num = 0; for (int i = currentIndex + 12; i < _parsedData.Length; i += 12) { if (arrayIndex == num) return new JsonElement(this, i); dbRow = _parsedData.Get(i); if (!dbRow.IsSimpleValue) i += 12 * dbRow.NumberOfRows; num++; } throw new IndexOutOfRangeException(); } internal int GetEndIndex(int index, bool includeEndElement) { CheckNotDisposed(); DbRow dbRow = _parsedData.Get(index); if (dbRow.IsSimpleValue) return index + 12; int num = index + 12 * dbRow.NumberOfRows; if (includeEndElement) num += 12; return num; } internal ReadOnlyMemory<byte> GetRootRawValue() { return GetRawValue(0, true); } internal ReadOnlyMemory<byte> GetRawValue(int index, bool includeQuotes) { CheckNotDisposed(); DbRow dbRow = _parsedData.Get(index); if (dbRow.IsSimpleValue) { if (includeQuotes && dbRow.TokenType == JsonTokenType.String) return _utf8Json.Slice(dbRow.Location - 1, dbRow.SizeOrLength + 2); return _utf8Json.Slice(dbRow.Location, dbRow.SizeOrLength); } int endIndex = GetEndIndex(index, false); int location = dbRow.Location; dbRow = _parsedData.Get(endIndex); return _utf8Json.Slice(location, dbRow.Location - location + dbRow.SizeOrLength); } private ReadOnlyMemory<byte> GetPropertyRawValue(int valueIndex) { CheckNotDisposed(); DbRow dbRow = _parsedData.Get(valueIndex - 12); int num = dbRow.Location - 1; dbRow = _parsedData.Get(valueIndex); int num2; if (dbRow.IsSimpleValue) { num2 = dbRow.Location + dbRow.SizeOrLength; if (dbRow.TokenType == JsonTokenType.String) num2++; return _utf8Json.Slice(num, num2 - num); } int endIndex = GetEndIndex(valueIndex, false); dbRow = _parsedData.Get(endIndex); num2 = dbRow.Location + dbRow.SizeOrLength; return _utf8Json.Slice(num, num2 - num); } internal string GetString(int index, JsonTokenType expectedType) { CheckNotDisposed(); DbRow dbRow = _parsedData.Get(index); JsonTokenType tokenType = dbRow.TokenType; if (tokenType == JsonTokenType.Null) return null; CheckExpectedType(expectedType, tokenType); ReadOnlySpan<byte> readOnlySpan = _utf8Json.Span.Slice(dbRow.Location, dbRow.SizeOrLength); if (!dbRow.HasComplexChildren) return JsonReaderHelper.TranscodeHelper(readOnlySpan); return JsonReaderHelper.GetUnescapedString(readOnlySpan); } internal unsafe bool TextEquals(int index, ReadOnlySpan<char> otherText, bool isPropertyName) { CheckNotDisposed(); byte[] array = null; int num = checked(otherText.Length * 3); Span<byte> span = (num > 256) ? ((Span<byte>)(array = ArrayPool<byte>.Shared.Rent(num))) : new Span<byte>(stackalloc byte[256], 256); Span<byte> destination = span; int written; bool result = JsonWriterHelper.ToUtf8(otherText, destination, out written) != OperationStatus.InvalidData && TextEquals(index, destination.Slice(0, written), isPropertyName, true); if (array != null) { span = destination.Slice(0, written); span.Clear(); ArrayPool<byte>.Shared.Return(array, false); } return result; } internal bool TextEquals(int index, ReadOnlySpan<byte> otherUtf8Text, bool isPropertyName, bool shouldUnescape) { CheckNotDisposed(); int index2 = isPropertyName ? (index - 12) : index; DbRow dbRow = _parsedData.Get(index2); CheckExpectedType(isPropertyName ? JsonTokenType.PropertyName : JsonTokenType.String, dbRow.TokenType); ReadOnlySpan<byte> span = _utf8Json.Span.Slice(dbRow.Location, dbRow.SizeOrLength); if (otherUtf8Text.Length > span.Length || (!shouldUnescape && otherUtf8Text.Length != span.Length)) return false; if (dbRow.HasComplexChildren & shouldUnescape) { if (otherUtf8Text.Length < span.Length / 6) return false; int num = span.IndexOf<byte>(92); if (!otherUtf8Text.StartsWith(span.Slice(0, num))) return false; return JsonReaderHelper.UnescapeAndCompare(span.Slice(num), otherUtf8Text.Slice(num)); } return span.SequenceEqual(otherUtf8Text); } internal string GetNameOfPropertyValue(int index) { return GetString(index - 12, JsonTokenType.PropertyName); } internal ReadOnlySpan<byte> GetPropertyNameRaw(int index) { CheckNotDisposed(); DbRow dbRow = _parsedData.Get(index - 12); return _utf8Json.Span.Slice(dbRow.Location, dbRow.SizeOrLength); } internal bool TryGetValue(int index, [System.Diagnostics.CodeAnalysis.NotNullWhen(true)] out byte[] value) { CheckNotDisposed(); DbRow dbRow = _parsedData.Get(index); CheckExpectedType(JsonTokenType.String, dbRow.TokenType); ReadOnlySpan<byte> readOnlySpan = _utf8Json.Span.Slice(dbRow.Location, dbRow.SizeOrLength); if (dbRow.HasComplexChildren) return JsonReaderHelper.TryGetUnescapedBase64Bytes(readOnlySpan, out value); return JsonReaderHelper.TryDecodeBase64(readOnlySpan, out value); } internal bool TryGetValue(int index, out sbyte value) { CheckNotDisposed(); DbRow dbRow = _parsedData.Get(index); CheckExpectedType(JsonTokenType.Number, dbRow.TokenType); ReadOnlySpan<byte> source = _utf8Json.Span.Slice(dbRow.Location, dbRow.SizeOrLength); if (Utf8Parser.TryParse(source, out sbyte value2, out int bytesConsumed, '') && bytesConsumed == source.Length) { value = value2; return true; } value = 0; return false; } internal bool TryGetValue(int index, out byte value) { CheckNotDisposed(); DbRow dbRow = _parsedData.Get(index); CheckExpectedType(JsonTokenType.Number, dbRow.TokenType); ReadOnlySpan<byte> source = _utf8Json.Span.Slice(dbRow.Location, dbRow.SizeOrLength); if (Utf8Parser.TryParse(source, out byte value2, out int bytesConsumed, '') && bytesConsumed == source.Length) { value = value2; return true; } value = 0; return false; } internal bool TryGetValue(int index, out short value) { CheckNotDisposed(); DbRow dbRow = _parsedData.Get(index); CheckExpectedType(JsonTokenType.Number, dbRow.TokenType); ReadOnlySpan<byte> source = _utf8Json.Span.Slice(dbRow.Location, dbRow.SizeOrLength); if (Utf8Parser.TryParse(source, out short value2, out int bytesConsumed, '') && bytesConsumed == source.Length) { value = value2; return true; } value = 0; return false; } internal bool TryGetValue(int index, out ushort value) { CheckNotDisposed(); DbRow dbRow = _parsedData.Get(index); CheckExpectedType(JsonTokenType.Number, dbRow.TokenType); ReadOnlySpan<byte> source = _utf8Json.Span.Slice(dbRow.Location, dbRow.SizeOrLength); if (Utf8Parser.TryParse(source, out ushort value2, out int bytesConsumed, '') && bytesConsumed == source.Length) { value = value2; return true; } value = 0; return false; } internal bool TryGetValue(int index, out int value) { CheckNotDisposed(); DbRow dbRow = _parsedData.Get(index); CheckExpectedType(JsonTokenType.Number, dbRow.TokenType); ReadOnlySpan<byte> source = _utf8Json.Span.Slice(dbRow.Location, dbRow.SizeOrLength); if (Utf8Parser.TryParse(source, out int value2, out int bytesConsumed, '') && bytesConsumed == source.Length) { value = value2; return true; } value = 0; return false; } internal bool TryGetValue(int index, out uint value) { CheckNotDisposed(); DbRow dbRow = _parsedData.Get(index); CheckExpectedType(JsonTokenType.Number, dbRow.TokenType); ReadOnlySpan<byte> source = _utf8Json.Span.Slice(dbRow.Location, dbRow.SizeOrLength); if (Utf8Parser.TryParse(source, out uint value2, out int bytesConsumed, '') && bytesConsumed == source.Length) { value = value2; return true; } value = 0; return false; } internal bool TryGetValue(int index, out long value) { CheckNotDisposed(); DbRow dbRow = _parsedData.Get(index); CheckExpectedType(JsonTokenType.Number, dbRow.TokenType); ReadOnlySpan<byte> source = _utf8Json.Span.Slice(dbRow.Location, dbRow.SizeOrLength); if (Utf8Parser.TryParse(source, out long value2, out int bytesConsumed, '') && bytesConsumed == source.Length) { value = value2; return true; } value = 0; return false; } internal bool TryGetValue(int index, out ulong value) { CheckNotDisposed(); DbRow dbRow = _parsedData.Get(index); CheckExpectedType(JsonTokenType.Number, dbRow.TokenType); ReadOnlySpan<byte> source = _utf8Json.Span.Slice(dbRow.Location, dbRow.SizeOrLength); if (Utf8Parser.TryParse(source, out ulong value2, out int bytesConsumed, '') && bytesConsumed == source.Length) { value = value2; return true; } value = 0; return false; } internal bool TryGetValue(int index, out double value) { CheckNotDisposed(); DbRow dbRow = _parsedData.Get(index); CheckExpectedType(JsonTokenType.Number, dbRow.TokenType); ReadOnlySpan<byte> source = _utf8Json.Span.Slice(dbRow.Location, dbRow.SizeOrLength); if (Utf8Parser.TryParse(source, out double value2, out int bytesConsumed, '') && source.Length == bytesConsumed) { value = value2; return true; } value = 0; return false; } internal bool TryGetValue(int index, out float value) { CheckNotDisposed(); DbRow dbRow = _parsedData.Get(index); CheckExpectedType(JsonTokenType.Number, dbRow.TokenType); ReadOnlySpan<byte> source = _utf8Json.Span.Slice(dbRow.Location, dbRow.SizeOrLength); if (Utf8Parser.TryParse(source, out float value2, out int bytesConsumed, '') && source.Length == bytesConsumed) { value = value2; return true; } value = 0; return false; } internal bool TryGetValue(int index, out decimal value) { CheckNotDisposed(); DbRow dbRow = _parsedData.Get(index); CheckExpectedType(JsonTokenType.Number, dbRow.TokenType); ReadOnlySpan<byte> source = _utf8Json.Span.Slice(dbRow.Location, dbRow.SizeOrLength); if (Utf8Parser.TryParse(source, out decimal value2, out int bytesConsumed, '') && source.Length == bytesConsumed) { value = value2; return true; } value = default(decimal); return false; } internal bool TryGetValue(int index, out DateTime value) { CheckNotDisposed(); DbRow dbRow = _parsedData.Get(index); CheckExpectedType(JsonTokenType.String, dbRow.TokenType); ReadOnlySpan<byte> source = _utf8Json.Span.Slice(dbRow.Location, dbRow.SizeOrLength); if (!JsonHelpers.IsValidDateTimeOffsetParseLength(source.Length)) { value = default(DateTime); return false; } if (dbRow.HasComplexChildren) return JsonReaderHelper.TryGetEscapedDateTime(source, out value); if (JsonHelpers.TryParseAsISO(source, out DateTime value2)) { value = value2; return true; } value = default(DateTime); return false; } internal bool TryGetValue(int index, out DateTimeOffset value) { CheckNotDisposed(); DbRow dbRow = _parsedData.Get(index); CheckExpectedType(JsonTokenType.String, dbRow.TokenType); ReadOnlySpan<byte> source = _utf8Json.Span.Slice(dbRow.Location, dbRow.SizeOrLength); if (!JsonHelpers.IsValidDateTimeOffsetParseLength(source.Length)) { value = default(DateTimeOffset); return false; } if (dbRow.HasComplexChildren) return JsonReaderHelper.TryGetEscapedDateTimeOffset(source, out value); if (JsonHelpers.TryParseAsISO(source, out DateTimeOffset value2)) { value = value2; return true; } value = default(DateTimeOffset); return false; } internal bool TryGetValue(int index, out Guid value) { CheckNotDisposed(); DbRow dbRow = _parsedData.Get(index); CheckExpectedType(JsonTokenType.String, dbRow.TokenType); ReadOnlySpan<byte> source = _utf8Json.Span.Slice(dbRow.Location, dbRow.SizeOrLength); if (source.Length > 216) { value = default(Guid); return false; } if (dbRow.HasComplexChildren) return JsonReaderHelper.TryGetEscapedGuid(source, out value); if (source.Length == 36 && Utf8Parser.TryParse(source, out Guid value2, out int _, 'D')) { value = value2; return true; } value = default(Guid); return false; } internal string GetRawValueAsString(int index) { return JsonReaderHelper.TranscodeHelper(GetRawValue(index, true).Span); } internal string GetPropertyRawValueAsString(int valueIndex) { return JsonReaderHelper.TranscodeHelper(GetPropertyRawValue(valueIndex).Span); } internal JsonElement CloneElement(int index) { int endIndex = GetEndIndex(index, true); MetadataDb parsedData = _parsedData.CopySegment(index, endIndex); return new JsonDocument(GetRawValue(index, true).ToArray(), parsedData, null, null, false).RootElement; } internal void WriteElementTo(int index, Utf8JsonWriter writer) { CheckNotDisposed(); DbRow row = _parsedData.Get(index); switch (row.TokenType) { case JsonTokenType.EndObject: case JsonTokenType.EndArray: case JsonTokenType.PropertyName: case JsonTokenType.Comment: break; case JsonTokenType.StartObject: writer.WriteStartObject(); WriteComplexElement(index, writer); break; case JsonTokenType.StartArray: writer.WriteStartArray(); WriteComplexElement(index, writer); break; case JsonTokenType.String: WriteString(ref row, writer); break; case JsonTokenType.Number: writer.WriteNumberValue(_utf8Json.Slice(row.Location, row.SizeOrLength).Span); break; case JsonTokenType.True: writer.WriteBooleanValue(true); break; case JsonTokenType.False: writer.WriteBooleanValue(false); break; case JsonTokenType.Null: writer.WriteNullValue(); break; } } private void WriteComplexElement(int index, Utf8JsonWriter writer) { int endIndex = GetEndIndex(index, true); for (int i = index + 12; i < endIndex; i += 12) { DbRow row = _parsedData.Get(i); switch (row.TokenType) { case JsonTokenType.String: WriteString(ref row, writer); break; case JsonTokenType.Number: writer.WriteNumberValue(_utf8Json.Slice(row.Location, row.SizeOrLength).Span); break; case JsonTokenType.True: writer.WriteBooleanValue(true); break; case JsonTokenType.False: writer.WriteBooleanValue(false); break; case JsonTokenType.Null: writer.WriteNullValue(); break; case JsonTokenType.StartObject: writer.WriteStartObject(); break; case JsonTokenType.EndObject: writer.WriteEndObject(); break; case JsonTokenType.StartArray: writer.WriteStartArray(); break; case JsonTokenType.EndArray: writer.WriteEndArray(); break; case JsonTokenType.PropertyName: WritePropertyName(ref row, writer); break; } } } private ReadOnlySpan<byte> UnescapeString([In] [System.Runtime.CompilerServices.IsReadOnly] ref DbRow row, out ArraySegment<byte> rented) { int location = row.Location; int sizeOrLength = row.SizeOrLength; ReadOnlySpan<byte> span = _utf8Json.Slice(location, sizeOrLength).Span; if (!row.HasComplexChildren) { rented = default(ArraySegment<byte>); return span; } byte[] array = ArrayPool<byte>.Shared.Rent(sizeOrLength); JsonReaderHelper.Unescape(span, array, out int written); rented = new ArraySegment<byte>(array, 0, written); return rented.AsSpan(); } private static void ClearAndReturn(ArraySegment<byte> rented) { if (rented.Array != null) { rented.AsSpan().Clear(); ArrayPool<byte>.Shared.Return(rented.Array, false); } } internal void WritePropertyName(int index, Utf8JsonWriter writer) { CheckNotDisposed(); DbRow row = _parsedData.Get(index - 12); WritePropertyName(ref row, writer); } private void WritePropertyName([In] [System.Runtime.CompilerServices.IsReadOnly] ref DbRow row, Utf8JsonWriter writer) { ArraySegment<byte> rented = default(ArraySegment<byte>); try { writer.WritePropertyName(UnescapeString(ref row, out rented)); } finally { ClearAndReturn(rented); } } private void WriteString([In] [System.Runtime.CompilerServices.IsReadOnly] ref DbRow row, Utf8JsonWriter writer) { ArraySegment<byte> rented = default(ArraySegment<byte>); try { writer.WriteStringValue(UnescapeString(ref row, out rented)); } finally { ClearAndReturn(rented); } } private static void Parse(ReadOnlySpan<byte> utf8JsonSpan, JsonReaderOptions readerOptions, ref MetadataDb database, ref StackRowStack stack) { bool flag = false; int num = 0; int num2 = 0; int num3 = 0; Utf8JsonReader utf8JsonReader = new Utf8JsonReader(utf8JsonSpan, true, new JsonReaderState(readerOptions)); while (utf8JsonReader.Read()) { JsonTokenType tokenType = utf8JsonReader.TokenType; int num4 = (int)utf8JsonReader.TokenStartIndex; ReadOnlySpan<byte> valueSpan; switch (tokenType) { case JsonTokenType.StartObject: { if (flag) num++; num3++; database.Append(tokenType, num4, -1); StackRow row2 = new StackRow(num, num2 + 1); stack.Push(row2); num = 0; num2 = 0; break; } case JsonTokenType.EndObject: { int index = database.FindIndexOfFirstUnsetSizeOrLength(JsonTokenType.StartObject); num3++; num2++; database.SetLength(index, num); int length2 = database.Length; JsonTokenType tokenType6 = tokenType; int startLocation5 = num4; valueSpan = utf8JsonReader.ValueSpan; database.Append(tokenType6, startLocation5, valueSpan.Length); database.SetNumberOfRows(index, num2); database.SetNumberOfRows(length2, num2); StackRow stackRow2 = stack.Pop(); num = stackRow2.SizeOrLength; num2 += stackRow2.NumberOfRows; break; } case JsonTokenType.StartArray: { if (flag) num++; num2++; database.Append(tokenType, num4, -1); StackRow row = new StackRow(num, num3 + 1); stack.Push(row); num = 0; num3 = 0; break; } case JsonTokenType.EndArray: { int num5 = database.FindIndexOfFirstUnsetSizeOrLength(JsonTokenType.StartArray); num3++; num2++; database.SetLength(num5, num); database.SetNumberOfRows(num5, num3); if (num + 1 != num3) database.SetHasComplexChildren(num5); int length = database.Length; JsonTokenType tokenType5 = tokenType; int startLocation4 = num4; valueSpan = utf8JsonReader.ValueSpan; database.Append(tokenType5, startLocation4, valueSpan.Length); database.SetNumberOfRows(length, num3); StackRow stackRow = stack.Pop(); num = stackRow.SizeOrLength; num3 += stackRow.NumberOfRows; break; } case JsonTokenType.PropertyName: { num3++; num2++; num++; JsonTokenType tokenType4 = tokenType; int startLocation3 = num4 + 1; valueSpan = utf8JsonReader.ValueSpan; database.Append(tokenType4, startLocation3, valueSpan.Length); if (utf8JsonReader.ValueIsEscaped) database.SetHasComplexChildren(database.Length - 12); break; } default: num3++; num2++; if (flag) num++; if (tokenType == JsonTokenType.String) { JsonTokenType tokenType2 = tokenType; int startLocation = num4 + 1; valueSpan = utf8JsonReader.ValueSpan; database.Append(tokenType2, startLocation, valueSpan.Length); if (utf8JsonReader.ValueIsEscaped) database.SetHasComplexChildren(database.Length - 12); } else { JsonTokenType tokenType3 = tokenType; int startLocation2 = num4; valueSpan = utf8JsonReader.ValueSpan; database.Append(tokenType3, startLocation2, valueSpan.Length); } break; } flag = utf8JsonReader.IsInArray; } database.CompleteAllocations(); } private void CheckNotDisposed() { if (_utf8Json.IsEmpty) ThrowHelper.ThrowObjectDisposedException_JsonDocument(); } private static void CheckExpectedType(JsonTokenType expected, JsonTokenType actual) { if (expected != actual) ThrowHelper.ThrowJsonElementWrongTypeException(expected, actual); } private static void CheckSupportedOptions(JsonReaderOptions readerOptions, string paramName) { if (readerOptions.CommentHandling == JsonCommentHandling.Allow) throw new ArgumentException(System.SR.JsonDocumentDoesNotSupportComments, paramName); } [return: System.Runtime.CompilerServices.Nullable(1)] public static JsonDocument Parse(ReadOnlyMemory<byte> utf8Json, JsonDocumentOptions options = default(JsonDocumentOptions)) { return Parse(utf8Json, options.GetReaderOptions(), null, null); } [return: System.Runtime.CompilerServices.Nullable(1)] public static JsonDocument Parse(ReadOnlySequence<byte> utf8Json, JsonDocumentOptions options = default(JsonDocumentOptions)) { JsonReaderOptions readerOptions = options.GetReaderOptions(); if (!utf8Json.IsSingleSegment) { int num = checked((int)utf8Json.Length); byte[] array = ArrayPool<byte>.Shared.Rent(num); try { ref utf8Json.CopyTo(array.AsSpan()); return Parse(array.AsMemory(0, num), readerOptions, array, null); } catch { array.AsSpan(0, num).Clear(); ArrayPool<byte>.Shared.Return(array, false); throw; } } return Parse(utf8Json.First, readerOptions, null, null); } [System.Runtime.CompilerServices.NullableContext(1)] public static JsonDocument Parse(Stream utf8Json, JsonDocumentOptions options = default(JsonDocumentOptions)) { if (utf8Json == null) ThrowHelper.ThrowArgumentNullException("utf8Json"); ArraySegment<byte> segment = ReadToEnd(utf8Json); try { return Parse(segment.AsMemory(), options.GetReaderOptions(), segment.Array, null); } catch { segment.AsSpan().Clear(); ArrayPool<byte>.Shared.Return(segment.Array, false); throw; } } internal static JsonDocument ParseRented(PooledByteBufferWriter utf8Json, JsonDocumentOptions options = default(JsonDocumentOptions)) { return Parse(utf8Json.WrittenMemory, options.GetReaderOptions(), null, utf8Json); } internal static JsonDocument ParseValue(Stream utf8Json, JsonDocumentOptions options) { ArraySegment<byte> segment = ReadToEnd(utf8Json); byte[] array = new byte[segment.Count]; Buffer.BlockCopy(segment.Array, 0, array, 0, segment.Count); segment.AsSpan().Clear(); ArrayPool<byte>.Shared.Return(segment.Array, false); return ParseUnrented(array.AsMemory(), options.GetReaderOptions(), JsonTokenType.None); } internal static JsonDocument ParseValue(ReadOnlySpan<byte> utf8Json, JsonDocumentOptions options) { byte[] array = new byte[utf8Json.Length]; utf8Json.CopyTo(array); return ParseUnrented(array.AsMemory(), options.GetReaderOptions(), JsonTokenType.None); } internal static JsonDocument ParseValue(string json, JsonDocumentOptions options) { return ParseValue(json.AsMemory(), options); } [System.Runtime.CompilerServices.NullableContext(1)] public static Task<JsonDocument> ParseAsync(Stream utf8Json, JsonDocumentOptions options = default(JsonDocumentOptions), CancellationToken cancellationToken = default(CancellationToken)) { if (utf8Json == null) ThrowHelper.ThrowArgumentNullException("utf8Json"); return ParseAsyncCore(utf8Json, options, cancellationToken); } [AsyncStateMachine(typeof(<ParseAsyncCore>d__69))] private static Task<JsonDocument> ParseAsyncCore(Stream utf8Json, JsonDocumentOptions options = default(JsonDocumentOptions), CancellationToken cancellationToken = default(CancellationToken)) { <ParseAsyncCore>d__69 stateMachine = default(<ParseAsyncCore>d__69); stateMachine.<>t__builder = AsyncTaskMethodBuilder<JsonDocument>.Create(); stateMachine.utf8Json = utf8Json; stateMachine.options = options; stateMachine.cancellationToken = cancellationToken; stateMachine.<>1__state = -1; stateMachine.<>t__builder.Start(ref stateMachine); return stateMachine.<>t__builder.Task; } [AsyncStateMachine(typeof(<ParseAsyncCoreUnrented>d__70))] internal static Task<JsonDocument> ParseAsyncCoreUnrented(Stream utf8Json, JsonDocumentOptions options = default(JsonDocumentOptions), CancellationToken cancellationToken = default(CancellationToken)) { <ParseAsyncCoreUnrented>d__70 stateMachine = default(<ParseAsyncCoreUnrented>d__70); stateMachine.<>t__builder = AsyncTaskMethodBuilder<JsonDocument>.Create(); stateMachine.utf8Json = utf8Json; stateMachine.options = options; stateMachine.cancellationToken = cancellationToken; stateMachine.<>1__state = -1; stateMachine.<>t__builder.Start(ref stateMachine); return stateMachine.<>t__builder.Task; } [return: System.Runtime.CompilerServices.Nullable(1)] public static JsonDocument Parse([System.Diagnostics.CodeAnalysis.StringSyntax("Json")] ReadOnlyMemory<char> json, JsonDocumentOptions options = default(JsonDocumentOptions)) { ReadOnlySpan<char> span = json.Span; int utf8ByteCount = JsonReaderHelper.GetUtf8ByteCount(span); byte[] array = ArrayPool<byte>.Shared.Rent(utf8ByteCount); try { int utf8FromText = JsonReaderHelper.GetUtf8FromText(span, array); return Parse(array.AsMemory(0, utf8FromText), options.GetReaderOptions(), array, null); } catch { array.AsSpan(0, utf8ByteCount).Clear(); ArrayPool<byte>.Shared.Return(array, false); throw; } } internal static JsonDocument ParseValue(ReadOnlyMemory<char> json, JsonDocumentOptions options) { ReadOnlySpan<char> span = json.Span; int utf8ByteCount = JsonReaderHelper.GetUtf8ByteCount(span); byte[] array = ArrayPool<byte>.Shared.Rent(utf8ByteCount); byte[] array2 = default(byte[]); try { int utf8FromText = JsonReaderHelper.GetUtf8FromText(span, array); array2 = new byte[utf8FromText]; Buffer.BlockCopy(array, 0, array2, 0, utf8FromText); } finally { array.AsSpan(0, utf8ByteCount).Clear(); ArrayPool<byte>.Shared.Return(array, false); } return ParseUnrented(array2.AsMemory(), options.GetReaderOptions(), JsonTokenType.None); } [System.Runtime.CompilerServices.NullableContext(1)] public static JsonDocument Parse([System.Diagnostics.CodeAnalysis.StringSyntax("Json")] string json, JsonDocumentOptions options = default(JsonDocumentOptions)) { if (json == null) ThrowHelper.ThrowArgumentNullException("json"); return Parse(json.AsMemory(), options); } [System.Runtime.CompilerServices.NullableContext(2)] public static bool TryParseValue(ref Utf8JsonReader reader, [System.Diagnostics.CodeAnalysis.NotNullWhen(true)] out JsonDocument document) { return TryParseValue(ref reader, out document, false, true); } [System.Runtime.CompilerServices.NullableContext(1)] public static JsonDocument ParseValue(ref Utf8JsonReader reader) { TryParseValue(ref reader, out JsonDocument document, true, true); return document; } internal static bool TryParseValue(ref Utf8JsonReader reader, [System.Diagnostics.CodeAnalysis.NotNullWhen(true)] out JsonDocument document, bool shouldThrow, bool useArrayPools) { JsonReaderState currentState = reader.CurrentState; CheckSupportedOptions(currentState.Options, "reader"); Utf8JsonReader utf8JsonReader = reader; ReadOnlySpan<byte> readOnlySpan = default(ReadOnlySpan<byte>); ReadOnlySequence<byte> source = default(ReadOnlySequence<byte>); try { JsonTokenType tokenType = reader.TokenType; ReadOnlySpan<byte> bytes; if ((tokenType == JsonTokenType.None || tokenType == JsonTokenType.PropertyName) && !reader.Read()) { if (shouldThrow) { bytes = default(ReadOnlySpan<byte>); ThrowHelper.ThrowJsonReaderException(ref reader, ExceptionResource.ExpectedJsonTokens, 0, bytes); } reader = utf8JsonReader; document = null; return false; } switch (reader.TokenType) { case JsonTokenType.StartObject: case JsonTokenType.StartArray: { long tokenStartIndex = reader.TokenStartIndex; if (!reader.TrySkip()) { if (shouldThrow) { bytes = default(ReadOnlySpan<byte>); ThrowHelper.ThrowJsonReaderException(ref reader, ExceptionResource.ExpectedJsonTokens, 0, bytes); } reader = utf8JsonReader; document = null; return false; } long num3 = reader.BytesConsumed - tokenStartIndex; ReadOnlySequence<byte> originalSequence2 = reader.OriginalSequence; if (originalSequence2.IsEmpty) { bytes = reader.OriginalSpan; readOnlySpan = checked(bytes.Slice((int)tokenStartIndex, (int)num3)); } else source = originalSequence2.Slice(tokenStartIndex, num3); break; } case JsonTokenType.True: case JsonTokenType.False: case JsonTokenType.Null: if (!useArrayPools) { document = CreateForLiteral(reader.TokenType); return true; } if (reader.HasValueSequence) source = reader.ValueSequence; else readOnlySpan = reader.ValueSpan; break; case JsonTokenType.Number: if (reader.HasValueSequence) source = reader.ValueSequence; else readOnlySpan = reader.ValueSpan; break; case JsonTokenType.String: { ReadOnlySequence<byte> originalSequence = reader.OriginalSequence; if (originalSequence.IsEmpty) { bytes = reader.ValueSpan; int length = bytes.Length + 2; readOnlySpan = reader.OriginalSpan.Slice((int)reader.TokenStartIndex, length); } else { long num = 2; if (reader.HasValueSequence) num += reader.ValueSequence.Length; else { long num2 = num; bytes = reader.ValueSpan; num = num2 + bytes.Length; } source = originalSequence.Slice(reader.TokenStartIndex, num); } break; } default: if (shouldThrow) { bytes = reader.ValueSpan; byte b = bytes[0]; byte nextByte = b; bytes = default(ReadOnlySpan<byte>); ThrowHelper.ThrowJsonReaderException(ref reader, ExceptionResource.ExpectedStartOfValueNotFound, nextByte, bytes); } reader = utf8JsonReader; document = null; return false; } } catch { reader = utf8JsonReader; throw; } int num4 = readOnlySpan.IsEmpty ? checked((int)source.Length) : readOnlySpan.Length; if (useArrayPools) { byte[] array = ArrayPool<byte>.Shared.Rent(num4); Span<byte> destination = array.AsSpan(0, num4); try { if (readOnlySpan.IsEmpty) ref source.CopyTo(destination); else readOnlySpan.CopyTo(destination); document = Parse(array.AsMemory(0, num4), currentState.Options, array, null); } catch { destination.Clear(); ArrayPool<byte>.Shared.Return(array, false); throw; } } else { byte[] array2 = (!readOnlySpan.IsEmpty) ? readOnlySpan.ToArray() : ref source.ToArray(); document = ParseUnrented(array2, currentState.Options, reader.TokenType); } return true; } private static JsonDocument CreateForLiteral(JsonTokenType tokenType) { <>c__DisplayClass77_0 <>c__DisplayClass77_ = default(<>c__DisplayClass77_0); <>c__DisplayClass77_.tokenType = tokenType; ReadOnlySpan<byte> readOnlySpan; switch (<>c__DisplayClass77_.tokenType) { case JsonTokenType.False: if (s_falseLiteral == null) { readOnlySpan = JsonConstants.FalseValue; s_falseLiteral = <CreateForLiteral>g__Create|77_0(readOnlySpan.ToArray(), ref <>c__DisplayClass77_); } return s_falseLiteral; case JsonTokenType.True: if (s_trueLiteral == null) { readOnlySpan = JsonConstants.TrueValue; s_trueLiteral = <CreateForLiteral>g__Create|77_0(readOnlySpan.ToArray(), ref <>c__DisplayClass77_); } return s_trueLiteral; default: if (s_nullLiteral == null) { readOnlySpan = JsonConstants.NullValue; s_nullLiteral = <CreateForLiteral>g__Create|77_0(readOnlySpan.ToArray(), ref <>c__DisplayClass77_); } return s_nullLiteral; } } private static JsonDocument Parse(ReadOnlyMemory<byte> utf8Json, JsonReaderOptions readerOptions, byte[] extraRentedArrayPoolBytes = null, PooledByteBufferWriter extraPooledByteBufferWriter = null) { ReadOnlySpan<byte> span = utf8Json.Span; MetadataDb database = MetadataDb.CreateRented(utf8Json.Length, false); StackRowStack stack = new StackRowStack(512); try { Parse(span, readerOptions, ref database, ref stack); } catch { database.Dispose(); throw; } finally { stack.Dispose(); } return new JsonDocument(utf8Json, database, extraRentedArrayPoolBytes, extraPooledByteBufferWriter, true); } private static JsonDocument ParseUnrented(ReadOnlyMemory<byte> utf8Json, JsonReaderOptions readerOptions, JsonTokenType tokenType = JsonTokenType.None) { ReadOnlySpan<byte> span = utf8Json.Span; MetadataDb database; if (tokenType == JsonTokenType.String || tokenType == JsonTokenType.Number) { database = MetadataDb.CreateLocked(utf8Json.Length); StackRowStack stack = default(StackRowStack); Parse(span, readerOptions, ref database, ref stack); } else { database = MetadataDb.CreateRented(utf8Json.Length, true); StackRowStack stack2 = new StackRowStack(512); try { Parse(span, readerOptions, ref database, ref stack2); } finally { stack2.Dispose(); } } return new JsonDocument(utf8Json, database, null, null, false); } private static ArraySegment<byte> ReadToEnd(Stream stream) { int num = 0; byte[] array = null; ReadOnlySpan<byte> utf8Bom = JsonConstants.Utf8Bom; try { if (stream.CanSeek) { long num2 = Math.Max(utf8Bom.Length, stream.Length - stream.Position) + 1; array = ArrayPool<byte>.Shared.Rent(checked((int)num2)); } else array = ArrayPool<byte>.Shared.Rent(4096); int num3; do { num3 = stream.Read(array, num, utf8Bom.Length - num); num += num3; } while (num3 > 0 && num < utf8Bom.Length); if (num == utf8Bom.Length && utf8Bom.SequenceEqual(array.AsSpan(0, utf8Bom.Length))) num = 0; do { if (array.Length == num) { byte[] array2 = array; array = ArrayPool<byte>.Shared.Rent(checked(array2.Length * 2)); Buffer.BlockCopy(array2, 0, array, 0, array2.Length); ArrayPool<byte>.Shared.Return(array2, true); } num3 = stream.Read(array, num, array.Length - num); num += num3; } while (num3 > 0); return new ArraySegment<byte>(array, 0, num); } catch { if (array != null) { array.AsSpan(0, num).Clear(); ArrayPool<byte>.Shared.Return(array, false); } throw; } } [AsyncStateMachine(typeof(<ReadToEndAsync>d__81))] private static Task<ArraySegment<byte>> ReadToEndAsync(Stream stream, CancellationToken cancellationToken) { <ReadToEndAsync>d__81 stateMachine = default(<ReadToEndAsync>d__81); stateMachine.<>t__builder = AsyncTaskMethodBuilder<ArraySegment<byte>>.Create(); stateMachine.stream = stream; stateMachine.cancellationToken = cancellationToken; stateMachine.<>1__state = -1; stateMachine.<>t__builder.Start(ref stateMachine); return stateMachine.<>t__builder.Task; } internal unsafe bool TryGetNamedPropertyValue(int index, ReadOnlySpan<char> propertyName, out JsonElement value) { CheckNotDisposed(); DbRow dbRow = _parsedData.Get(index); CheckExpectedType(JsonTokenType.StartObject, dbRow.TokenType); if (dbRow.NumberOfRows == 1) { value = default(JsonElement); return false; } int maxByteCount = JsonReaderHelper.s_utf8Encoding.GetMaxByteCount(propertyName.Length); int startIndex = index + 12; int num = checked(dbRow.NumberOfRows * 12 + index); if (maxByteCount < 256) { Span<byte> span = new Span<byte>(stackalloc byte[256], 256); int utf8FromText = JsonReaderHelper.GetUtf8FromText(propertyName, span); span = span.Slice(0, utf8FromText); return TryGetNamedPropertyValue(startIndex, num, span, out value); } int length = propertyName.Length; int num2; for (num2 = num - 12; num2 > index; num2 -= 12) { int num3 = num2; dbRow = _parsedData.Get(num2); num2 = ((!dbRow.IsSimpleValue) ? (num2 - 12 * (dbRow.NumberOfRows + 1)) : (num2 - 12)); dbRow = _parsedData.Get(num2); if (dbRow.SizeOrLength >= length) { byte[] array = ArrayPool<byte>.Shared.Rent(maxByteCount); Span<byte> span2 = default(Span<byte>); try { int utf8FromText2 = JsonReaderHelper.GetUtf8FromText(propertyName, array); span2 = array.AsSpan(0, utf8FromText2); return TryGetNamedPropertyValue(startIndex, num3 + 12, span2, out value); } finally { span2.Clear(); ArrayPool<byte>.Shared.Return(array, false); } } } value = default(JsonElement); return false; } internal bool TryGetNamedPropertyValue(int index, ReadOnlySpan<byte> propertyName, out JsonElement value) { CheckNotDisposed(); DbRow dbRow = _parsedData.Get(index); CheckExpectedType(JsonTokenType.StartObject, dbRow.TokenType); if (dbRow.NumberOfRows == 1) { value = default(JsonElement); return false; } int endIndex = checked(dbRow.NumberOfRows * 12 + index); return TryGetNamedPropertyValue(index + 12, endIndex, propertyName, out value); } private unsafe bool TryGetNamedPropertyValue(int startIndex, int endIndex, ReadOnlySpan<byte> propertyName, out JsonElement value) { ReadOnlySpan<byte> span = _utf8Json.Span; Span<byte> span2 = new Span<byte>(stackalloc byte[256], 256); int num; for (num = endIndex - 12; num > startIndex; num -= 12) { DbRow dbRow = _parsedData.Get(num); num = ((!dbRow.IsSimpleValue) ? (num - 12 * (dbRow.NumberOfRows + 1)) : (num - 12)); dbRow = _parsedData.Get(num); ReadOnlySpan<byte> span3 = span.Slice(dbRow.Location, dbRow.SizeOrLength); if (dbRow.HasComplexChildren) { if (span3.Length > propertyName.Length) { int num2 = span3.IndexOf<byte>(92); if (propertyName.Length > num2 && span3.Slice(0, num2).SequenceEqual(propertyName.Slice(0, num2))) { int num3 = span3.Length - num2; int written = 0; byte[] array = null; try { Span<byte> destination = (num3 <= span2.Length) ? span2 : ((Span<byte>)(array = ArrayPool<byte>.Shared.Rent(num3))); JsonReaderHelper.Unescape(span3.Slice(num2), destination, 0, out written); if (destination.Slice(0, written).SequenceEqual(propertyName.Slice(num2))) { value = new JsonElement(this, num + 12); return true; } } finally { if (array != null) { array.AsSpan(0, written).Clear(); ArrayPool<byte>.Shared.Return(array, false); } } } } } else if (span3.SequenceEqual(propertyName)) { value = new JsonElement(this, num + 12); return true; } } value = default(JsonElement); return false; } } }