diff --git a/src/SharpCompress/Compressors/LZMA/LZipStream.Async.cs b/src/SharpCompress/Compressors/LZMA/LZipStream.Async.cs index 5daa3aef..ae8e1074 100644 --- a/src/SharpCompress/Compressors/LZMA/LZipStream.Async.cs +++ b/src/SharpCompress/Compressors/LZMA/LZipStream.Async.cs @@ -1,4 +1,5 @@ using System; +using System.Buffers; using System.Buffers.Binary; using System.IO; using System.Threading; @@ -34,7 +35,7 @@ public sealed partial class LZipStream return new LZipStream(stream, mode, leaveOpen); } - public async ValueTask FinishAsync() + public async ValueTask FinishAsync(CancellationToken cancellationToken) { if (_finished) { @@ -43,32 +44,40 @@ public sealed partial class LZipStream if (Mode == CompressionMode.Compress) { + cancellationToken.ThrowIfCancellationRequested(); var crc32Stream = (Crc32Stream)_stream; await FinishWrappedStreamAsync(crc32Stream).ConfigureAwait(false); var compressedCount = _countingWritableSubStream.NotNull().BytesWritten; - var intBuf = new byte[8]; - BinaryPrimitives.WriteUInt32LittleEndian(intBuf, crc32Stream.Crc); - await _countingWritableSubStream - .NotNull() - .WriteAsync(intBuf, 0, 4, CancellationToken.None) - .ConfigureAwait(false); + var intBuf = ArrayPool.Shared.Rent(8); + try + { + BinaryPrimitives.WriteUInt32LittleEndian(intBuf, crc32Stream.Crc); + await _countingWritableSubStream + .NotNull() + .WriteAsync(intBuf, 0, 4, cancellationToken) + .ConfigureAwait(false); - BinaryPrimitives.WriteInt64LittleEndian(intBuf, _writeCount); - await _countingWritableSubStream - .NotNull() - .WriteAsync(intBuf, 0, intBuf.Length, CancellationToken.None) - .ConfigureAwait(false); + BinaryPrimitives.WriteInt64LittleEndian(intBuf, _writeCount); + await _countingWritableSubStream + .NotNull() + .WriteAsync(intBuf, 0, 8, cancellationToken) + .ConfigureAwait(false); - // Total member size includes the 6-byte header and 20-byte trailer. - BinaryPrimitives.WriteUInt64LittleEndian( - intBuf, - (ulong)compressedCount + (ulong)(6 + 20) - ); - await _countingWritableSubStream - .NotNull() - .WriteAsync(intBuf, 0, intBuf.Length, CancellationToken.None) - .ConfigureAwait(false); + // Total member size includes the 6-byte header and 20-byte trailer. + BinaryPrimitives.WriteUInt64LittleEndian( + intBuf, + (ulong)compressedCount + (ulong)(6 + 20) + ); + await _countingWritableSubStream + .NotNull() + .WriteAsync(intBuf, 0, 8, cancellationToken) + .ConfigureAwait(false); + } + finally + { + ArrayPool.Shared.Return(intBuf); + } } _finished = true; diff --git a/src/SharpCompress/Compressors/LZMA/Lzma2EncoderStream.cs b/src/SharpCompress/Compressors/LZMA/Lzma2EncoderStream.cs index e562bb7c..f1ed808c 100644 --- a/src/SharpCompress/Compressors/LZMA/Lzma2EncoderStream.cs +++ b/src/SharpCompress/Compressors/LZMA/Lzma2EncoderStream.cs @@ -157,6 +157,8 @@ internal sealed class Lzma2EncoderStream : Stream base.Dispose(disposing); } + private static readonly byte[] _endMarker = [0x00]; + #if !LEGACY_DOTNET || NETSTANDARD2_1 public override async ValueTask DisposeAsync() #else @@ -171,8 +173,12 @@ internal sealed class Lzma2EncoderStream : Stream { await FlushChunkAsync().ConfigureAwait(false); } +#if !LEGACY_DOTNET || NETSTANDARD2_1 - await _output.WriteAsync(new byte[] { 0x00 }, 0, 1).ConfigureAwait(false); + await _output.WriteAsync(new Memory(_endMarker)).ConfigureAwait(false); +#else + await _output.WriteAsync(_endMarker, 0, 1).ConfigureAwait(false); +#endif } #if !LEGACY_DOTNET || NETSTANDARD2_1 diff --git a/src/SharpCompress/Providers/IFinishable.cs b/src/SharpCompress/Providers/IFinishable.cs index ea4980d4..da532674 100644 --- a/src/SharpCompress/Providers/IFinishable.cs +++ b/src/SharpCompress/Providers/IFinishable.cs @@ -1,3 +1,4 @@ +using System.Threading; using System.Threading.Tasks; namespace SharpCompress.Providers; @@ -19,5 +20,5 @@ public interface IFinishable /// void Finish(); - ValueTask FinishAsync(); + ValueTask FinishAsync(CancellationToken cancellationToken); } diff --git a/src/SharpCompress/Writers/SevenZip/SevenZipWriter.Async.cs b/src/SharpCompress/Writers/SevenZip/SevenZipWriter.Async.cs index 48d3b0c7..9b24371d 100644 --- a/src/SharpCompress/Writers/SevenZip/SevenZipWriter.Async.cs +++ b/src/SharpCompress/Writers/SevenZip/SevenZipWriter.Async.cs @@ -29,7 +29,14 @@ public partial class SevenZipWriter finalized = true; await FinalizeArchiveAsync().ConfigureAwait(false); } - OutputStream?.Dispose(); + if (OutputStream is IAsyncDisposable asyncDisposable) + { + await asyncDisposable.DisposeAsync().ConfigureAwait(false); + } + else + { + OutputStream?.Dispose(); + } // base.DisposeAsync() is a no-op since _isDisposed is already set await base.DisposeAsync().ConfigureAwait(false); } diff --git a/src/SharpCompress/Writers/Tar/TarWriter.Async.cs b/src/SharpCompress/Writers/Tar/TarWriter.Async.cs index f66ad7ac..76ec1766 100644 --- a/src/SharpCompress/Writers/Tar/TarWriter.Async.cs +++ b/src/SharpCompress/Writers/Tar/TarWriter.Async.cs @@ -29,7 +29,7 @@ public partial class TarWriter } if (OutputStream is IFinishable finishable) { - await finishable.FinishAsync().ConfigureAwait(false); + await finishable.FinishAsync(CancellationToken.None).ConfigureAwait(false); } if (OutputStream is IAsyncDisposable asyncDisposableOutputStream) { diff --git a/src/SharpCompress/Writers/Zip/ZipWriter.Async.cs b/src/SharpCompress/Writers/Zip/ZipWriter.Async.cs index 91a91cb8..014a4806 100644 --- a/src/SharpCompress/Writers/Zip/ZipWriter.Async.cs +++ b/src/SharpCompress/Writers/Zip/ZipWriter.Async.cs @@ -34,7 +34,14 @@ public partial class ZipWriter ms.Position = 0; await ms.CopyToAsync(OutputStream.NotNull()).ConfigureAwait(false); - OutputStream?.Dispose(); + if (OutputStream is IAsyncDisposable asyncDisposable) + { + await asyncDisposable.DisposeAsync().ConfigureAwait(false); + } + else + { + OutputStream?.Dispose(); + } // base.DisposeAsync() is a no-op since _isDisposed is already set await base.DisposeAsync().ConfigureAwait(false); }