diff --git a/src/ICSharpCode.SharpZipLib/Zip/Compression/Streams/DeflaterOutputStream.cs b/src/ICSharpCode.SharpZipLib/Zip/Compression/Streams/DeflaterOutputStream.cs index a7e6807ca..08c61b574 100644 --- a/src/ICSharpCode.SharpZipLib/Zip/Compression/Streams/DeflaterOutputStream.cs +++ b/src/ICSharpCode.SharpZipLib/Zip/Compression/Streams/DeflaterOutputStream.cs @@ -1,5 +1,6 @@ using ICSharpCode.SharpZipLib.Encryption; using System; +using System.Buffers; using System.IO; using System.Security.Cryptography; using System.Text; @@ -83,7 +84,16 @@ public DeflaterOutputStream(Stream baseOutputStream, Deflater deflater, int buff } baseOutputStream_ = baseOutputStream; - buffer_ = new byte[bufferSize]; + + if(ArrayPool<byte>.Shared != null) + { + buffer_ = ArrayPool<byte>.Shared.Rent(bufferSize); + isBufferOwnedByArrayPool_ = true; + } + else + { + buffer_ = new byte[bufferSize]; + } deflater_ = deflater ?? throw new ArgumentNullException(nameof(deflater)); } @@ -226,7 +236,10 @@ public Encoding ZipCryptoEncoding { /// </param> protected void EncryptBlock(byte[] buffer, int offset, int length) { - if(cryptoTransform_ is null) return; + if(cryptoTransform_ is null) + { + return; + } cryptoTransform_.TransformBlock(buffer, 0, length, buffer, 0); } @@ -432,6 +445,13 @@ protected override void Dispose(bool disposing) baseOutputStream_.Dispose(); } } + + // Ensure buffer is returned to the pool if it was rented from it. + if(isBufferOwnedByArrayPool_) + { + ArrayPool<byte>.Shared.Return(buffer_); + } + buffer_ = null; } } @@ -540,6 +560,11 @@ public override async Task WriteAsync(byte[] buffer, int offset, int count, Canc /// </summary> private byte[] buffer_; + /// <summary> + /// If true, this buffer is owned by the array pool and should be returned there on Dispose. + /// </summary> + private bool isBufferOwnedByArrayPool_; + /// <summary> /// The deflater which is used to deflate the stream. /// </summary> diff --git a/src/ICSharpCode.SharpZipLib/Zip/Compression/Streams/InflaterInputStream.cs b/src/ICSharpCode.SharpZipLib/Zip/Compression/Streams/InflaterInputStream.cs index 980ffc701..39e79a501 100644 --- a/src/ICSharpCode.SharpZipLib/Zip/Compression/Streams/InflaterInputStream.cs +++ b/src/ICSharpCode.SharpZipLib/Zip/Compression/Streams/InflaterInputStream.cs @@ -1,4 +1,5 @@ using System; +using System.Buffers; using System.IO; using System.Security.Cryptography; using ICSharpCode.SharpZipLib.Core; @@ -11,7 +12,7 @@ namespace ICSharpCode.SharpZipLib.Zip.Compression.Streams /// <remarks> /// The buffer supports decryption of incoming data. /// </remarks> - public class InflaterInputBuffer + public class InflaterInputBuffer : IDisposable { #region Constructors @@ -36,7 +37,16 @@ public InflaterInputBuffer(Stream stream, int bufferSize) { bufferSize = 1024; } - rawData = new byte[bufferSize]; + + if(ArrayPool<bool>.Shared != null) + { + rawData = ArrayPool<byte>.Shared.Rent(bufferSize); + isRawDataOwnedByArrayPool = true; + } + else + { + rawData = new byte[bufferSize]; + } clearText = rawData; } @@ -269,6 +279,20 @@ public long ReadLeLong() return (uint)ReadLeInt() | ((long)ReadLeInt() << 32); } + /// <summary> + /// Implements the dispose method of the <see cref="IDisposable"/> interface. + /// </summary> + public void Dispose() + { + if(isRawDataOwnedByArrayPool) + { + ArrayPool<byte>.Shared.Return(rawData); + } + rawData = null; + clearText = null; + internalClearText = null; + } + /// <summary> /// Get/set the <see cref="ICryptoTransform"/> to apply to any data. /// </summary> @@ -306,6 +330,7 @@ public ICryptoTransform CryptoTransform private int rawLength; private byte[] rawData; + private bool isRawDataOwnedByArrayPool = false; private int clearTextLength; private byte[] clearText; @@ -637,6 +662,11 @@ protected override void Dispose(bool disposing) InflaterPool.Instance.Return(inflater); } inf = null; + + if(inputBuffer != null) + { + inputBuffer.Dispose(); + } } /// <summary>