public async override Task <int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) { // TODO: Validate buffer if (_disposed) { return(0); } try { cancellationToken.ThrowIfCancellationRequested(); if (_expectChunkHeader) { System.Diagnostics.Debug.Assert(_chunkBytesRemaining == 0); string headerLine = await _inner.ReadLineAsync(cancellationToken); if (!long.TryParse(headerLine, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out _chunkBytesRemaining)) { throw new IOException("Invalid chunk header: " + headerLine); } _expectChunkHeader = false; } int read = 0; if (_chunkBytesRemaining > 0) { // Not the last (empty) chunk. int toRead = (int)Math.Min(count, _chunkBytesRemaining); read = await _inner.ReadAsync(buffer, offset, toRead, cancellationToken); _chunkBytesRemaining -= read; System.Diagnostics.Debug.Assert(_chunkBytesRemaining >= 0, "Negative bytes remaining? " + _chunkBytesRemaining); } // TODO: else, drain trailer headers. if (_chunkBytesRemaining == 0) { // End of chunk, read the terminator CRLF string trailerLine = await _inner.ReadLineAsync(cancellationToken); System.Diagnostics.Debug.Assert(string.IsNullOrEmpty(trailerLine)); _expectChunkHeader = true; } if (read == 0) { Dispose(); } return(read); } catch (Exception) { Dispose(); throw; } }
public async override Task <int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) { // TODO: Validate buffer ThrowIfDisposed(); if (_done) { return(0); } cancellationToken.ThrowIfCancellationRequested(); if (_chunkBytesRemaining == 0) { string headerLine = await _inner.ReadLineAsync(cancellationToken).ConfigureAwait(false); if (!long.TryParse(headerLine, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out _chunkBytesRemaining)) { throw new IOException("Invalid chunk header: " + headerLine); } } int read = 0; if (_chunkBytesRemaining > 0) { int toRead = (int)Math.Min(count, _chunkBytesRemaining); read = await _inner.ReadAsync(buffer, offset, toRead, cancellationToken).ConfigureAwait(false); if (read == 0) { throw new EndOfStreamException(); } _chunkBytesRemaining -= read; } if (_chunkBytesRemaining == 0) { // End of chunk, read the terminator CRLF var trailer = await _inner.ReadLineAsync(cancellationToken).ConfigureAwait(false); if (trailer.Length > 0) { throw new IOException("Invalid chunk trailer"); } if (read == 0) { _done = true; } } return(read); }