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

ReadBufferState

using System.Buffers; using System.IO; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; namespace System.Text.Json.Serialization { [StructLayout(LayoutKind.Auto)] internal struct ReadBufferState : IDisposable { private byte[] _buffer; private byte _offset; private int _count; private int _maxCount; private bool _isFirstBlock; private bool _isFinalBlock; private const int UnsuccessfulReadCountThreshold = 5; private int _unsuccessfulReadCount; public bool IsFinalBlock { [System.Runtime.CompilerServices.IsReadOnly] get { return _isFinalBlock; } } public ReadOnlySpan<byte> Bytes { [System.Runtime.CompilerServices.IsReadOnly] get { return _buffer.AsSpan(_offset, _count); } } public ReadBufferState(int initialBufferSize) { _unsuccessfulReadCount = 0; _buffer = ArrayPool<byte>.Shared.Rent(Math.Max(initialBufferSize, JsonConstants.Utf8Bom.Length)); _maxCount = (_count = (_offset = 0)); _isFirstBlock = true; _isFinalBlock = false; } [System.Runtime.CompilerServices.IsReadOnly] [AsyncStateMachine(typeof(<ReadFromStreamAsync>d__13))] public ValueTask<ReadBufferState> ReadFromStreamAsync(Stream utf8Json, CancellationToken cancellationToken, bool fillBuffer = true) { <ReadFromStreamAsync>d__13 stateMachine = default(<ReadFromStreamAsync>d__13); stateMachine.<>t__builder = AsyncValueTaskMethodBuilder<ReadBufferState>.Create(); stateMachine.<>4__this = this; stateMachine.utf8Json = utf8Json; stateMachine.cancellationToken = cancellationToken; stateMachine.fillBuffer = fillBuffer; stateMachine.<>1__state = -1; stateMachine.<>t__builder.Start(ref stateMachine); return stateMachine.<>t__builder.Task; } public void ReadFromStream(Stream utf8Json) { do { int num = utf8Json.Read(_buffer, _count, _buffer.Length - _count); if (num == 0) { _isFinalBlock = true; break; } _count += num; } while (_count < _buffer.Length); ProcessReadBytes(); } public void AdvanceBuffer(int bytesConsumed) { _unsuccessfulReadCount = ((bytesConsumed == 0) ? (_unsuccessfulReadCount + 1) : 0); _count -= bytesConsumed; if (!_isFinalBlock) { if ((uint)_count > (uint)_buffer.Length / 2) { byte[] buffer = _buffer; int maxCount = _maxCount; byte[] array = ArrayPool<byte>.Shared.Rent((_buffer.Length < 1073741823) ? (_buffer.Length * 2) : 2147483647); Buffer.BlockCopy(buffer, _offset + bytesConsumed, array, 0, _count); _buffer = array; _maxCount = _count; new Span<byte>(buffer, 0, maxCount).Clear(); ArrayPool<byte>.Shared.Return(buffer, false); } else if (_count != 0) { Buffer.BlockCopy(_buffer, _offset + bytesConsumed, _buffer, 0, _count); } } _offset = 0; } private void ProcessReadBytes() { if (_count > _maxCount) _maxCount = _count; if (_isFirstBlock) { _isFirstBlock = false; if (_buffer.AsSpan(0, _count).StartsWith(JsonConstants.Utf8Bom)) { ReadOnlySpan<byte> utf8Bom = JsonConstants.Utf8Bom; _offset = (byte)utf8Bom.Length; int count = _count; utf8Bom = JsonConstants.Utf8Bom; _count = count - utf8Bom.Length; } } } public void Dispose() { new Span<byte>(_buffer, 0, _maxCount).Clear(); byte[] buffer = _buffer; _buffer = null; ArrayPool<byte>.Shared.Return(buffer, false); } } }