From c1d240b516abddd11437673c2a9237e4e46581b1 Mon Sep 17 00:00:00 2001 From: Adam Hathcock Date: Wed, 14 Jan 2026 14:06:39 +0000 Subject: [PATCH 1/8] Fix more tests --- tests/SharpCompress.Test/GZip/GZipReaderAsyncTests.cs | 2 +- tests/SharpCompress.Test/Tar/TarArchiveAsyncTests.cs | 6 +++--- tests/SharpCompress.Test/Tar/TarReaderAsyncTests.cs | 2 +- tests/SharpCompress.Test/Zip/Zip64AsyncTests.cs | 2 +- .../Zip/ZipMemoryArchiveWithCrcAsyncTests.cs | 3 ++- 5 files changed, 8 insertions(+), 7 deletions(-) diff --git a/tests/SharpCompress.Test/GZip/GZipReaderAsyncTests.cs b/tests/SharpCompress.Test/GZip/GZipReaderAsyncTests.cs index 58f5d9dc..74eabb47 100644 --- a/tests/SharpCompress.Test/GZip/GZipReaderAsyncTests.cs +++ b/tests/SharpCompress.Test/GZip/GZipReaderAsyncTests.cs @@ -70,7 +70,7 @@ public class GZipReaderAsyncTests : ReaderTests bufferSize: options.BufferSize ); using var testStream = new TestStream(protectedStream); - await using (var reader = ReaderFactory.OpenAsync(testStream, options, default)) + await using (var reader = ReaderFactory.OpenAsync(new AsyncOnlyStream(testStream), options, default)) { await UseReaderAsync(reader, expectedCompression); protectedStream.ThrowOnDispose = false; diff --git a/tests/SharpCompress.Test/Tar/TarArchiveAsyncTests.cs b/tests/SharpCompress.Test/Tar/TarArchiveAsyncTests.cs index f7758bb3..4acb78ad 100644 --- a/tests/SharpCompress.Test/Tar/TarArchiveAsyncTests.cs +++ b/tests/SharpCompress.Test/Tar/TarArchiveAsyncTests.cs @@ -33,7 +33,7 @@ public class TarArchiveAsyncTests : ArchiveTests // Step 1: create a tar file containing a file with the test name using (Stream stream = File.OpenWrite(Path.Combine(SCRATCH2_FILES_PATH, archive))) - using (var writer = WriterFactory.OpenAsync(stream, ArchiveType.Tar, CompressionType.None)) + using (var writer = WriterFactory.OpenAsync(new AsyncOnlyStream(stream), ArchiveType.Tar, CompressionType.None)) using (Stream inputStream = new MemoryStream()) { var sw = new StreamWriter(inputStream); @@ -82,7 +82,7 @@ public class TarArchiveAsyncTests : ArchiveTests // Step 1: create a tar file containing a file with a long name using (Stream stream = File.OpenWrite(Path.Combine(SCRATCH2_FILES_PATH, archive))) - using (var writer = WriterFactory.OpenAsync(stream, ArchiveType.Tar, CompressionType.None)) + using (var writer = WriterFactory.OpenAsync(new AsyncOnlyStream(stream), ArchiveType.Tar, CompressionType.None)) using (Stream inputStream = new MemoryStream()) { var sw = new StreamWriter(inputStream); @@ -183,7 +183,7 @@ public class TarArchiveAsyncTests : ArchiveTests using (var inputMemory = new MemoryStream(mstm.ToArray())) { var tropt = new ReaderOptions { ArchiveEncoding = enc }; - await using (var tr = ReaderFactory.OpenAsync(inputMemory, tropt)) + await using (var tr = ReaderFactory.OpenAsync(new AsyncOnlyStream(inputMemory), tropt)) { while (await tr.MoveToNextEntryAsync()) { diff --git a/tests/SharpCompress.Test/Tar/TarReaderAsyncTests.cs b/tests/SharpCompress.Test/Tar/TarReaderAsyncTests.cs index 1a18f3ce..92d23ad1 100644 --- a/tests/SharpCompress.Test/Tar/TarReaderAsyncTests.cs +++ b/tests/SharpCompress.Test/Tar/TarReaderAsyncTests.cs @@ -73,7 +73,7 @@ public class TarReaderAsyncTests : ReaderTests public async ValueTask Tar_BZip2_Entry_Stream_Async() { using (Stream stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "Tar.tar.bz2"))) - await using (var reader = ReaderFactory.OpenAsync(stream)) + await using (var reader = ReaderFactory.OpenAsync(new AsyncOnlyStream(stream))) { while (await reader.MoveToNextEntryAsync()) { diff --git a/tests/SharpCompress.Test/Zip/Zip64AsyncTests.cs b/tests/SharpCompress.Test/Zip/Zip64AsyncTests.cs index eab7e1c7..e32b3da6 100644 --- a/tests/SharpCompress.Test/Zip/Zip64AsyncTests.cs +++ b/tests/SharpCompress.Test/Zip/Zip64AsyncTests.cs @@ -199,7 +199,7 @@ public class Zip64AsyncTests : WriterTests ZipEntry? prev = null; using (var fs = File.OpenRead(filename)) { - var rd = ReaderFactory.OpenAsync(fs, new ReaderOptions { LookForHeader = false }); + var rd = ReaderFactory.OpenAsync(new AsyncOnlyStream(fs), new ReaderOptions { LookForHeader = false }); await using (rd) { while (await rd.MoveToNextEntryAsync()) diff --git a/tests/SharpCompress.Test/Zip/ZipMemoryArchiveWithCrcAsyncTests.cs b/tests/SharpCompress.Test/Zip/ZipMemoryArchiveWithCrcAsyncTests.cs index 471e8e31..eb93503a 100644 --- a/tests/SharpCompress.Test/Zip/ZipMemoryArchiveWithCrcAsyncTests.cs +++ b/tests/SharpCompress.Test/Zip/ZipMemoryArchiveWithCrcAsyncTests.cs @@ -9,6 +9,7 @@ using SharpCompress.Common; using SharpCompress.Compressors.Deflate; using SharpCompress.Compressors.Xz; using SharpCompress.Crypto; +using SharpCompress.Test.Mocks; using SharpCompress.Writers; using SharpCompress.Writers.Zip; using Xunit; @@ -131,7 +132,7 @@ public class ZipTypesLevelsWithCrcRatioAsyncTests : ArchiveTests CompressionLevel = compressionLevel, }; - using (var writer = WriterFactory.OpenAsync(zipStream, ArchiveType.Zip, writerOptions)) + using (var writer = WriterFactory.OpenAsync(new AsyncOnlyStream(zipStream), ArchiveType.Zip, writerOptions)) { await writer.WriteAsync( $"{compressionType}_level_{compressionLevel}_{sizeMb}MiB.txt", From ebfa16f09f5253d12a2cd97b5dbfcf74cc9a776f Mon Sep 17 00:00:00 2001 From: Adam Hathcock Date: Wed, 14 Jan 2026 14:12:53 +0000 Subject: [PATCH 2/8] more test fixes --- .../Rar/RarArchiveAsyncTests.cs | 3 ++- .../SevenZip/SevenZipArchiveAsyncTests.cs | 21 ++++++++++--------- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/tests/SharpCompress.Test/Rar/RarArchiveAsyncTests.cs b/tests/SharpCompress.Test/Rar/RarArchiveAsyncTests.cs index acfe4c27..a700f8d5 100644 --- a/tests/SharpCompress.Test/Rar/RarArchiveAsyncTests.cs +++ b/tests/SharpCompress.Test/Rar/RarArchiveAsyncTests.cs @@ -6,6 +6,7 @@ using SharpCompress.Archives.Rar; using SharpCompress.Common; using SharpCompress.Compressors.LZMA.Utilites; using SharpCompress.Readers; +using SharpCompress.Test.Mocks; using Xunit; namespace SharpCompress.Test.Rar; @@ -649,7 +650,7 @@ public class RarArchiveAsyncTests : ArchiveTests { testArchive = Path.Combine(TEST_ARCHIVES_PATH, testArchive); using var stream = File.OpenRead(testArchive); - await using var archive = await ArchiveFactory.OpenAsync(stream); + await using var archive = await ArchiveFactory.OpenAsync(new AsyncOnlyStream(stream)); Assert.True(await archive.IsSolidAsync()); await using (var reader = await archive.ExtractAllEntriesAsync()) { diff --git a/tests/SharpCompress.Test/SevenZip/SevenZipArchiveAsyncTests.cs b/tests/SharpCompress.Test/SevenZip/SevenZipArchiveAsyncTests.cs index 7a8718ee..6c571ea1 100644 --- a/tests/SharpCompress.Test/SevenZip/SevenZipArchiveAsyncTests.cs +++ b/tests/SharpCompress.Test/SevenZip/SevenZipArchiveAsyncTests.cs @@ -4,6 +4,7 @@ using System.Threading; using System.Threading.Tasks; using SharpCompress.Archives; using SharpCompress.Common; +using SharpCompress.Test.Mocks; using Xunit; namespace SharpCompress.Test.SevenZip; @@ -16,9 +17,9 @@ public class SevenZipArchiveAsyncTests : ArchiveTests { var testArchive = Path.Combine(TEST_ARCHIVES_PATH, "7Zip.LZMA.7z"); using var stream = File.OpenRead(testArchive); - using var archive = ArchiveFactory.Open(stream); + await using var archive = await ArchiveFactory.OpenAsync(new AsyncOnlyStream(stream)); - foreach (var entry in archive.Entries.Where(entry => !entry.IsDirectory)) + await foreach (var entry in archive.EntriesAsync.Where(entry => !entry.IsDirectory)) { var targetPath = Path.Combine(SCRATCH_FILES_PATH, entry.Key!); var targetDir = Path.GetDirectoryName(targetPath); @@ -41,9 +42,9 @@ public class SevenZipArchiveAsyncTests : ArchiveTests { var testArchive = Path.Combine(TEST_ARCHIVES_PATH, "7Zip.LZMA2.7z"); using var stream = File.OpenRead(testArchive); - using var archive = ArchiveFactory.Open(stream); + await using var archive = await ArchiveFactory.OpenAsync(new AsyncOnlyStream(stream)); - foreach (var entry in archive.Entries.Where(entry => !entry.IsDirectory)) + await foreach (var entry in archive.EntriesAsync.Where(entry => !entry.IsDirectory)) { var targetPath = Path.Combine(SCRATCH_FILES_PATH, entry.Key!); var targetDir = Path.GetDirectoryName(targetPath); @@ -66,9 +67,9 @@ public class SevenZipArchiveAsyncTests : ArchiveTests { var testArchive = Path.Combine(TEST_ARCHIVES_PATH, "7Zip.solid.7z"); using var stream = File.OpenRead(testArchive); - using var archive = ArchiveFactory.Open(stream); + await using var archive = await ArchiveFactory.OpenAsync(new AsyncOnlyStream(stream)); - foreach (var entry in archive.Entries.Where(entry => !entry.IsDirectory)) + await foreach (var entry in archive.EntriesAsync.Where(entry => !entry.IsDirectory)) { var targetPath = Path.Combine(SCRATCH_FILES_PATH, entry.Key!); var targetDir = Path.GetDirectoryName(targetPath); @@ -91,9 +92,9 @@ public class SevenZipArchiveAsyncTests : ArchiveTests { var testArchive = Path.Combine(TEST_ARCHIVES_PATH, "7Zip.BZip2.7z"); using var stream = File.OpenRead(testArchive); - using var archive = ArchiveFactory.Open(stream); + await using var archive = await ArchiveFactory.OpenAsync(new AsyncOnlyStream(stream)); - foreach (var entry in archive.Entries.Where(entry => !entry.IsDirectory)) + await foreach (var entry in archive.EntriesAsync.Where(entry => !entry.IsDirectory)) { var targetPath = Path.Combine(SCRATCH_FILES_PATH, entry.Key!); var targetDir = Path.GetDirectoryName(targetPath); @@ -116,9 +117,9 @@ public class SevenZipArchiveAsyncTests : ArchiveTests { var testArchive = Path.Combine(TEST_ARCHIVES_PATH, "7Zip.PPMd.7z"); using var stream = File.OpenRead(testArchive); - using var archive = ArchiveFactory.Open(stream); + await using var archive = await ArchiveFactory.OpenAsync(new AsyncOnlyStream(stream)); - foreach (var entry in archive.Entries.Where(entry => !entry.IsDirectory)) + await foreach (var entry in archive.EntriesAsync.Where(entry => !entry.IsDirectory)) { var targetPath = Path.Combine(SCRATCH_FILES_PATH, entry.Key!); var targetDir = Path.GetDirectoryName(targetPath); From 84b5b5a717dfc0772b6a3f4a7c84a65d3666048a Mon Sep 17 00:00:00 2001 From: Adam Hathcock Date: Wed, 14 Jan 2026 14:33:20 +0000 Subject: [PATCH 3/8] add more tests --- .../Ace/AceReaderAsyncTests.cs | 132 +++++++++++++++ .../Arj/ArjReaderAsyncTests.cs | 156 ++++++++++++++++++ .../BZip2/BZip2StreamAsyncTests.cs | 17 +- .../Xz/XZStreamAsyncTests.cs | 7 +- 4 files changed, 301 insertions(+), 11 deletions(-) create mode 100644 tests/SharpCompress.Test/Ace/AceReaderAsyncTests.cs create mode 100644 tests/SharpCompress.Test/Arj/ArjReaderAsyncTests.cs diff --git a/tests/SharpCompress.Test/Ace/AceReaderAsyncTests.cs b/tests/SharpCompress.Test/Ace/AceReaderAsyncTests.cs new file mode 100644 index 00000000..d42f36bc --- /dev/null +++ b/tests/SharpCompress.Test/Ace/AceReaderAsyncTests.cs @@ -0,0 +1,132 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading.Tasks; +using SharpCompress.Common; +using SharpCompress.Readers; +using SharpCompress.Readers.Ace; +using SharpCompress.Test.Mocks; +using Xunit; + +namespace SharpCompress.Test.Ace +{ + public class AceReaderAsyncTests : ReaderTests + { + public AceReaderAsyncTests() + { + UseExtensionInsteadOfNameToVerify = true; + UseCaseInsensitiveToVerify = true; + } + + [Fact] + public async ValueTask Ace_Uncompressed_Read_Async() => + await ReadAsync("Ace.store.ace", CompressionType.None); + + [Fact] + public async ValueTask Ace_Encrypted_Read_Async() + { + var exception = await Assert.ThrowsAsync(() => + ReadAsync("Ace.encrypted.ace") + ); + } + + [Theory] + [InlineData("Ace.method1.ace", CompressionType.AceLZ77)] + [InlineData("Ace.method1-solid.ace", CompressionType.AceLZ77)] + [InlineData("Ace.method2.ace", CompressionType.AceLZ77)] + [InlineData("Ace.method2-solid.ace", CompressionType.AceLZ77)] + public async ValueTask Ace_Unsupported_ShouldThrow_Async(string fileName, CompressionType compressionType) + { + var exception = await Assert.ThrowsAsync(() => + ReadAsync(fileName, compressionType) + ); + } + + [Theory] + [InlineData("Ace.store.largefile.ace", CompressionType.None)] + public async ValueTask Ace_LargeFileTest_Read_Async(string fileName, CompressionType compressionType) + { + await ReadForBufferBoundaryCheckAsync(fileName, compressionType); + } + + [Fact] + public async ValueTask Ace_Multi_Reader_Async() + { + var exception = await Assert.ThrowsAsync(() => + DoMultiReaderAsync(new[] { "Ace.store.split.ace", "Ace.store.split.c01" }) + ); + } + + private async Task ReadAsync(string testArchive, CompressionType expectedCompression) + { + testArchive = Path.Combine(TEST_ARCHIVES_PATH, testArchive); + using Stream stream = File.OpenRead(testArchive); + await using var reader = ReaderFactory.OpenAsync( + new AsyncOnlyStream(stream), + new ReaderOptions() + ); + while (await reader.MoveToNextEntryAsync()) + { + if (!reader.Entry.IsDirectory) + { + Assert.Equal(expectedCompression, reader.Entry.CompressionType); + await reader.WriteEntryToDirectoryAsync( + SCRATCH_FILES_PATH, + new ExtractionOptions { ExtractFullPath = true, Overwrite = true } + ); + } + } + VerifyFiles(); + } + + private async Task ReadForBufferBoundaryCheckAsync(string testArchive, CompressionType expectedCompression) + { + testArchive = Path.Combine(TEST_ARCHIVES_PATH, testArchive); + using Stream stream = File.OpenRead(testArchive); + await using var reader = ReaderFactory.OpenAsync( + new AsyncOnlyStream(stream), + new ReaderOptions() { LookForHeader = false } + ); + while (await reader.MoveToNextEntryAsync()) + { + if (!reader.Entry.IsDirectory) + { + Assert.Equal(expectedCompression, reader.Entry.CompressionType); + await reader.WriteEntryToDirectoryAsync( + SCRATCH_FILES_PATH, + new ExtractionOptions { ExtractFullPath = true, Overwrite = true } + ); + } + } + VerifyFiles(); + } + + private async Task DoMultiReaderAsync(string[] archiveNames) + { + var testArchives = archiveNames.Select(s => Path.Combine(TEST_ARCHIVES_PATH, s)).ToList(); + var streams = testArchives.Select(File.OpenRead).ToList(); + try + { + await using var reader = ReaderFactory.OpenAsync(new AsyncOnlyStream(streams.First())); + while (await reader.MoveToNextEntryAsync()) + { + if (!reader.Entry.IsDirectory) + { + await reader.WriteEntryToDirectoryAsync( + SCRATCH_FILES_PATH, + new ExtractionOptions { ExtractFullPath = true, Overwrite = true } + ); + } + } + } + finally + { + foreach (var stream in streams) + { + stream.Dispose(); + } + } + } + } +} diff --git a/tests/SharpCompress.Test/Arj/ArjReaderAsyncTests.cs b/tests/SharpCompress.Test/Arj/ArjReaderAsyncTests.cs new file mode 100644 index 00000000..993cc781 --- /dev/null +++ b/tests/SharpCompress.Test/Arj/ArjReaderAsyncTests.cs @@ -0,0 +1,156 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using SharpCompress.Common; +using SharpCompress.Readers; +using SharpCompress.Readers.Arj; +using SharpCompress.Test.Mocks; +using Xunit; +using Xunit.Sdk; + +namespace SharpCompress.Test.Arj +{ + public class ArjReaderAsyncTests : ReaderTests + { + public ArjReaderAsyncTests() + { + UseExtensionInsteadOfNameToVerify = true; + UseCaseInsensitiveToVerify = true; + } + + [Fact] + public async ValueTask Arj_Uncompressed_Read_Async() => await ReadAsync("Arj.store.arj", CompressionType.None); + + [Fact] + public async ValueTask Arj_Method1_Read_Async() => await ReadAsync("Arj.method1.arj"); + + [Fact] + public async ValueTask Arj_Method2_Read_Async() => await ReadAsync("Arj.method2.arj"); + + [Fact] + public async ValueTask Arj_Method3_Read_Async() => await ReadAsync("Arj.method3.arj"); + + [Fact] + public async ValueTask Arj_Method4_Read_Async() => await ReadAsync("Arj.method4.arj"); + + [Fact] + public async ValueTask Arj_Encrypted_Read_Async() + { + var exception = await Assert.ThrowsAsync(() => ReadAsync("Arj.encrypted.arj")); + } + + [Fact] + public async ValueTask Arj_Multi_Reader_Async() + { + var exception = await Assert.ThrowsAsync(() => + DoMultiReaderAsync( + [ + "Arj.store.split.arj", + "Arj.store.split.a01", + "Arj.store.split.a02", + "Arj.store.split.a03", + "Arj.store.split.a04", + "Arj.store.split.a05", + ], + streams => ReaderFactory.OpenAsync(new AsyncOnlyStream(streams.First())) + ) + ); + } + + [Theory] + [InlineData("Arj.method1.largefile.arj", CompressionType.ArjLZ77)] + [InlineData("Arj.method2.largefile.arj", CompressionType.ArjLZ77)] + [InlineData("Arj.method3.largefile.arj", CompressionType.ArjLZ77)] + public async ValueTask Arj_LargeFile_ShouldThrow_Async(string fileName, CompressionType compressionType) + { + var exception = await Assert.ThrowsAsync(() => + ReadForBufferBoundaryCheckAsync(fileName, compressionType) + ); + } + + [Theory] + [InlineData("Arj.store.largefile.arj", CompressionType.None)] + [InlineData("Arj.method4.largefile.arj", CompressionType.ArjLZ77)] + public async ValueTask Arj_LargeFileTest_Read_Async(string fileName, CompressionType compressionType) + { + await ReadForBufferBoundaryCheckAsync(fileName, compressionType); + } + + private async Task ReadAsync(string testArchive, CompressionType? expectedCompression = null) + { + testArchive = Path.Combine(TEST_ARCHIVES_PATH, testArchive); + using Stream stream = File.OpenRead(testArchive); + await using var reader = ReaderFactory.OpenAsync( + new AsyncOnlyStream(stream), + new ReaderOptions() + ); + while (await reader.MoveToNextEntryAsync()) + { + if (!reader.Entry.IsDirectory) + { + if (expectedCompression.HasValue) + { + Assert.Equal(expectedCompression.Value, reader.Entry.CompressionType); + } + await reader.WriteEntryToDirectoryAsync( + SCRATCH_FILES_PATH, + new ExtractionOptions { ExtractFullPath = true, Overwrite = true } + ); + } + } + VerifyFiles(); + } + + private async Task ReadForBufferBoundaryCheckAsync(string testArchive, CompressionType expectedCompression) + { + testArchive = Path.Combine(TEST_ARCHIVES_PATH, testArchive); + using Stream stream = File.OpenRead(testArchive); + await using var reader = ReaderFactory.OpenAsync( + new AsyncOnlyStream(stream), + new ReaderOptions() { LookForHeader = false } + ); + while (await reader.MoveToNextEntryAsync()) + { + if (!reader.Entry.IsDirectory) + { + Assert.Equal(expectedCompression, reader.Entry.CompressionType); + await reader.WriteEntryToDirectoryAsync( + SCRATCH_FILES_PATH, + new ExtractionOptions { ExtractFullPath = true, Overwrite = true } + ); + } + } + VerifyFiles(); + } + + private async Task DoMultiReaderAsync(string[] archiveNames, Func, IAsyncReader> openReader) + { + var testArchives = archiveNames.Select(s => Path.Combine(TEST_ARCHIVES_PATH, s)).ToList(); + var streams = testArchives.Select(File.OpenRead).ToList(); + try + { + await using var reader = openReader(streams); + while (await reader.MoveToNextEntryAsync()) + { + if (!reader.Entry.IsDirectory) + { + await reader.WriteEntryToDirectoryAsync( + SCRATCH_FILES_PATH, + new ExtractionOptions { ExtractFullPath = true, Overwrite = true } + ); + } + } + } + finally + { + foreach (var stream in streams) + { + stream.Dispose(); + } + } + } + } +} diff --git a/tests/SharpCompress.Test/BZip2/BZip2StreamAsyncTests.cs b/tests/SharpCompress.Test/BZip2/BZip2StreamAsyncTests.cs index 0c2d62d8..5ccfde90 100644 --- a/tests/SharpCompress.Test/BZip2/BZip2StreamAsyncTests.cs +++ b/tests/SharpCompress.Test/BZip2/BZip2StreamAsyncTests.cs @@ -4,6 +4,7 @@ using System.IO; using System.Text; using System.Threading.Tasks; using SharpCompress.Compressors.BZip2; +using SharpCompress.Test.Mocks; using Xunit; namespace SharpCompress.Test.BZip2; @@ -32,7 +33,7 @@ public class BZip2StreamAsyncTests { using ( var bzip2Stream = new BZip2Stream( - memoryStream, + new AsyncOnlyStream(memoryStream), SharpCompress.Compressors.CompressionMode.Compress, false ) @@ -54,7 +55,7 @@ public class BZip2StreamAsyncTests { using ( var bzip2Stream = new BZip2Stream( - memoryStream, + new AsyncOnlyStream(memoryStream), SharpCompress.Compressors.CompressionMode.Decompress, false ) @@ -93,7 +94,7 @@ public class BZip2StreamAsyncTests { using ( var bzip2Stream = new BZip2Stream( - memoryStream, + new AsyncOnlyStream(memoryStream), SharpCompress.Compressors.CompressionMode.Compress, false ) @@ -110,7 +111,7 @@ public class BZip2StreamAsyncTests { using ( var bzip2Stream = new BZip2Stream( - memoryStream, + new AsyncOnlyStream(memoryStream), SharpCompress.Compressors.CompressionMode.Decompress, false ) @@ -133,7 +134,7 @@ public class BZip2StreamAsyncTests { using ( var bzip2Stream = new BZip2Stream( - memoryStream, + new AsyncOnlyStream(memoryStream), SharpCompress.Compressors.CompressionMode.Compress, false ) @@ -158,7 +159,7 @@ public class BZip2StreamAsyncTests { using ( var bzip2Stream = new BZip2Stream( - readStream, + new AsyncOnlyStream(memoryStream), SharpCompress.Compressors.CompressionMode.Decompress, false ) @@ -189,7 +190,7 @@ public class BZip2StreamAsyncTests { using ( var bzip2Stream = new BZip2Stream( - memoryStream, + new AsyncOnlyStream(memoryStream), SharpCompress.Compressors.CompressionMode.Compress, false ) @@ -207,7 +208,7 @@ public class BZip2StreamAsyncTests { using ( var bzip2Stream = new BZip2Stream( - memoryStream, + new AsyncOnlyStream(memoryStream), SharpCompress.Compressors.CompressionMode.Decompress, false ) diff --git a/tests/SharpCompress.Test/Xz/XZStreamAsyncTests.cs b/tests/SharpCompress.Test/Xz/XZStreamAsyncTests.cs index 53f97bb6..a2276602 100644 --- a/tests/SharpCompress.Test/Xz/XZStreamAsyncTests.cs +++ b/tests/SharpCompress.Test/Xz/XZStreamAsyncTests.cs @@ -1,6 +1,7 @@ using System.IO; using System.Threading.Tasks; using SharpCompress.Compressors.Xz; +using SharpCompress.Test.Mocks; using Xunit; namespace SharpCompress.Test.Xz; @@ -11,7 +12,7 @@ public class XzStreamAsyncTests : XzTestsBase public async ValueTask CanReadEmptyStreamAsync() { var xz = new XZStream(CompressedEmptyStream); - using var sr = new StreamReader(xz); + using var sr = new StreamReader(new AsyncOnlyStream(xz)); var uncompressed = await sr.ReadToEndAsync().ConfigureAwait(false); Assert.Equal(OriginalEmpty, uncompressed); } @@ -20,7 +21,7 @@ public class XzStreamAsyncTests : XzTestsBase public async ValueTask CanReadStreamAsync() { var xz = new XZStream(CompressedStream); - using var sr = new StreamReader(xz); + using var sr = new StreamReader(new AsyncOnlyStream(xz)); var uncompressed = await sr.ReadToEndAsync().ConfigureAwait(false); Assert.Equal(Original, uncompressed); } @@ -29,7 +30,7 @@ public class XzStreamAsyncTests : XzTestsBase public async ValueTask CanReadIndexedStreamAsync() { var xz = new XZStream(CompressedIndexedStream); - using var sr = new StreamReader(xz); + using var sr = new StreamReader(new AsyncOnlyStream(xz)); var uncompressed = await sr.ReadToEndAsync().ConfigureAwait(false); Assert.Equal(OriginalIndexed, uncompressed); } From 81a2060c7560d250aa853ce7105d02ad1530e76b Mon Sep 17 00:00:00 2001 From: Adam Hathcock Date: Wed, 14 Jan 2026 15:33:08 +0000 Subject: [PATCH 4/8] reduce memory usage on headers --- src/SharpCompress/Common/AsyncBinaryReader.cs | 11 +- .../Common/Zip/Headers/DirectoryEndHeader.cs | 3 +- .../Zip/Headers/DirectoryEntryHeader.cs | 10 +- .../Common/Zip/Headers/LocalEntryHeader.cs | 6 +- .../Zip/Headers/Zip64DirectoryEndHeader.cs | 10 +- .../Common/Zip/SeekableZipHeaderFactory.cs | 116 +++++------------- .../Common/Zip/ZipHeaderFactory.cs | 2 +- 7 files changed, 53 insertions(+), 105 deletions(-) diff --git a/src/SharpCompress/Common/AsyncBinaryReader.cs b/src/SharpCompress/Common/AsyncBinaryReader.cs index 51da5d5c..2b963944 100644 --- a/src/SharpCompress/Common/AsyncBinaryReader.cs +++ b/src/SharpCompress/Common/AsyncBinaryReader.cs @@ -51,11 +51,14 @@ namespace SharpCompress.Common return BinaryPrimitives.ReadUInt64LittleEndian(_buffer); } - public async ValueTask ReadBytesAsync(int count, CancellationToken ct = default) + public async ValueTask ReadBytesAsync(byte[] bytes, int offset, int count, CancellationToken ct = default) { - var result = new byte[count]; - await _stream.ReadExactAsync(result, 0, count, ct).ConfigureAwait(false); - return result; + await _stream.ReadExactAsync(bytes, offset, count, ct).ConfigureAwait(false); + } + + public async ValueTask SkipAsync(int count, CancellationToken ct = default) + { + await _stream.SkipAsync( count, ct).ConfigureAwait(false); } public void Dispose() diff --git a/src/SharpCompress/Common/Zip/Headers/DirectoryEndHeader.cs b/src/SharpCompress/Common/Zip/Headers/DirectoryEndHeader.cs index 7d35f3ea..068358cf 100644 --- a/src/SharpCompress/Common/Zip/Headers/DirectoryEndHeader.cs +++ b/src/SharpCompress/Common/Zip/Headers/DirectoryEndHeader.cs @@ -29,7 +29,8 @@ internal class DirectoryEndHeader : ZipHeader DirectorySize = await reader.ReadUInt32Async(); DirectoryStartOffsetRelativeToDisk = await reader.ReadUInt32Async(); CommentLength = await reader.ReadUInt16Async(); - Comment = await reader.ReadBytesAsync(CommentLength); + Comment = new byte[CommentLength]; + await reader.ReadBytesAsync(Comment, 0, CommentLength); } public ushort VolumeNumber { get; private set; } diff --git a/src/SharpCompress/Common/Zip/Headers/DirectoryEntryHeader.cs b/src/SharpCompress/Common/Zip/Headers/DirectoryEntryHeader.cs index a9ed564f..79430b02 100644 --- a/src/SharpCompress/Common/Zip/Headers/DirectoryEntryHeader.cs +++ b/src/SharpCompress/Common/Zip/Headers/DirectoryEntryHeader.cs @@ -53,10 +53,12 @@ internal class DirectoryEntryHeader : ZipFileEntry InternalFileAttributes = await reader.ReadUInt16Async(); ExternalFileAttributes = await reader.ReadUInt32Async(); RelativeOffsetOfEntryHeader = await reader.ReadUInt32Async(); - - var name = await reader.ReadBytesAsync(nameLength); - var extra = await reader.ReadBytesAsync(extraLength); - var comment = await reader.ReadBytesAsync(commentLength); + var name = new byte[nameLength]; + var extra = new byte[extraLength]; + var comment = new byte[commentLength]; + await reader.ReadBytesAsync(name,0 ,nameLength); + await reader.ReadBytesAsync(extra, 0, extraLength); + await reader.ReadBytesAsync(comment, 0, commentLength); ProcessReadData(name, extra, comment); } diff --git a/src/SharpCompress/Common/Zip/Headers/LocalEntryHeader.cs b/src/SharpCompress/Common/Zip/Headers/LocalEntryHeader.cs index 9091d454..be33793d 100644 --- a/src/SharpCompress/Common/Zip/Headers/LocalEntryHeader.cs +++ b/src/SharpCompress/Common/Zip/Headers/LocalEntryHeader.cs @@ -37,8 +37,10 @@ internal class LocalEntryHeader(IArchiveEncoding archiveEncoding) UncompressedSize = await reader.ReadUInt32Async(); var nameLength = await reader.ReadUInt16Async(); var extraLength = await reader.ReadUInt16Async(); - var name = await reader.ReadBytesAsync(nameLength); - var extra = await reader.ReadBytesAsync(extraLength); + var name = new byte[nameLength]; + var extra = new byte[extraLength]; + await reader.ReadBytesAsync(name,0 ,nameLength); + await reader.ReadBytesAsync(extra, 0, extraLength); ProcessReadData(name, extra); } diff --git a/src/SharpCompress/Common/Zip/Headers/Zip64DirectoryEndHeader.cs b/src/SharpCompress/Common/Zip/Headers/Zip64DirectoryEndHeader.cs index b15b6f16..c5d5aa8a 100644 --- a/src/SharpCompress/Common/Zip/Headers/Zip64DirectoryEndHeader.cs +++ b/src/SharpCompress/Common/Zip/Headers/Zip64DirectoryEndHeader.cs @@ -38,12 +38,12 @@ internal class Zip64DirectoryEndHeader : ZipHeader TotalNumberOfEntries = (long)await reader.ReadUInt64Async(); DirectorySize = (long)await reader.ReadUInt64Async(); DirectoryStartOffsetRelativeToDisk = (long)await reader.ReadUInt64Async(); - DataSector = await reader.ReadBytesAsync( - (int)( - SizeOfDirectoryEndRecord - - SIZE_OF_FIXED_HEADER_DATA_EXCEPT_SIGNATURE_AND_SIZE_FIELDS - ) + var size = (int)( + SizeOfDirectoryEndRecord + - SIZE_OF_FIXED_HEADER_DATA_EXCEPT_SIGNATURE_AND_SIZE_FIELDS ); + DataSector = new byte[size]; + await reader.ReadBytesAsync(DataSector, 0, size); } private const int SIZE_OF_FIXED_HEADER_DATA_EXCEPT_SIGNATURE_AND_SIZE_FIELDS = 44; diff --git a/src/SharpCompress/Common/Zip/SeekableZipHeaderFactory.cs b/src/SharpCompress/Common/Zip/SeekableZipHeaderFactory.cs index 90856622..6e05216b 100644 --- a/src/SharpCompress/Common/Zip/SeekableZipHeaderFactory.cs +++ b/src/SharpCompress/Common/Zip/SeekableZipHeaderFactory.cs @@ -1,4 +1,5 @@ using System; +using System.Buffers; using System.Collections.Generic; using System.IO; using System.Threading.Tasks; @@ -16,6 +17,8 @@ internal sealed class SeekableZipHeaderFactory : ZipHeaderFactory private const int MAX_SEARCH_LENGTH_FOR_EOCD = 65557; private bool _zip64; + private static readonly byte[] needle = { 0x06, 0x05, 0x4b, 0x50 }; + internal SeekableZipHeaderFactory(string? password, IArchiveEncoding archiveEncoding) : base(StreamingMode.Seekable, password, archiveEncoding) { } @@ -153,74 +156,8 @@ internal sealed class SeekableZipHeaderFactory : ZipHeaderFactory } } - internal async IAsyncEnumerable ReadSeekableHeaderAsync(Stream stream, bool useSync) - { - var reader = new AsyncBinaryReader(stream); - await SeekBackToHeaderAsync(stream, reader); - - var eocd_location = stream.Position; - var entry = new DirectoryEndHeader(); - await entry.Read(reader); - - if (entry.IsZip64) - { - _zip64 = true; - - // ZIP64_END_OF_CENTRAL_DIRECTORY_LOCATOR should be before the EOCD - stream.Seek(eocd_location - ZIP64_EOCD_LENGTH - 4, SeekOrigin.Begin); - var zip64_locator = await reader.ReadUInt32Async(); - if (zip64_locator != ZIP64_END_OF_CENTRAL_DIRECTORY_LOCATOR) - { - throw new ArchiveException("Failed to locate the Zip64 Directory Locator"); - } - - var zip64Locator = new Zip64DirectoryEndLocatorHeader(); - await zip64Locator.Read(reader); - - stream.Seek(zip64Locator.RelativeOffsetOfTheEndOfDirectoryRecord, SeekOrigin.Begin); - var zip64Signature = await reader.ReadUInt32Async(); - if (zip64Signature != ZIP64_END_OF_CENTRAL_DIRECTORY) - { - throw new ArchiveException("Failed to locate the Zip64 Header"); - } - - var zip64Entry = new Zip64DirectoryEndHeader(); - await zip64Entry.Read(reader); - stream.Seek(zip64Entry.DirectoryStartOffsetRelativeToDisk, SeekOrigin.Begin); - } - else - { - stream.Seek(entry.DirectoryStartOffsetRelativeToDisk, SeekOrigin.Begin); - } - - var position = stream.Position; - while (true) - { - stream.Position = position; - var signature = await reader.ReadUInt32Async(); - var nextHeader = await ReadHeader(signature, reader, _zip64); - position = stream.Position; - - if (nextHeader is null) - { - yield break; - } - - if (nextHeader is DirectoryEntryHeader entryHeader) - { - //entry could be zero bytes so we need to know that. - entryHeader.HasData = entryHeader.CompressedSize != 0; - yield return entryHeader; - } - else if (nextHeader is DirectoryEndHeader endHeader) - { - yield return endHeader; - } - } - } - - private static bool IsMatch(byte[] haystack, int position, byte[] needle) + private static bool IsMatch(Span haystack, int position, byte[] needle) { for (var i = 0; i < needle.Length; i++) { @@ -247,29 +184,35 @@ internal sealed class SeekableZipHeaderFactory : ZipHeaderFactory stream.Length < MAX_SEARCH_LENGTH_FOR_EOCD ? (int)stream.Length : MAX_SEARCH_LENGTH_FOR_EOCD; - // We search for marker in reverse to find the first occurance - byte[] needle = { 0x06, 0x05, 0x4b, 0x50 }; stream.Seek(-len, SeekOrigin.End); + var seek = ArrayPool.Shared.Rent(len); - var seek = await reader.ReadBytesAsync(len); - - // Search in reverse - Array.Reverse(seek); - - // don't exclude the minimum eocd region, otherwise you fail to locate the header in empty zip files - var max_search_area = len; // - MINIMUM_EOCD_LENGTH; - - for (var pos_from_end = 0; pos_from_end < max_search_area; ++pos_from_end) + try { - if (IsMatch(seek, pos_from_end, needle)) - { - stream.Seek(-pos_from_end, SeekOrigin.End); - return; - } - } + await reader.ReadBytesAsync(seek, 0, len, default); + var memory = new Memory(seek, 0, len); + var span = memory.Span; + span.Reverse(); - throw new ArchiveException("Failed to locate the Zip Header"); + // don't exclude the minimum eocd region, otherwise you fail to locate the header in empty zip files + var max_search_area = len; // - MINIMUM_EOCD_LENGTH; + + for (var pos_from_end = 0; pos_from_end < max_search_area; ++pos_from_end) + { + if (IsMatch(span, pos_from_end, needle)) + { + stream.Seek(-pos_from_end, SeekOrigin.End); + return; + } + } + + throw new ArchiveException("Failed to locate the Zip Header"); + } + finally + { + ArrayPool.Shared.Return(seek); + } } private static void SeekBackToHeader(Stream stream, BinaryReader reader) @@ -286,9 +229,6 @@ internal sealed class SeekableZipHeaderFactory : ZipHeaderFactory stream.Length < MAX_SEARCH_LENGTH_FOR_EOCD ? (int)stream.Length : MAX_SEARCH_LENGTH_FOR_EOCD; - // We search for marker in reverse to find the first occurance - byte[] needle = { 0x06, 0x05, 0x4b, 0x50 }; - stream.Seek(-len, SeekOrigin.End); var seek = reader.ReadBytes(len); diff --git a/src/SharpCompress/Common/Zip/ZipHeaderFactory.cs b/src/SharpCompress/Common/Zip/ZipHeaderFactory.cs index 7238dda5..44e40734 100644 --- a/src/SharpCompress/Common/Zip/ZipHeaderFactory.cs +++ b/src/SharpCompress/Common/Zip/ZipHeaderFactory.cs @@ -79,7 +79,7 @@ internal class ZipHeaderFactory } else { - await reader.ReadBytesAsync(zip64 ? 20 : 12); + await reader.SkipAsync(zip64 ? 20 : 12); } return null; } From 437271c6a24c054c43211b17e35c4e742dcfc626 Mon Sep 17 00:00:00 2001 From: Adam Hathcock Date: Wed, 14 Jan 2026 15:55:14 +0000 Subject: [PATCH 5/8] change byte[] to memory using pool --- .../Compressors/Deflate/Inflate.cs | 36 ++++++++++--------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/src/SharpCompress/Compressors/Deflate/Inflate.cs b/src/SharpCompress/Compressors/Deflate/Inflate.cs index fd1c764a..ca00e28a 100644 --- a/src/SharpCompress/Compressors/Deflate/Inflate.cs +++ b/src/SharpCompress/Compressors/Deflate/Inflate.cs @@ -64,6 +64,7 @@ // ----------------------------------------------------------------------- using System; +using System.Buffers; using SharpCompress.Algorithms; namespace SharpCompress.Compressors.Deflate; @@ -116,14 +117,14 @@ internal sealed class InflateBlocks internal int readAt; // window read pointer internal int table; // table lengths (14 bits) internal int[] tb = new int[1]; // bit length decoding tree - internal byte[] window; // sliding window + internal IMemoryOwner window; // sliding window internal int writeAt; // window write pointer internal InflateBlocks(ZlibCodec codec, object checkfn, int w) { _codec = codec; hufts = new int[MANY * 3]; - window = new byte[w]; + window = MemoryPool.Shared.Rent(w); end = w; this.checkfn = checkfn; mode = InflateBlockMode.TYPE; @@ -340,7 +341,7 @@ internal sealed class InflateBlocks { t = m; } - Array.Copy(_codec.InputBuffer, p, window, q, t); + _codec.InputBuffer.AsSpan(p, t).CopyTo(window.Memory.Span.Slice(q)); p += t; n -= t; q += t; @@ -715,13 +716,14 @@ internal sealed class InflateBlocks internal void Free() { Reset(); + window?.Dispose(); window = null; hufts = null; } internal void SetDictionary(byte[] d, int start, int n) { - Array.Copy(d, start, window, 0, n); + d.AsSpan(start, n).CopyTo(window.Memory.Span.Slice(0, n)); readAt = writeAt = n; } @@ -774,11 +776,11 @@ internal sealed class InflateBlocks // update check information if (checkfn != null) { - _codec._adler32 = check = Adler32.Calculate(check, window.AsSpan(readAt, nBytes)); + _codec._adler32 = check = Adler32.Calculate(check, window.Memory.Span.Slice(readAt, nBytes)); } // copy as far as end of window - Array.Copy(window, readAt, _codec.OutputBuffer, _codec.NextOut, nBytes); + window.Memory.Span.Slice(readAt, nBytes).CopyTo(_codec.OutputBuffer.AsSpan(_codec.NextOut)); _codec.NextOut += nBytes; readAt += nBytes; @@ -1213,7 +1215,7 @@ internal sealed class InflateCodes } } - blocks.window[q++] = blocks.window[f++]; + blocks.window.Memory.Span[q++] = blocks.window.Memory.Span[f++]; m--; if (f == blocks.end) @@ -1259,7 +1261,7 @@ internal sealed class InflateCodes } r = ZlibConstants.Z_OK; - blocks.window[q++] = (byte)lit; + blocks.window.Memory.Span[q++] = (byte)lit; m--; mode = START; @@ -1396,7 +1398,7 @@ internal sealed class InflateCodes b >>= (tp[tp_index_t_3 + 1]); k -= (tp[tp_index_t_3 + 1]); - s.window[q++] = (byte)tp[tp_index_t_3 + 2]; + s.window.Memory.Span[q++] = (byte)tp[tp_index_t_3 + 2]; m--; continue; } @@ -1461,13 +1463,13 @@ internal sealed class InflateCodes r = q - d; if (q - r > 0 && 2 > (q - r)) { - s.window[q++] = s.window[r++]; // minimum count is three, - s.window[q++] = s.window[r++]; // so unroll loop a little + s.window.Memory.Span[q++] = s.window.Memory.Span[r++]; // minimum count is three, + s.window.Memory.Span[q++] = s.window.Memory.Span[r++]; // so unroll loop a little c -= 2; } else { - Array.Copy(s.window, r, s.window, q, 2); + s.window.Memory.Span.Slice(r, 2).CopyTo(s.window.Memory.Span.Slice(q)); q += 2; r += 2; c -= 2; @@ -1490,12 +1492,12 @@ internal sealed class InflateCodes { do { - s.window[q++] = s.window[r++]; + s.window.Memory.Span[q++] = s.window.Memory.Span[r++]; } while (--e != 0); } else { - Array.Copy(s.window, r, s.window, q, e); + s.window.Memory.Span.Slice(r, e).CopyTo(s.window.Memory.Span.Slice(q)); q += e; r += e; e = 0; @@ -1509,12 +1511,12 @@ internal sealed class InflateCodes { do { - s.window[q++] = s.window[r++]; + s.window.Memory.Span[q++] = s.window.Memory.Span[r++]; } while (--c != 0); } else { - Array.Copy(s.window, r, s.window, q, c); + s.window.Memory.Span.Slice(r, c).CopyTo(s.window.Memory.Span.Slice(q)); q += c; r += c; c = 0; @@ -1560,7 +1562,7 @@ internal sealed class InflateCodes { b >>= (tp[tp_index_t_3 + 1]); k -= (tp[tp_index_t_3 + 1]); - s.window[q++] = (byte)tp[tp_index_t_3 + 2]; + s.window.Memory.Span[q++] = (byte)tp[tp_index_t_3 + 2]; m--; break; } From 38eec23e079ff26ac6ddeaff7fa971d5c123bce8 Mon Sep 17 00:00:00 2001 From: Adam Hathcock Date: Wed, 14 Jan 2026 16:38:57 +0000 Subject: [PATCH 6/8] rar byte[] better --- src/SharpCompress/Archives/Rar/RarArchive.cs | 14 ++++++++++++++ src/SharpCompress/Compressors/Rar/RarStream.cs | 2 +- .../Compressors/Rar/UnpackV1/Unpack.cs | 14 +++++--------- 3 files changed, 20 insertions(+), 10 deletions(-) diff --git a/src/SharpCompress/Archives/Rar/RarArchive.cs b/src/SharpCompress/Archives/Rar/RarArchive.cs index d67dd15c..9bfde20b 100644 --- a/src/SharpCompress/Archives/Rar/RarArchive.cs +++ b/src/SharpCompress/Archives/Rar/RarArchive.cs @@ -48,6 +48,20 @@ public partial class RarArchive : AbstractArchive, I } } + public override async ValueTask DisposeAsync() + { + if (!_disposed) + { + if (UnpackV1.IsValueCreated && UnpackV1.Value is IDisposable unpackV1) + { + unpackV1.Dispose(); + } + + _disposed = true; + await base.DisposeAsync(); + } + } + protected override IEnumerable LoadEntries(IEnumerable volumes) => RarArchiveEntryFactory.GetEntries(this, volumes, ReaderOptions); diff --git a/src/SharpCompress/Compressors/Rar/RarStream.cs b/src/SharpCompress/Compressors/Rar/RarStream.cs index 7f258bc5..21c225c3 100644 --- a/src/SharpCompress/Compressors/Rar/RarStream.cs +++ b/src/SharpCompress/Compressors/Rar/RarStream.cs @@ -87,10 +87,10 @@ internal class RarStream : Stream, IStreamStack #endif ArrayPool.Shared.Return(this.tmpBuffer); this.tmpBuffer = null; + readStream.Dispose(); } isDisposed = true; base.Dispose(disposing); - readStream.Dispose(); } } diff --git a/src/SharpCompress/Compressors/Rar/UnpackV1/Unpack.cs b/src/SharpCompress/Compressors/Rar/UnpackV1/Unpack.cs index 1518830a..4f2120a7 100644 --- a/src/SharpCompress/Compressors/Rar/UnpackV1/Unpack.cs +++ b/src/SharpCompress/Compressors/Rar/UnpackV1/Unpack.cs @@ -126,17 +126,13 @@ internal sealed partial class Unpack : BitInput, IRarUnpack private FileHeader fileHeader; - private void Init(byte[] window) + + private void Init() { - if (this.window is null && window is null) + if (this.window is null) { this.window = ArrayPool.Shared.Rent(PackDef.MAXWINSIZE); } - else if (window is not null) - { - this.window = window; - externalWindow = true; - } inAddr = 0; UnpInitData(false); } @@ -149,7 +145,7 @@ internal sealed partial class Unpack : BitInput, IRarUnpack this.writeStream = writeStream; if (!fileHeader.IsSolid) { - Init(null); + Init(); } suspended = false; DoUnpack(); @@ -168,7 +164,7 @@ internal sealed partial class Unpack : BitInput, IRarUnpack this.writeStream = writeStream; if (!fileHeader.IsSolid) { - Init(null); + Init(); } suspended = false; await DoUnpackAsync(cancellationToken).ConfigureAwait(false); From 227fec66ad7403a1bf4650f552d1cbac3cef6280 Mon Sep 17 00:00:00 2001 From: Adam Hathcock Date: Wed, 14 Jan 2026 16:49:34 +0000 Subject: [PATCH 7/8] more pooling --- src/SharpCompress/IO/BufferedSubStream.cs | 8 ++++++-- src/SharpCompress/IO/SharpCompressStream.cs | 2 -- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/SharpCompress/IO/BufferedSubStream.cs b/src/SharpCompress/IO/BufferedSubStream.cs index f9216216..f5232aed 100755 --- a/src/SharpCompress/IO/BufferedSubStream.cs +++ b/src/SharpCompress/IO/BufferedSubStream.cs @@ -1,4 +1,5 @@ using System; +using System.Buffers; using System.IO; using System.Threading; using System.Threading.Tasks; @@ -28,13 +29,16 @@ internal class BufferedSubStream : SharpCompressStream, IStreamStack #if DEBUG_STREAMS this.DebugDispose(typeof(BufferedSubStream)); #endif - if (disposing) { } + if (disposing) + { + ArrayPool.Shared.Return(_cache); + } base.Dispose(disposing); } private int _cacheOffset; private int _cacheLength; - private readonly byte[] _cache = new byte[32 << 10]; + private readonly byte[] _cache = ArrayPool.Shared.Rent(32 << 10); private long origin; private long BytesLeftToRead { get; set; } diff --git a/src/SharpCompress/IO/SharpCompressStream.cs b/src/SharpCompress/IO/SharpCompressStream.cs index 8261505f..948fdb57 100644 --- a/src/SharpCompress/IO/SharpCompressStream.cs +++ b/src/SharpCompress/IO/SharpCompressStream.cs @@ -1,8 +1,6 @@ using System; using System.Buffers; -using System.Diagnostics; using System.IO; -using System.Text; using System.Threading; using System.Threading.Tasks; From ec310c87de7ed03efa4d018e20638ea81bb40dcb Mon Sep 17 00:00:00 2001 From: Adam Hathcock Date: Thu, 15 Jan 2026 15:20:52 +0000 Subject: [PATCH 8/8] merge fixes and fmt --- src/SharpCompress/Common/AsyncBinaryReader.cs | 9 +++- .../Zip/Headers/DirectoryEntryHeader.cs | 2 +- .../Common/Zip/Headers/LocalEntryHeader.cs | 4 +- .../Zip/Headers/Zip64DirectoryEndHeader.cs | 5 +-- .../Common/Zip/SeekableZipHeaderFactory.cs | 1 - .../Compressors/Deflate/Inflate.cs | 18 +++++--- .../Compressors/Rar/UnpackV1/Unpack.cs | 1 - src/SharpCompress/IO/BufferedSubStream.cs | 2 +- .../Ace/AceReaderAsyncTests.cs | 27 ++++++++---- .../Arj/ArjReaderAsyncTests.cs | 42 ++++++++++++++----- .../BZip2/BZip2StreamAsyncTests.cs | 2 +- .../GZip/GZipReaderAsyncTests.cs | 8 +++- .../Rar/RarArchiveAsyncTests.cs | 4 +- .../SevenZip/SevenZipArchiveAsyncTests.cs | 20 ++++++--- .../Tar/TarArchiveAsyncTests.cs | 20 +++++++-- .../Tar/TarReaderAsyncTests.cs | 2 +- .../SharpCompress.Test/Zip/Zip64AsyncTests.cs | 5 ++- .../Zip/ZipMemoryArchiveWithCrcAsyncTests.cs | 8 +++- 18 files changed, 132 insertions(+), 48 deletions(-) diff --git a/src/SharpCompress/Common/AsyncBinaryReader.cs b/src/SharpCompress/Common/AsyncBinaryReader.cs index 2b963944..8c5327ae 100644 --- a/src/SharpCompress/Common/AsyncBinaryReader.cs +++ b/src/SharpCompress/Common/AsyncBinaryReader.cs @@ -51,14 +51,19 @@ namespace SharpCompress.Common return BinaryPrimitives.ReadUInt64LittleEndian(_buffer); } - public async ValueTask ReadBytesAsync(byte[] bytes, int offset, int count, CancellationToken ct = default) + public async ValueTask ReadBytesAsync( + byte[] bytes, + int offset, + int count, + CancellationToken ct = default + ) { await _stream.ReadExactAsync(bytes, offset, count, ct).ConfigureAwait(false); } public async ValueTask SkipAsync(int count, CancellationToken ct = default) { - await _stream.SkipAsync( count, ct).ConfigureAwait(false); + await _stream.SkipAsync(count, ct).ConfigureAwait(false); } public void Dispose() diff --git a/src/SharpCompress/Common/Zip/Headers/DirectoryEntryHeader.cs b/src/SharpCompress/Common/Zip/Headers/DirectoryEntryHeader.cs index 79430b02..b19aeea5 100644 --- a/src/SharpCompress/Common/Zip/Headers/DirectoryEntryHeader.cs +++ b/src/SharpCompress/Common/Zip/Headers/DirectoryEntryHeader.cs @@ -56,7 +56,7 @@ internal class DirectoryEntryHeader : ZipFileEntry var name = new byte[nameLength]; var extra = new byte[extraLength]; var comment = new byte[commentLength]; - await reader.ReadBytesAsync(name,0 ,nameLength); + await reader.ReadBytesAsync(name, 0, nameLength); await reader.ReadBytesAsync(extra, 0, extraLength); await reader.ReadBytesAsync(comment, 0, commentLength); diff --git a/src/SharpCompress/Common/Zip/Headers/LocalEntryHeader.cs b/src/SharpCompress/Common/Zip/Headers/LocalEntryHeader.cs index be33793d..d676dde0 100644 --- a/src/SharpCompress/Common/Zip/Headers/LocalEntryHeader.cs +++ b/src/SharpCompress/Common/Zip/Headers/LocalEntryHeader.cs @@ -39,8 +39,8 @@ internal class LocalEntryHeader(IArchiveEncoding archiveEncoding) var extraLength = await reader.ReadUInt16Async(); var name = new byte[nameLength]; var extra = new byte[extraLength]; - await reader.ReadBytesAsync(name,0 ,nameLength); - await reader.ReadBytesAsync(extra, 0, extraLength); + await reader.ReadBytesAsync(name, 0, nameLength); + await reader.ReadBytesAsync(extra, 0, extraLength); ProcessReadData(name, extra); } diff --git a/src/SharpCompress/Common/Zip/Headers/Zip64DirectoryEndHeader.cs b/src/SharpCompress/Common/Zip/Headers/Zip64DirectoryEndHeader.cs index c5d5aa8a..cdd412b2 100644 --- a/src/SharpCompress/Common/Zip/Headers/Zip64DirectoryEndHeader.cs +++ b/src/SharpCompress/Common/Zip/Headers/Zip64DirectoryEndHeader.cs @@ -39,11 +39,10 @@ internal class Zip64DirectoryEndHeader : ZipHeader DirectorySize = (long)await reader.ReadUInt64Async(); DirectoryStartOffsetRelativeToDisk = (long)await reader.ReadUInt64Async(); var size = (int)( - SizeOfDirectoryEndRecord - - SIZE_OF_FIXED_HEADER_DATA_EXCEPT_SIGNATURE_AND_SIZE_FIELDS + SizeOfDirectoryEndRecord - SIZE_OF_FIXED_HEADER_DATA_EXCEPT_SIGNATURE_AND_SIZE_FIELDS ); DataSector = new byte[size]; - await reader.ReadBytesAsync(DataSector, 0, size); + await reader.ReadBytesAsync(DataSector, 0, size); } private const int SIZE_OF_FIXED_HEADER_DATA_EXCEPT_SIGNATURE_AND_SIZE_FIELDS = 44; diff --git a/src/SharpCompress/Common/Zip/SeekableZipHeaderFactory.cs b/src/SharpCompress/Common/Zip/SeekableZipHeaderFactory.cs index 6e05216b..971ffa3c 100644 --- a/src/SharpCompress/Common/Zip/SeekableZipHeaderFactory.cs +++ b/src/SharpCompress/Common/Zip/SeekableZipHeaderFactory.cs @@ -156,7 +156,6 @@ internal sealed class SeekableZipHeaderFactory : ZipHeaderFactory } } - private static bool IsMatch(Span haystack, int position, byte[] needle) { for (var i = 0; i < needle.Length; i++) diff --git a/src/SharpCompress/Compressors/Deflate/Inflate.cs b/src/SharpCompress/Compressors/Deflate/Inflate.cs index ca00e28a..aff2c659 100644 --- a/src/SharpCompress/Compressors/Deflate/Inflate.cs +++ b/src/SharpCompress/Compressors/Deflate/Inflate.cs @@ -776,11 +776,16 @@ internal sealed class InflateBlocks // update check information if (checkfn != null) { - _codec._adler32 = check = Adler32.Calculate(check, window.Memory.Span.Slice(readAt, nBytes)); + _codec._adler32 = check = Adler32.Calculate( + check, + window.Memory.Span.Slice(readAt, nBytes) + ); } // copy as far as end of window - window.Memory.Span.Slice(readAt, nBytes).CopyTo(_codec.OutputBuffer.AsSpan(_codec.NextOut)); + window + .Memory.Span.Slice(readAt, nBytes) + .CopyTo(_codec.OutputBuffer.AsSpan(_codec.NextOut)); _codec.NextOut += nBytes; readAt += nBytes; @@ -1469,7 +1474,8 @@ internal sealed class InflateCodes } else { - s.window.Memory.Span.Slice(r, 2).CopyTo(s.window.Memory.Span.Slice(q)); + s.window.Memory.Span.Slice(r, 2) + .CopyTo(s.window.Memory.Span.Slice(q)); q += 2; r += 2; c -= 2; @@ -1497,7 +1503,8 @@ internal sealed class InflateCodes } else { - s.window.Memory.Span.Slice(r, e).CopyTo(s.window.Memory.Span.Slice(q)); + s.window.Memory.Span.Slice(r, e) + .CopyTo(s.window.Memory.Span.Slice(q)); q += e; r += e; e = 0; @@ -1516,7 +1523,8 @@ internal sealed class InflateCodes } else { - s.window.Memory.Span.Slice(r, c).CopyTo(s.window.Memory.Span.Slice(q)); + s.window.Memory.Span.Slice(r, c) + .CopyTo(s.window.Memory.Span.Slice(q)); q += c; r += c; c = 0; diff --git a/src/SharpCompress/Compressors/Rar/UnpackV1/Unpack.cs b/src/SharpCompress/Compressors/Rar/UnpackV1/Unpack.cs index 4f2120a7..18c2c2e3 100644 --- a/src/SharpCompress/Compressors/Rar/UnpackV1/Unpack.cs +++ b/src/SharpCompress/Compressors/Rar/UnpackV1/Unpack.cs @@ -126,7 +126,6 @@ internal sealed partial class Unpack : BitInput, IRarUnpack private FileHeader fileHeader; - private void Init() { if (this.window is null) diff --git a/src/SharpCompress/IO/BufferedSubStream.cs b/src/SharpCompress/IO/BufferedSubStream.cs index f5232aed..747c9776 100755 --- a/src/SharpCompress/IO/BufferedSubStream.cs +++ b/src/SharpCompress/IO/BufferedSubStream.cs @@ -38,7 +38,7 @@ internal class BufferedSubStream : SharpCompressStream, IStreamStack private int _cacheOffset; private int _cacheLength; - private readonly byte[] _cache = ArrayPool.Shared.Rent(32 << 10); + private readonly byte[] _cache = ArrayPool.Shared.Rent(32 << 10); private long origin; private long BytesLeftToRead { get; set; } diff --git a/tests/SharpCompress.Test/Ace/AceReaderAsyncTests.cs b/tests/SharpCompress.Test/Ace/AceReaderAsyncTests.cs index d42f36bc..bb8d9ed4 100644 --- a/tests/SharpCompress.Test/Ace/AceReaderAsyncTests.cs +++ b/tests/SharpCompress.Test/Ace/AceReaderAsyncTests.cs @@ -36,7 +36,10 @@ namespace SharpCompress.Test.Ace [InlineData("Ace.method1-solid.ace", CompressionType.AceLZ77)] [InlineData("Ace.method2.ace", CompressionType.AceLZ77)] [InlineData("Ace.method2-solid.ace", CompressionType.AceLZ77)] - public async ValueTask Ace_Unsupported_ShouldThrow_Async(string fileName, CompressionType compressionType) + public async ValueTask Ace_Unsupported_ShouldThrow_Async( + string fileName, + CompressionType compressionType + ) { var exception = await Assert.ThrowsAsync(() => ReadAsync(fileName, compressionType) @@ -45,7 +48,10 @@ namespace SharpCompress.Test.Ace [Theory] [InlineData("Ace.store.largefile.ace", CompressionType.None)] - public async ValueTask Ace_LargeFileTest_Read_Async(string fileName, CompressionType compressionType) + public async ValueTask Ace_LargeFileTest_Read_Async( + string fileName, + CompressionType compressionType + ) { await ReadForBufferBoundaryCheckAsync(fileName, compressionType); } @@ -62,7 +68,7 @@ namespace SharpCompress.Test.Ace { testArchive = Path.Combine(TEST_ARCHIVES_PATH, testArchive); using Stream stream = File.OpenRead(testArchive); - await using var reader = ReaderFactory.OpenAsync( + await using var reader = ReaderFactory.OpenAsyncReader( new AsyncOnlyStream(stream), new ReaderOptions() ); @@ -80,11 +86,14 @@ namespace SharpCompress.Test.Ace VerifyFiles(); } - private async Task ReadForBufferBoundaryCheckAsync(string testArchive, CompressionType expectedCompression) + private async Task ReadForBufferBoundaryCheckAsync( + string testArchive, + CompressionType expectedCompression + ) { testArchive = Path.Combine(TEST_ARCHIVES_PATH, testArchive); using Stream stream = File.OpenRead(testArchive); - await using var reader = ReaderFactory.OpenAsync( + await using var reader = ReaderFactory.OpenAsyncReader( new AsyncOnlyStream(stream), new ReaderOptions() { LookForHeader = false } ); @@ -104,11 +113,15 @@ namespace SharpCompress.Test.Ace private async Task DoMultiReaderAsync(string[] archiveNames) { - var testArchives = archiveNames.Select(s => Path.Combine(TEST_ARCHIVES_PATH, s)).ToList(); + var testArchives = archiveNames + .Select(s => Path.Combine(TEST_ARCHIVES_PATH, s)) + .ToList(); var streams = testArchives.Select(File.OpenRead).ToList(); try { - await using var reader = ReaderFactory.OpenAsync(new AsyncOnlyStream(streams.First())); + await using var reader = ReaderFactory.OpenAsyncReader( + new AsyncOnlyStream(streams.First()) + ); while (await reader.MoveToNextEntryAsync()) { if (!reader.Entry.IsDirectory) diff --git a/tests/SharpCompress.Test/Arj/ArjReaderAsyncTests.cs b/tests/SharpCompress.Test/Arj/ArjReaderAsyncTests.cs index 993cc781..3bd094a0 100644 --- a/tests/SharpCompress.Test/Arj/ArjReaderAsyncTests.cs +++ b/tests/SharpCompress.Test/Arj/ArjReaderAsyncTests.cs @@ -22,7 +22,8 @@ namespace SharpCompress.Test.Arj } [Fact] - public async ValueTask Arj_Uncompressed_Read_Async() => await ReadAsync("Arj.store.arj", CompressionType.None); + public async ValueTask Arj_Uncompressed_Read_Async() => + await ReadAsync("Arj.store.arj", CompressionType.None); [Fact] public async ValueTask Arj_Method1_Read_Async() => await ReadAsync("Arj.method1.arj"); @@ -39,7 +40,9 @@ namespace SharpCompress.Test.Arj [Fact] public async ValueTask Arj_Encrypted_Read_Async() { - var exception = await Assert.ThrowsAsync(() => ReadAsync("Arj.encrypted.arj")); + var exception = await Assert.ThrowsAsync(() => + ReadAsync("Arj.encrypted.arj") + ); } [Fact] @@ -55,7 +58,7 @@ namespace SharpCompress.Test.Arj "Arj.store.split.a04", "Arj.store.split.a05", ], - streams => ReaderFactory.OpenAsync(new AsyncOnlyStream(streams.First())) + streams => ReaderFactory.OpenAsyncReader(new AsyncOnlyStream(streams.First())) ) ); } @@ -64,7 +67,10 @@ namespace SharpCompress.Test.Arj [InlineData("Arj.method1.largefile.arj", CompressionType.ArjLZ77)] [InlineData("Arj.method2.largefile.arj", CompressionType.ArjLZ77)] [InlineData("Arj.method3.largefile.arj", CompressionType.ArjLZ77)] - public async ValueTask Arj_LargeFile_ShouldThrow_Async(string fileName, CompressionType compressionType) + public async ValueTask Arj_LargeFile_ShouldThrow_Async( + string fileName, + CompressionType compressionType + ) { var exception = await Assert.ThrowsAsync(() => ReadForBufferBoundaryCheckAsync(fileName, compressionType) @@ -74,16 +80,22 @@ namespace SharpCompress.Test.Arj [Theory] [InlineData("Arj.store.largefile.arj", CompressionType.None)] [InlineData("Arj.method4.largefile.arj", CompressionType.ArjLZ77)] - public async ValueTask Arj_LargeFileTest_Read_Async(string fileName, CompressionType compressionType) + public async ValueTask Arj_LargeFileTest_Read_Async( + string fileName, + CompressionType compressionType + ) { await ReadForBufferBoundaryCheckAsync(fileName, compressionType); } - private async Task ReadAsync(string testArchive, CompressionType? expectedCompression = null) + private async Task ReadAsync( + string testArchive, + CompressionType? expectedCompression = null + ) { testArchive = Path.Combine(TEST_ARCHIVES_PATH, testArchive); using Stream stream = File.OpenRead(testArchive); - await using var reader = ReaderFactory.OpenAsync( + await using var reader = ReaderFactory.OpenAsyncReader( new AsyncOnlyStream(stream), new ReaderOptions() ); @@ -104,11 +116,14 @@ namespace SharpCompress.Test.Arj VerifyFiles(); } - private async Task ReadForBufferBoundaryCheckAsync(string testArchive, CompressionType expectedCompression) + private async Task ReadForBufferBoundaryCheckAsync( + string testArchive, + CompressionType expectedCompression + ) { testArchive = Path.Combine(TEST_ARCHIVES_PATH, testArchive); using Stream stream = File.OpenRead(testArchive); - await using var reader = ReaderFactory.OpenAsync( + await using var reader = ReaderFactory.OpenAsyncReader( new AsyncOnlyStream(stream), new ReaderOptions() { LookForHeader = false } ); @@ -126,9 +141,14 @@ namespace SharpCompress.Test.Arj VerifyFiles(); } - private async Task DoMultiReaderAsync(string[] archiveNames, Func, IAsyncReader> openReader) + private async Task DoMultiReaderAsync( + string[] archiveNames, + Func, IAsyncReader> openReader + ) { - var testArchives = archiveNames.Select(s => Path.Combine(TEST_ARCHIVES_PATH, s)).ToList(); + var testArchives = archiveNames + .Select(s => Path.Combine(TEST_ARCHIVES_PATH, s)) + .ToList(); var streams = testArchives.Select(File.OpenRead).ToList(); try { diff --git a/tests/SharpCompress.Test/BZip2/BZip2StreamAsyncTests.cs b/tests/SharpCompress.Test/BZip2/BZip2StreamAsyncTests.cs index 5ccfde90..bde34a14 100644 --- a/tests/SharpCompress.Test/BZip2/BZip2StreamAsyncTests.cs +++ b/tests/SharpCompress.Test/BZip2/BZip2StreamAsyncTests.cs @@ -33,7 +33,7 @@ public class BZip2StreamAsyncTests { using ( var bzip2Stream = new BZip2Stream( - new AsyncOnlyStream(memoryStream), + new AsyncOnlyStream(memoryStream), SharpCompress.Compressors.CompressionMode.Compress, false ) diff --git a/tests/SharpCompress.Test/GZip/GZipReaderAsyncTests.cs b/tests/SharpCompress.Test/GZip/GZipReaderAsyncTests.cs index c9e879e6..8f821805 100644 --- a/tests/SharpCompress.Test/GZip/GZipReaderAsyncTests.cs +++ b/tests/SharpCompress.Test/GZip/GZipReaderAsyncTests.cs @@ -70,7 +70,13 @@ public class GZipReaderAsyncTests : ReaderTests bufferSize: options.BufferSize ); using var testStream = new TestStream(protectedStream); - await using (var reader = ReaderFactory.OpenAsync(new AsyncOnlyStream(testStream), options, default)) + await using ( + var reader = ReaderFactory.OpenAsyncReader( + new AsyncOnlyStream(testStream), + options, + default + ) + ) { await UseReaderAsync(reader, expectedCompression); protectedStream.ThrowOnDispose = false; diff --git a/tests/SharpCompress.Test/Rar/RarArchiveAsyncTests.cs b/tests/SharpCompress.Test/Rar/RarArchiveAsyncTests.cs index 44d0a400..479a5655 100644 --- a/tests/SharpCompress.Test/Rar/RarArchiveAsyncTests.cs +++ b/tests/SharpCompress.Test/Rar/RarArchiveAsyncTests.cs @@ -654,7 +654,9 @@ public class RarArchiveAsyncTests : ArchiveTests { testArchive = Path.Combine(TEST_ARCHIVES_PATH, testArchive); using var stream = File.OpenRead(testArchive); - await using var archive = await ArchiveFactory.OpenAsync(new AsyncOnlyStream(stream)); + await using var archive = await ArchiveFactory.OpenAsyncArchive( + new AsyncOnlyStream(stream) + ); Assert.True(await archive.IsSolidAsync()); await using (var reader = await archive.ExtractAllEntriesAsync()) { diff --git a/tests/SharpCompress.Test/SevenZip/SevenZipArchiveAsyncTests.cs b/tests/SharpCompress.Test/SevenZip/SevenZipArchiveAsyncTests.cs index 6c571ea1..31e8bf74 100644 --- a/tests/SharpCompress.Test/SevenZip/SevenZipArchiveAsyncTests.cs +++ b/tests/SharpCompress.Test/SevenZip/SevenZipArchiveAsyncTests.cs @@ -17,7 +17,9 @@ public class SevenZipArchiveAsyncTests : ArchiveTests { var testArchive = Path.Combine(TEST_ARCHIVES_PATH, "7Zip.LZMA.7z"); using var stream = File.OpenRead(testArchive); - await using var archive = await ArchiveFactory.OpenAsync(new AsyncOnlyStream(stream)); + await using var archive = await ArchiveFactory.OpenAsyncArchive( + new AsyncOnlyStream(stream) + ); await foreach (var entry in archive.EntriesAsync.Where(entry => !entry.IsDirectory)) { @@ -42,7 +44,9 @@ public class SevenZipArchiveAsyncTests : ArchiveTests { var testArchive = Path.Combine(TEST_ARCHIVES_PATH, "7Zip.LZMA2.7z"); using var stream = File.OpenRead(testArchive); - await using var archive = await ArchiveFactory.OpenAsync(new AsyncOnlyStream(stream)); + await using var archive = await ArchiveFactory.OpenAsyncArchive( + new AsyncOnlyStream(stream) + ); await foreach (var entry in archive.EntriesAsync.Where(entry => !entry.IsDirectory)) { @@ -67,7 +71,9 @@ public class SevenZipArchiveAsyncTests : ArchiveTests { var testArchive = Path.Combine(TEST_ARCHIVES_PATH, "7Zip.solid.7z"); using var stream = File.OpenRead(testArchive); - await using var archive = await ArchiveFactory.OpenAsync(new AsyncOnlyStream(stream)); + await using var archive = await ArchiveFactory.OpenAsyncArchive( + new AsyncOnlyStream(stream) + ); await foreach (var entry in archive.EntriesAsync.Where(entry => !entry.IsDirectory)) { @@ -92,7 +98,9 @@ public class SevenZipArchiveAsyncTests : ArchiveTests { var testArchive = Path.Combine(TEST_ARCHIVES_PATH, "7Zip.BZip2.7z"); using var stream = File.OpenRead(testArchive); - await using var archive = await ArchiveFactory.OpenAsync(new AsyncOnlyStream(stream)); + await using var archive = await ArchiveFactory.OpenAsyncArchive( + new AsyncOnlyStream(stream) + ); await foreach (var entry in archive.EntriesAsync.Where(entry => !entry.IsDirectory)) { @@ -117,7 +125,9 @@ public class SevenZipArchiveAsyncTests : ArchiveTests { var testArchive = Path.Combine(TEST_ARCHIVES_PATH, "7Zip.PPMd.7z"); using var stream = File.OpenRead(testArchive); - await using var archive = await ArchiveFactory.OpenAsync(new AsyncOnlyStream(stream)); + await using var archive = await ArchiveFactory.OpenAsyncArchive( + new AsyncOnlyStream(stream) + ); await foreach (var entry in archive.EntriesAsync.Where(entry => !entry.IsDirectory)) { diff --git a/tests/SharpCompress.Test/Tar/TarArchiveAsyncTests.cs b/tests/SharpCompress.Test/Tar/TarArchiveAsyncTests.cs index 2a13bb4f..5a12507c 100644 --- a/tests/SharpCompress.Test/Tar/TarArchiveAsyncTests.cs +++ b/tests/SharpCompress.Test/Tar/TarArchiveAsyncTests.cs @@ -33,7 +33,13 @@ public class TarArchiveAsyncTests : ArchiveTests // Step 1: create a tar file containing a file with the test name using (Stream stream = File.OpenWrite(Path.Combine(SCRATCH2_FILES_PATH, archive))) - using (var writer = WriterFactory.OpenAsync(new AsyncOnlyStream(stream), ArchiveType.Tar, CompressionType.None)) + using ( + var writer = WriterFactory.OpenAsyncWriter( + new AsyncOnlyStream(stream), + ArchiveType.Tar, + CompressionType.None + ) + ) using (Stream inputStream = new MemoryStream()) { var sw = new StreamWriter(inputStream); @@ -84,7 +90,13 @@ public class TarArchiveAsyncTests : ArchiveTests // Step 1: create a tar file containing a file with a long name using (Stream stream = File.OpenWrite(Path.Combine(SCRATCH2_FILES_PATH, archive))) - using (var writer = WriterFactory.OpenAsync(new AsyncOnlyStream(stream), ArchiveType.Tar, CompressionType.None)) + using ( + var writer = WriterFactory.OpenAsyncWriter( + new AsyncOnlyStream(stream), + ArchiveType.Tar, + CompressionType.None + ) + ) using (Stream inputStream = new MemoryStream()) { var sw = new StreamWriter(inputStream); @@ -187,7 +199,9 @@ public class TarArchiveAsyncTests : ArchiveTests using (var inputMemory = new MemoryStream(mstm.ToArray())) { var tropt = new ReaderOptions { ArchiveEncoding = enc }; - await using (var tr = ReaderFactory.OpenAsync(new AsyncOnlyStream(inputMemory), tropt)) + await using ( + var tr = ReaderFactory.OpenAsyncReader(new AsyncOnlyStream(inputMemory), tropt) + ) { while (await tr.MoveToNextEntryAsync()) { diff --git a/tests/SharpCompress.Test/Tar/TarReaderAsyncTests.cs b/tests/SharpCompress.Test/Tar/TarReaderAsyncTests.cs index 37578381..2f92fe3a 100644 --- a/tests/SharpCompress.Test/Tar/TarReaderAsyncTests.cs +++ b/tests/SharpCompress.Test/Tar/TarReaderAsyncTests.cs @@ -73,7 +73,7 @@ public class TarReaderAsyncTests : ReaderTests public async ValueTask Tar_BZip2_Entry_Stream_Async() { using (Stream stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "Tar.tar.bz2"))) - await using (var reader = ReaderFactory.OpenAsync(new AsyncOnlyStream(stream))) + await using (var reader = ReaderFactory.OpenAsyncReader(new AsyncOnlyStream(stream))) { while (await reader.MoveToNextEntryAsync()) { diff --git a/tests/SharpCompress.Test/Zip/Zip64AsyncTests.cs b/tests/SharpCompress.Test/Zip/Zip64AsyncTests.cs index 82a096c3..cd9fe18d 100644 --- a/tests/SharpCompress.Test/Zip/Zip64AsyncTests.cs +++ b/tests/SharpCompress.Test/Zip/Zip64AsyncTests.cs @@ -199,7 +199,10 @@ public class Zip64AsyncTests : WriterTests ZipEntry? prev = null; using (var fs = File.OpenRead(filename)) { - var rd = ReaderFactory.OpenAsync(new AsyncOnlyStream(fs), new ReaderOptions { LookForHeader = false }); + var rd = ReaderFactory.OpenAsyncReader( + new AsyncOnlyStream(fs), + new ReaderOptions { LookForHeader = false } + ); await using (rd) { while (await rd.MoveToNextEntryAsync()) diff --git a/tests/SharpCompress.Test/Zip/ZipMemoryArchiveWithCrcAsyncTests.cs b/tests/SharpCompress.Test/Zip/ZipMemoryArchiveWithCrcAsyncTests.cs index dec05c40..c57d5026 100644 --- a/tests/SharpCompress.Test/Zip/ZipMemoryArchiveWithCrcAsyncTests.cs +++ b/tests/SharpCompress.Test/Zip/ZipMemoryArchiveWithCrcAsyncTests.cs @@ -132,7 +132,13 @@ public class ZipTypesLevelsWithCrcRatioAsyncTests : ArchiveTests CompressionLevel = compressionLevel, }; - using (var writer = WriterFactory.OpenAsync(new AsyncOnlyStream(zipStream), ArchiveType.Zip, writerOptions)) + using ( + var writer = WriterFactory.OpenAsyncWriter( + new AsyncOnlyStream(zipStream), + ArchiveType.Zip, + writerOptions + ) + ) { await writer.WriteAsync( $"{compressionType}_level_{compressionLevel}_{sizeMb}MiB.txt",