diff --git a/src/ICSharpCode.SharpZipLib/Encryption/ZipAESStream.cs b/src/ICSharpCode.SharpZipLib/Encryption/ZipAESStream.cs index 80ce0b4ab..09dd3a6be 100644 --- a/src/ICSharpCode.SharpZipLib/Encryption/ZipAESStream.cs +++ b/src/ICSharpCode.SharpZipLib/Encryption/ZipAESStream.cs @@ -67,6 +67,44 @@ public ZipAESStream(Stream stream, ZipAESTransform transform, CryptoStreamMode m /// and advances the position within the stream by the number of bytes read. /// public override int Read(byte[] buffer, int offset, int count) + { + // If we have buffered data, read that first + int nBytes = ReadDataFromBuffer(buffer, ref offset, ref count); + + // If we've read the requested amount of data, return just that + if (count == 0) + return nBytes; + + // Read more data from the input, if available + if (_slideBuffer != null) + { + nBytes += ReadAndTransformAsync(buffer, offset, count, false, default).GetAwaiter().GetResult(); + } + + return nBytes; + } + + /// + public override async Task ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) + { + // If we have buffered data, read that first + int nBytes = ReadDataFromBuffer(buffer, ref offset, ref count); + + // If we've read the requested amount of data, return just that + if (count == 0) + return nBytes; + + // Read more data from the input, if available + if (_slideBuffer != null) + { + nBytes += await ReadAndTransformAsync(buffer, offset, count, true, cancellationToken).ConfigureAwait(false); + } + + return nBytes; + } + + // Read up to the requested amount of data from the buffer + private int ReadDataFromBuffer(byte[] buffer, ref int offset, ref int count) { // Nothing to do if (count == 0) @@ -78,30 +116,15 @@ public override int Read(byte[] buffer, int offset, int count) { nBytes = ReadBufferedData(buffer, offset, count); - // Read all requested data from the buffer - if (nBytes == count) - return nBytes; - offset += nBytes; count -= nBytes; } - // Read more data from the input, if available - if (_slideBuffer != null) - nBytes += ReadAndTransform(buffer, offset, count); - return nBytes; } - /// - public override Task ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) - { - var readCount = Read(buffer, offset, count); - return Task.FromResult(readCount); - } - // Read data from the underlying stream and decrypt it - private int ReadAndTransform(byte[] buffer, int offset, int count) + private async Task ReadAndTransformAsync(byte[] buffer, int offset, int count, bool useAsync, CancellationToken cancellationToken) { int nBytes = 0; while (nBytes < count) @@ -126,7 +149,11 @@ private int ReadAndTransform(byte[] buffer, int offset, int count) _slideBufFreePos -= _slideBufStartPos; // Note the -= _slideBufStartPos = 0; } - int obtained = StreamUtils.ReadRequestedBytes(_stream, _slideBuffer, _slideBufFreePos, lengthToRead); + + int obtained = useAsync ? + await StreamUtils.ReadRequestedBytesAsync(_stream, _slideBuffer, _slideBufFreePos, lengthToRead, cancellationToken).ConfigureAwait(false) : + StreamUtils.ReadRequestedBytes(_stream, _slideBuffer, _slideBufFreePos, lengthToRead); + _slideBufFreePos += obtained; // Recalculate how much data we now have