diff --git a/src/SharpCompress/Archives/AbstractArchive.cs b/src/SharpCompress/Archives/AbstractArchive.cs index b66d7845..12ab15a6 100644 --- a/src/SharpCompress/Archives/AbstractArchive.cs +++ b/src/SharpCompress/Archives/AbstractArchive.cs @@ -7,7 +7,7 @@ using SharpCompress.Readers; namespace SharpCompress.Archives; -public abstract class AbstractArchive : IArchive, IArchiveAsync +public abstract class AbstractArchive : IArchive, IAsyncArchive where TEntry : IArchiveEntry where TVolume : IVolume { @@ -133,7 +133,7 @@ public abstract class AbstractArchive : IArchive, IArchiveAsync } protected abstract IReader CreateReaderForSolidExtraction(); - protected abstract ValueTask CreateReaderForSolidExtractionAsync(); + protected abstract ValueTask CreateReaderForSolidExtractionAsync(); /// /// Archive is SOLID (this means the Archive saved bytes by reusing information which helps for archives containing many small files). @@ -187,12 +187,12 @@ public abstract class AbstractArchive : IArchive, IArchiveAsync } public virtual IAsyncEnumerable EntriesAsync => _lazyEntriesAsync; - IAsyncEnumerable IArchiveAsync.EntriesAsync => + IAsyncEnumerable IAsyncArchive.EntriesAsync => EntriesAsync.Cast(); public IAsyncEnumerable VolumesAsync => _lazyVolumesAsync.Cast(); - public async ValueTask ExtractAllEntriesAsync() + public async ValueTask ExtractAllEntriesAsync() { if (!IsSolid && Type != ArchiveType.SevenZip) { diff --git a/src/SharpCompress/Archives/ArchiveFactory.cs b/src/SharpCompress/Archives/ArchiveFactory.cs index 245940f2..35e18db9 100644 --- a/src/SharpCompress/Archives/ArchiveFactory.cs +++ b/src/SharpCompress/Archives/ArchiveFactory.cs @@ -33,7 +33,7 @@ public static class ArchiveFactory /// /// /// - public static async Task OpenAsync( + public static async Task OpenAsync( Stream stream, ReaderOptions? readerOptions = null, CancellationToken cancellationToken = default @@ -79,7 +79,7 @@ public static class ArchiveFactory /// /// /// - public static Task OpenAsync( + public static Task OpenAsync( string filePath, ReaderOptions? options = null, CancellationToken cancellationToken = default @@ -107,7 +107,7 @@ public static class ArchiveFactory /// /// /// - public static async Task OpenAsync( + public static async Task OpenAsync( FileInfo fileInfo, ReaderOptions? options = null, CancellationToken cancellationToken = default @@ -152,7 +152,7 @@ public static class ArchiveFactory /// /// /// - public static async Task OpenAsync( + public static async Task OpenAsync( IEnumerable fileInfos, ReaderOptions? options = null, CancellationToken cancellationToken = default @@ -212,7 +212,7 @@ public static class ArchiveFactory /// /// /// - public static async Task OpenAsync( + public static async Task OpenAsync( IEnumerable streams, ReaderOptions? options = null, CancellationToken cancellationToken = default diff --git a/src/SharpCompress/Archives/AutoArchiveFactory.cs b/src/SharpCompress/Archives/AutoArchiveFactory.cs index 0c36d1c0..7751c7e0 100644 --- a/src/SharpCompress/Archives/AutoArchiveFactory.cs +++ b/src/SharpCompress/Archives/AutoArchiveFactory.cs @@ -34,7 +34,7 @@ internal class AutoArchiveFactory : IArchiveFactory public IArchive Open(Stream stream, ReaderOptions? readerOptions = null) => ArchiveFactory.Open(stream, readerOptions); - public async ValueTask OpenAsync( + public async ValueTask OpenAsync( Stream stream, ReaderOptions? readerOptions = null, CancellationToken cancellationToken = default @@ -43,7 +43,7 @@ internal class AutoArchiveFactory : IArchiveFactory public IArchive Open(FileInfo fileInfo, ReaderOptions? readerOptions = null) => ArchiveFactory.Open(fileInfo, readerOptions); - public async ValueTask OpenAsync( + public async ValueTask OpenAsync( FileInfo fileInfo, ReaderOptions? readerOptions = null, CancellationToken cancellationToken = default diff --git a/src/SharpCompress/Archives/GZip/GZipArchive.cs b/src/SharpCompress/Archives/GZip/GZipArchive.cs index 82d9c53d..f089d7d1 100644 --- a/src/SharpCompress/Archives/GZip/GZipArchive.cs +++ b/src/SharpCompress/Archives/GZip/GZipArchive.cs @@ -108,7 +108,7 @@ public class GZipArchive : AbstractWritableArchive /// /// /// - public static ValueTask OpenAsync( + public static ValueTask OpenAsync( Stream stream, ReaderOptions? readerOptions = null, CancellationToken cancellationToken = default @@ -124,7 +124,7 @@ public class GZipArchive : AbstractWritableArchive /// /// /// - public static ValueTask OpenAsync( + public static ValueTask OpenAsync( FileInfo fileInfo, ReaderOptions? readerOptions = null, CancellationToken cancellationToken = default @@ -140,7 +140,7 @@ public class GZipArchive : AbstractWritableArchive /// /// /// - public static ValueTask OpenAsync( + public static ValueTask OpenAsync( IReadOnlyList streams, ReaderOptions? readerOptions = null, CancellationToken cancellationToken = default @@ -156,7 +156,7 @@ public class GZipArchive : AbstractWritableArchive /// /// /// - public static ValueTask OpenAsync( + public static ValueTask OpenAsync( IReadOnlyList fileInfos, ReaderOptions? readerOptions = null, CancellationToken cancellationToken = default @@ -337,7 +337,7 @@ public class GZipArchive : AbstractWritableArchive return GZipReader.Open(stream); } - protected override ValueTask CreateReaderForSolidExtractionAsync() + protected override ValueTask CreateReaderForSolidExtractionAsync() { var stream = Volumes.Single().Stream; stream.Position = 0; diff --git a/src/SharpCompress/Archives/IArchive.cs b/src/SharpCompress/Archives/IArchive.cs index 9f5b78a9..3ed7490d 100644 --- a/src/SharpCompress/Archives/IArchive.cs +++ b/src/SharpCompress/Archives/IArchive.cs @@ -1,47 +1,10 @@ using System; using System.Collections.Generic; -using System.Threading.Tasks; using SharpCompress.Common; using SharpCompress.Readers; namespace SharpCompress.Archives; -public interface IArchiveAsync : IAsyncDisposable -{ - IAsyncEnumerable EntriesAsync { get; } - IAsyncEnumerable VolumesAsync { get; } - - ArchiveType Type { get; } - - /// - /// Use this method to extract all entries in an archive in order. - /// This is primarily for SOLID Rar Archives or 7Zip Archives as they need to be - /// extracted sequentially for the best performance. - /// - ValueTask ExtractAllEntriesAsync(); - - /// - /// Archive is SOLID (this means the Archive saved bytes by reusing information which helps for archives containing many small files). - /// Rar Archives can be SOLID while all 7Zip archives are considered SOLID. - /// - ValueTask IsSolidAsync(); - - /// - /// This checks to see if all the known entries have IsComplete = true - /// - ValueTask IsCompleteAsync(); - - /// - /// The total size of the files compressed in the archive. - /// - ValueTask TotalSizeAsync(); - - /// - /// The total size of the files as uncompressed in the archive. - /// - ValueTask TotalUncompressSizeAsync(); -} - public interface IArchive : IDisposable { IEnumerable Entries { get; } diff --git a/src/SharpCompress/Archives/IArchiveAsyncExtensions.cs b/src/SharpCompress/Archives/IArchiveAsyncExtensions.cs deleted file mode 100644 index 95a1617f..00000000 --- a/src/SharpCompress/Archives/IArchiveAsyncExtensions.cs +++ /dev/null @@ -1,100 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Threading; -using System.Threading.Tasks; -using SharpCompress.Common; -using SharpCompress.Readers; - -namespace SharpCompress.Archives; - -public static class IArchiveAsyncExtensions -{ - /// The archive to extract. - extension(IArchiveAsync archive) - { - /// - /// Extract to specific directory asynchronously with progress reporting and cancellation support - /// - /// The folder to extract into. - /// Extraction options. - /// Optional progress reporter for tracking extraction progress. - /// Optional cancellation token. - public async Task WriteToDirectoryAsync( - string destinationDirectory, - ExtractionOptions? options = null, - IProgress? progress = null, - CancellationToken cancellationToken = default - ) - { - // For solid archives (Rar, 7Zip), use the optimized reader-based approach - if (await archive.IsSolidAsync() || archive.Type == ArchiveType.SevenZip) - { - await using var reader = await archive.ExtractAllEntriesAsync(); - await reader.WriteAllToDirectoryAsync( - destinationDirectory, - options, - cancellationToken - ); - } - else - { - // For non-solid archives, extract entries directly - await archive.WriteToDirectoryAsyncInternal( - destinationDirectory, - options, - progress, - cancellationToken - ); - } - } - - private async Task WriteToDirectoryAsyncInternal( - string destinationDirectory, - ExtractionOptions? options, - IProgress? progress, - CancellationToken cancellationToken - ) - { - // Prepare for progress reporting - var totalBytes = await archive.TotalUncompressSizeAsync(); - var bytesRead = 0L; - - // Tracking for created directories. - var seenDirectories = new HashSet(); - - // Extract - await foreach (var entry in archive.EntriesAsync.WithCancellation(cancellationToken)) - { - cancellationToken.ThrowIfCancellationRequested(); - - if (entry.IsDirectory) - { - var dirPath = Path.Combine( - destinationDirectory, - entry.Key.NotNull("Entry Key is null") - ); - if ( - Path.GetDirectoryName(dirPath + "/") is { } parentDirectory - && seenDirectories.Add(dirPath) - ) - { - Directory.CreateDirectory(parentDirectory); - } - continue; - } - - // Use the entry's WriteToDirectoryAsync method which respects ExtractionOptions - await entry - .WriteToDirectoryAsync(destinationDirectory, options, cancellationToken) - .ConfigureAwait(false); - - // Update progress - bytesRead += entry.Size; - progress?.Report( - new ProgressReport(entry.Key ?? string.Empty, bytesRead, totalBytes) - ); - } - } - } -} diff --git a/src/SharpCompress/Archives/IArchiveFactory.cs b/src/SharpCompress/Archives/IArchiveFactory.cs index 40e25d00..1c1253f6 100644 --- a/src/SharpCompress/Archives/IArchiveFactory.cs +++ b/src/SharpCompress/Archives/IArchiveFactory.cs @@ -34,7 +34,7 @@ public interface IArchiveFactory : IFactory /// An open, readable and seekable stream. /// reading options. /// Cancellation token. - ValueTask OpenAsync( + ValueTask OpenAsync( Stream stream, ReaderOptions? readerOptions = null, CancellationToken cancellationToken = default @@ -53,7 +53,7 @@ public interface IArchiveFactory : IFactory /// the file to open. /// reading options. /// Cancellation token. - ValueTask OpenAsync( + ValueTask OpenAsync( FileInfo fileInfo, ReaderOptions? readerOptions = null, CancellationToken cancellationToken = default diff --git a/src/SharpCompress/Archives/IAsyncArchive.cs b/src/SharpCompress/Archives/IAsyncArchive.cs new file mode 100644 index 00000000..bd3f290e --- /dev/null +++ b/src/SharpCompress/Archives/IAsyncArchive.cs @@ -0,0 +1,43 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using SharpCompress.Common; +using SharpCompress.Readers; + +namespace SharpCompress.Archives; + +public interface IAsyncArchive : IAsyncDisposable +{ + IAsyncEnumerable EntriesAsync { get; } + IAsyncEnumerable VolumesAsync { get; } + + ArchiveType Type { get; } + + /// + /// Use this method to extract all entries in an archive in order. + /// This is primarily for SOLID Rar Archives or 7Zip Archives as they need to be + /// extracted sequentially for the best performance. + /// + ValueTask ExtractAllEntriesAsync(); + + /// + /// Archive is SOLID (this means the Archive saved bytes by reusing information which helps for archives containing many small files). + /// Rar Archives can be SOLID while all 7Zip archives are considered SOLID. + /// + ValueTask IsSolidAsync(); + + /// + /// This checks to see if all the known entries have IsComplete = true + /// + ValueTask IsCompleteAsync(); + + /// + /// The total size of the files compressed in the archive. + /// + ValueTask TotalSizeAsync(); + + /// + /// The total size of the files as uncompressed in the archive. + /// + ValueTask TotalUncompressSizeAsync(); +} diff --git a/src/SharpCompress/Archives/IAsyncArchiveExtensions.cs b/src/SharpCompress/Archives/IAsyncArchiveExtensions.cs new file mode 100644 index 00000000..b6b0cad1 --- /dev/null +++ b/src/SharpCompress/Archives/IAsyncArchiveExtensions.cs @@ -0,0 +1,93 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Threading; +using System.Threading.Tasks; +using SharpCompress.Common; +using SharpCompress.Readers; + +namespace SharpCompress.Archives; + +public static class IAsyncArchiveExtensions +{ + /// + /// Extract to specific directory asynchronously with progress reporting and cancellation support + /// + /// The archive to extract. + /// The folder to extract into. + /// Extraction options. + /// Optional progress reporter for tracking extraction progress. + /// Optional cancellation token. + public static async Task WriteToDirectoryAsync( + this IAsyncArchive archive, + string destinationDirectory, + ExtractionOptions? options = null, + IProgress? progress = null, + CancellationToken cancellationToken = default + ) + { + // For solid archives (Rar, 7Zip), use the optimized reader-based approach + if (await archive.IsSolidAsync() || archive.Type == ArchiveType.SevenZip) + { + await using var reader = await archive.ExtractAllEntriesAsync(); + await reader.WriteAllToDirectoryAsync(destinationDirectory, options, cancellationToken); + } + else + { + // For non-solid archives, extract entries directly + await archive.WriteToDirectoryAsyncInternal( + destinationDirectory, + options, + progress, + cancellationToken + ); + } + } + + private static async Task WriteToDirectoryAsyncInternal( + this IAsyncArchive archive, + string destinationDirectory, + ExtractionOptions? options, + IProgress? progress, + CancellationToken cancellationToken + ) + { + // Prepare for progress reporting + var totalBytes = await archive.TotalUncompressSizeAsync(); + var bytesRead = 0L; + + // Tracking for created directories. + var seenDirectories = new HashSet(); + + // Extract + await foreach (var entry in archive.EntriesAsync.WithCancellation(cancellationToken)) + { + cancellationToken.ThrowIfCancellationRequested(); + + if (entry.IsDirectory) + { + var dirPath = Path.Combine( + destinationDirectory, + entry.Key.NotNull("Entry Key is null") + ); + if ( + Path.GetDirectoryName(dirPath + "/") is { } parentDirectory + && seenDirectories.Add(dirPath) + ) + { + Directory.CreateDirectory(parentDirectory); + } + continue; + } + + // Use the entry's WriteToDirectoryAsync method which respects ExtractionOptions + await entry + .WriteToDirectoryAsync(destinationDirectory, options, cancellationToken) + .ConfigureAwait(false); + + // Update progress + bytesRead += entry.Size; + progress?.Report(new ProgressReport(entry.Key ?? string.Empty, bytesRead, totalBytes)); + } + } +} diff --git a/src/SharpCompress/Archives/IMultiArchiveFactory.cs b/src/SharpCompress/Archives/IMultiArchiveFactory.cs index 2c96ef53..4fa94d7f 100644 --- a/src/SharpCompress/Archives/IMultiArchiveFactory.cs +++ b/src/SharpCompress/Archives/IMultiArchiveFactory.cs @@ -35,7 +35,7 @@ public interface IMultiArchiveFactory : IFactory /// /// reading options. /// Cancellation token. - ValueTask OpenAsync( + ValueTask OpenAsync( IReadOnlyList streams, ReaderOptions? readerOptions = null, CancellationToken cancellationToken = default @@ -54,7 +54,7 @@ public interface IMultiArchiveFactory : IFactory /// /// reading options. /// Cancellation token. - ValueTask OpenAsync( + ValueTask OpenAsync( IReadOnlyList fileInfos, ReaderOptions? readerOptions = null, CancellationToken cancellationToken = default diff --git a/src/SharpCompress/Archives/Rar/RarArchive.cs b/src/SharpCompress/Archives/Rar/RarArchive.cs index 400551b0..03b8d4d9 100644 --- a/src/SharpCompress/Archives/Rar/RarArchive.cs +++ b/src/SharpCompress/Archives/Rar/RarArchive.cs @@ -70,7 +70,7 @@ public class RarArchive : AbstractArchive protected override IReader CreateReaderForSolidExtraction() => CreateReaderForSolidExtractionInternal(); - protected override ValueTask CreateReaderForSolidExtractionAsync() => + protected override ValueTask CreateReaderForSolidExtractionAsync() => new(CreateReaderForSolidExtractionInternal()); private RarReader CreateReaderForSolidExtractionInternal() @@ -195,7 +195,7 @@ public class RarArchive : AbstractArchive /// /// /// - public static ValueTask OpenAsync( + public static ValueTask OpenAsync( Stream stream, ReaderOptions? readerOptions = null, CancellationToken cancellationToken = default @@ -211,7 +211,7 @@ public class RarArchive : AbstractArchive /// /// /// - public static ValueTask OpenAsync( + public static ValueTask OpenAsync( FileInfo fileInfo, ReaderOptions? readerOptions = null, CancellationToken cancellationToken = default @@ -227,7 +227,7 @@ public class RarArchive : AbstractArchive /// /// /// - public static ValueTask OpenAsync( + public static ValueTask OpenAsync( IReadOnlyList streams, ReaderOptions? readerOptions = null, CancellationToken cancellationToken = default @@ -243,7 +243,7 @@ public class RarArchive : AbstractArchive /// /// /// - public static ValueTask OpenAsync( + public static ValueTask OpenAsync( IReadOnlyList fileInfos, ReaderOptions? readerOptions = null, CancellationToken cancellationToken = default diff --git a/src/SharpCompress/Archives/SevenZip/SevenZipArchive.cs b/src/SharpCompress/Archives/SevenZip/SevenZipArchive.cs index 54c59538..43f49abe 100644 --- a/src/SharpCompress/Archives/SevenZip/SevenZipArchive.cs +++ b/src/SharpCompress/Archives/SevenZip/SevenZipArchive.cs @@ -111,7 +111,7 @@ public class SevenZipArchive : AbstractArchive /// /// - public static ValueTask OpenAsync( + public static ValueTask OpenAsync( Stream stream, ReaderOptions? readerOptions = null, CancellationToken cancellationToken = default @@ -127,7 +127,7 @@ public class SevenZipArchive : AbstractArchive /// /// - public static ValueTask OpenAsync( + public static ValueTask OpenAsync( FileInfo fileInfo, ReaderOptions? readerOptions = null, CancellationToken cancellationToken = default @@ -143,7 +143,7 @@ public class SevenZipArchive : AbstractArchive /// /// - public static ValueTask OpenAsync( + public static ValueTask OpenAsync( IReadOnlyList streams, ReaderOptions? readerOptions = null, CancellationToken cancellationToken = default @@ -159,7 +159,7 @@ public class SevenZipArchive : AbstractArchive /// /// - public static ValueTask OpenAsync( + public static ValueTask OpenAsync( IReadOnlyList fileInfos, ReaderOptions? readerOptions = null, CancellationToken cancellationToken = default @@ -265,7 +265,7 @@ public class SevenZipArchive : AbstractArchive new SevenZipReader(ReaderOptions, this); - protected override ValueTask CreateReaderForSolidExtractionAsync() => + protected override ValueTask CreateReaderForSolidExtractionAsync() => new(new SevenZipReader(ReaderOptions, this)); public override bool IsSolid => diff --git a/src/SharpCompress/Archives/Tar/TarArchive.cs b/src/SharpCompress/Archives/Tar/TarArchive.cs index 195d7ee4..f75455ec 100644 --- a/src/SharpCompress/Archives/Tar/TarArchive.cs +++ b/src/SharpCompress/Archives/Tar/TarArchive.cs @@ -109,7 +109,7 @@ public class TarArchive : AbstractWritableArchive /// /// /// - public static ValueTask OpenAsync( + public static ValueTask OpenAsync( Stream stream, ReaderOptions? readerOptions = null, CancellationToken cancellationToken = default @@ -125,7 +125,7 @@ public class TarArchive : AbstractWritableArchive /// /// /// - public static ValueTask OpenAsync( + public static ValueTask OpenAsync( FileInfo fileInfo, ReaderOptions? readerOptions = null, CancellationToken cancellationToken = default @@ -141,7 +141,7 @@ public class TarArchive : AbstractWritableArchive /// /// /// - public static ValueTask OpenAsync( + public static ValueTask OpenAsync( IReadOnlyList streams, ReaderOptions? readerOptions = null, CancellationToken cancellationToken = default @@ -157,7 +157,7 @@ public class TarArchive : AbstractWritableArchive /// /// /// - public static ValueTask OpenAsync( + public static ValueTask OpenAsync( IReadOnlyList fileInfos, ReaderOptions? readerOptions = null, CancellationToken cancellationToken = default @@ -367,7 +367,7 @@ public class TarArchive : AbstractWritableArchive return TarReader.Open(stream); } - protected override ValueTask CreateReaderForSolidExtractionAsync() + protected override ValueTask CreateReaderForSolidExtractionAsync() { var stream = Volumes.Single().Stream; stream.Position = 0; diff --git a/src/SharpCompress/Archives/Zip/ZipArchive.cs b/src/SharpCompress/Archives/Zip/ZipArchive.cs index b0da0d05..4bd425bb 100644 --- a/src/SharpCompress/Archives/Zip/ZipArchive.cs +++ b/src/SharpCompress/Archives/Zip/ZipArchive.cs @@ -130,7 +130,7 @@ public class ZipArchive : AbstractWritableArchive /// /// /// - public static ValueTask OpenAsync( + public static ValueTask OpenAsync( Stream stream, ReaderOptions? readerOptions = null, CancellationToken cancellationToken = default @@ -146,7 +146,7 @@ public class ZipArchive : AbstractWritableArchive /// /// /// - public static ValueTask OpenAsync( + public static ValueTask OpenAsync( FileInfo fileInfo, ReaderOptions? readerOptions = null, CancellationToken cancellationToken = default @@ -162,7 +162,7 @@ public class ZipArchive : AbstractWritableArchive /// /// /// - public static ValueTask OpenAsync( + public static ValueTask OpenAsync( IReadOnlyList streams, ReaderOptions? readerOptions = null, CancellationToken cancellationToken = default @@ -178,7 +178,7 @@ public class ZipArchive : AbstractWritableArchive /// /// /// - public static ValueTask OpenAsync( + public static ValueTask OpenAsync( IReadOnlyList fileInfos, ReaderOptions? readerOptions = null, CancellationToken cancellationToken = default @@ -593,7 +593,7 @@ public class ZipArchive : AbstractWritableArchive return ZipReader.Open(stream, ReaderOptions, Entries); } - protected override ValueTask CreateReaderForSolidExtractionAsync() + protected override ValueTask CreateReaderForSolidExtractionAsync() { var stream = Volumes.Single().Stream; stream.Position = 0; diff --git a/src/SharpCompress/Factories/AceFactory.cs b/src/SharpCompress/Factories/AceFactory.cs index 987176ec..95f647dd 100644 --- a/src/SharpCompress/Factories/AceFactory.cs +++ b/src/SharpCompress/Factories/AceFactory.cs @@ -32,7 +32,7 @@ namespace SharpCompress.Factories public IReader OpenReader(Stream stream, ReaderOptions? options) => AceReader.Open(stream, options); - public ValueTask OpenReaderAsync( + public ValueTask OpenReaderAsync( Stream stream, ReaderOptions? options, CancellationToken cancellationToken = default diff --git a/src/SharpCompress/Factories/ArcFactory.cs b/src/SharpCompress/Factories/ArcFactory.cs index 5f7aa36e..37984112 100644 --- a/src/SharpCompress/Factories/ArcFactory.cs +++ b/src/SharpCompress/Factories/ArcFactory.cs @@ -44,7 +44,7 @@ namespace SharpCompress.Factories public IReader OpenReader(Stream stream, ReaderOptions? options) => ArcReader.Open(stream, options); - public ValueTask OpenReaderAsync( + public ValueTask OpenReaderAsync( Stream stream, ReaderOptions? options, CancellationToken cancellationToken = default diff --git a/src/SharpCompress/Factories/ArjFactory.cs b/src/SharpCompress/Factories/ArjFactory.cs index 590aaad9..6e5f7a30 100644 --- a/src/SharpCompress/Factories/ArjFactory.cs +++ b/src/SharpCompress/Factories/ArjFactory.cs @@ -35,7 +35,7 @@ namespace SharpCompress.Factories public IReader OpenReader(Stream stream, ReaderOptions? options) => ArjReader.Open(stream, options); - public ValueTask OpenReaderAsync( + public ValueTask OpenReaderAsync( Stream stream, ReaderOptions? options, CancellationToken cancellationToken = default diff --git a/src/SharpCompress/Factories/Factory.cs b/src/SharpCompress/Factories/Factory.cs index 652a7b96..f28f3d24 100644 --- a/src/SharpCompress/Factories/Factory.cs +++ b/src/SharpCompress/Factories/Factory.cs @@ -113,7 +113,7 @@ public abstract class Factory : IFactory return false; } - internal virtual async ValueTask<(bool, IReaderAsync?)> TryOpenReaderAsync( + internal virtual async ValueTask<(bool, IAsyncReader?)> TryOpenReaderAsync( SharpCompressStream stream, ReaderOptions options, CancellationToken cancellationToken diff --git a/src/SharpCompress/Factories/GZipFactory.cs b/src/SharpCompress/Factories/GZipFactory.cs index 83ecfb58..48f5c63e 100644 --- a/src/SharpCompress/Factories/GZipFactory.cs +++ b/src/SharpCompress/Factories/GZipFactory.cs @@ -65,7 +65,7 @@ public class GZipFactory GZipArchive.Open(stream, readerOptions); /// - public ValueTask OpenAsync( + public ValueTask OpenAsync( Stream stream, ReaderOptions? readerOptions = null, CancellationToken cancellationToken = default @@ -82,7 +82,7 @@ public class GZipFactory GZipArchive.Open(fileInfo, readerOptions); /// - public ValueTask OpenAsync( + public ValueTask OpenAsync( FileInfo fileInfo, ReaderOptions? readerOptions = null, CancellationToken cancellationToken = default @@ -97,7 +97,7 @@ public class GZipFactory GZipArchive.Open(streams, readerOptions); /// - public ValueTask OpenAsync( + public ValueTask OpenAsync( IReadOnlyList streams, ReaderOptions? readerOptions = null, CancellationToken cancellationToken = default @@ -108,7 +108,7 @@ public class GZipFactory GZipArchive.Open(fileInfos, readerOptions); /// - public ValueTask OpenAsync( + public ValueTask OpenAsync( IReadOnlyList fileInfos, ReaderOptions? readerOptions = null, CancellationToken cancellationToken = default @@ -153,7 +153,7 @@ public class GZipFactory GZipReader.Open(stream, options); /// - public ValueTask OpenReaderAsync( + public ValueTask OpenReaderAsync( Stream stream, ReaderOptions? options, CancellationToken cancellationToken = default diff --git a/src/SharpCompress/Factories/RarFactory.cs b/src/SharpCompress/Factories/RarFactory.cs index a856fe58..fb9e03ab 100644 --- a/src/SharpCompress/Factories/RarFactory.cs +++ b/src/SharpCompress/Factories/RarFactory.cs @@ -50,7 +50,7 @@ public class RarFactory : Factory, IArchiveFactory, IMultiArchiveFactory, IReade RarArchive.Open(stream, readerOptions); /// - public ValueTask OpenAsync( + public ValueTask OpenAsync( Stream stream, ReaderOptions? readerOptions = null, CancellationToken cancellationToken = default @@ -61,7 +61,7 @@ public class RarFactory : Factory, IArchiveFactory, IMultiArchiveFactory, IReade RarArchive.Open(fileInfo, readerOptions); /// - public ValueTask OpenAsync( + public ValueTask OpenAsync( FileInfo fileInfo, ReaderOptions? readerOptions = null, CancellationToken cancellationToken = default @@ -82,7 +82,7 @@ public class RarFactory : Factory, IArchiveFactory, IMultiArchiveFactory, IReade RarArchive.Open(streams, readerOptions); /// - public ValueTask OpenAsync( + public ValueTask OpenAsync( IReadOnlyList streams, ReaderOptions? readerOptions = null, CancellationToken cancellationToken = default @@ -93,7 +93,7 @@ public class RarFactory : Factory, IArchiveFactory, IMultiArchiveFactory, IReade RarArchive.Open(fileInfos, readerOptions); /// - public ValueTask OpenAsync( + public ValueTask OpenAsync( IReadOnlyList fileInfos, ReaderOptions? readerOptions = null, CancellationToken cancellationToken = default @@ -108,7 +108,7 @@ public class RarFactory : Factory, IArchiveFactory, IMultiArchiveFactory, IReade RarReader.Open(stream, options); /// - public ValueTask OpenReaderAsync( + public ValueTask OpenReaderAsync( Stream stream, ReaderOptions? options, CancellationToken cancellationToken = default diff --git a/src/SharpCompress/Factories/SevenZipFactory.cs b/src/SharpCompress/Factories/SevenZipFactory.cs index 567290a6..c387e3b3 100644 --- a/src/SharpCompress/Factories/SevenZipFactory.cs +++ b/src/SharpCompress/Factories/SevenZipFactory.cs @@ -45,7 +45,7 @@ public class SevenZipFactory : Factory, IArchiveFactory, IMultiArchiveFactory SevenZipArchive.Open(stream, readerOptions); /// - public ValueTask OpenAsync( + public ValueTask OpenAsync( Stream stream, ReaderOptions? readerOptions = null, CancellationToken cancellationToken = default @@ -56,7 +56,7 @@ public class SevenZipFactory : Factory, IArchiveFactory, IMultiArchiveFactory SevenZipArchive.Open(fileInfo, readerOptions); /// - public ValueTask OpenAsync( + public ValueTask OpenAsync( FileInfo fileInfo, ReaderOptions? readerOptions = null, CancellationToken cancellationToken = default @@ -77,7 +77,7 @@ public class SevenZipFactory : Factory, IArchiveFactory, IMultiArchiveFactory SevenZipArchive.Open(streams, readerOptions); /// - public ValueTask OpenAsync( + public ValueTask OpenAsync( IReadOnlyList streams, ReaderOptions? readerOptions = null, CancellationToken cancellationToken = default @@ -88,7 +88,7 @@ public class SevenZipFactory : Factory, IArchiveFactory, IMultiArchiveFactory SevenZipArchive.Open(fileInfos, readerOptions); /// - public ValueTask OpenAsync( + public ValueTask OpenAsync( IReadOnlyList fileInfos, ReaderOptions? readerOptions = null, CancellationToken cancellationToken = default diff --git a/src/SharpCompress/Factories/TarFactory.cs b/src/SharpCompress/Factories/TarFactory.cs index 7a74bdd7..4e22e0bd 100644 --- a/src/SharpCompress/Factories/TarFactory.cs +++ b/src/SharpCompress/Factories/TarFactory.cs @@ -76,7 +76,7 @@ public class TarFactory TarArchive.Open(stream, readerOptions); /// - public ValueTask OpenAsync( + public ValueTask OpenAsync( Stream stream, ReaderOptions? readerOptions = null, CancellationToken cancellationToken = default @@ -87,7 +87,7 @@ public class TarFactory TarArchive.Open(fileInfo, readerOptions); /// - public ValueTask OpenAsync( + public ValueTask OpenAsync( FileInfo fileInfo, ReaderOptions? readerOptions = null, CancellationToken cancellationToken = default @@ -102,7 +102,7 @@ public class TarFactory TarArchive.Open(streams, readerOptions); /// - public ValueTask OpenAsync( + public ValueTask OpenAsync( IReadOnlyList streams, ReaderOptions? readerOptions = null, CancellationToken cancellationToken = default @@ -113,7 +113,7 @@ public class TarFactory TarArchive.Open(fileInfos, readerOptions); /// - public ValueTask OpenAsync( + public ValueTask OpenAsync( IReadOnlyList fileInfos, ReaderOptions? readerOptions = null, CancellationToken cancellationToken = default @@ -271,7 +271,7 @@ public class TarFactory TarReader.Open(stream, options); /// - public ValueTask OpenReaderAsync( + public ValueTask OpenReaderAsync( Stream stream, ReaderOptions? options, CancellationToken cancellationToken = default diff --git a/src/SharpCompress/Factories/ZipFactory.cs b/src/SharpCompress/Factories/ZipFactory.cs index 44a62696..a9e62f14 100644 --- a/src/SharpCompress/Factories/ZipFactory.cs +++ b/src/SharpCompress/Factories/ZipFactory.cs @@ -143,7 +143,7 @@ public class ZipFactory ZipArchive.Open(stream, readerOptions); /// - public ValueTask OpenAsync( + public ValueTask OpenAsync( Stream stream, ReaderOptions? readerOptions = null, CancellationToken cancellationToken = default @@ -154,7 +154,7 @@ public class ZipFactory ZipArchive.Open(fileInfo, readerOptions); /// - public ValueTask OpenAsync( + public ValueTask OpenAsync( FileInfo fileInfo, ReaderOptions? readerOptions = null, CancellationToken cancellationToken = default @@ -169,7 +169,7 @@ public class ZipFactory ZipArchive.Open(streams, readerOptions); /// - public ValueTask OpenAsync( + public ValueTask OpenAsync( IReadOnlyList streams, ReaderOptions? readerOptions = null, CancellationToken cancellationToken = default @@ -180,7 +180,7 @@ public class ZipFactory ZipArchive.Open(fileInfos, readerOptions); /// - public ValueTask OpenAsync( + public ValueTask OpenAsync( IReadOnlyList fileInfos, ReaderOptions? readerOptions = null, CancellationToken cancellationToken = default @@ -195,7 +195,7 @@ public class ZipFactory ZipReader.Open(stream, options); /// - public ValueTask OpenReaderAsync( + public ValueTask OpenReaderAsync( Stream stream, ReaderOptions? options, CancellationToken cancellationToken = default diff --git a/src/SharpCompress/Readers/AbstractReader.cs b/src/SharpCompress/Readers/AbstractReader.cs index 5621085b..63caf92b 100644 --- a/src/SharpCompress/Readers/AbstractReader.cs +++ b/src/SharpCompress/Readers/AbstractReader.cs @@ -12,7 +12,7 @@ namespace SharpCompress.Readers; /// /// A generic push reader that reads unseekable comrpessed streams. /// -public abstract class AbstractReader : IReader, IReaderAsync +public abstract class AbstractReader : IReader, IAsyncReader where TEntry : Entry where TVolume : Volume { @@ -438,5 +438,5 @@ public abstract class AbstractReader : IReader, IReaderAsync #endregion IEntry IReader.Entry => Entry; - IEntry IReaderAsync.Entry => Entry; + IEntry IAsyncReader.Entry => Entry; } diff --git a/src/SharpCompress/Readers/IAsyncReader.cs b/src/SharpCompress/Readers/IAsyncReader.cs new file mode 100644 index 00000000..d5695d72 --- /dev/null +++ b/src/SharpCompress/Readers/IAsyncReader.cs @@ -0,0 +1,38 @@ +using System; +using System.IO; +using System.Threading; +using System.Threading.Tasks; +using SharpCompress.Common; + +namespace SharpCompress.Readers; + +public interface IAsyncReader : IAsyncDisposable +{ + ArchiveType ArchiveType { get; } + + IEntry Entry { get; } + + /// + /// Decompresses the current entry to the stream asynchronously. This cannot be called twice for the current entry. + /// + /// + /// + Task WriteEntryToAsync(Stream writableStream, CancellationToken cancellationToken = default); + + bool Cancelled { get; } + void Cancel(); + + /// + /// Moves to the next entry asynchronously by reading more data from the underlying stream. This skips if data has not been read. + /// + /// + /// + Task MoveToNextEntryAsync(CancellationToken cancellationToken = default); + + /// + /// Opens the current entry asynchronously as a stream that will decompress as it is read. + /// Read the entire stream or use SkipEntry on EntryStream. + /// + /// + Task OpenEntryStreamAsync(CancellationToken cancellationToken = default); +} diff --git a/src/SharpCompress/Readers/IReaderAsyncExtensions.cs b/src/SharpCompress/Readers/IAsyncReaderExtensions.cs similarity index 96% rename from src/SharpCompress/Readers/IReaderAsyncExtensions.cs rename to src/SharpCompress/Readers/IAsyncReaderExtensions.cs index 26de3a13..77e46964 100644 --- a/src/SharpCompress/Readers/IReaderAsyncExtensions.cs +++ b/src/SharpCompress/Readers/IAsyncReaderExtensions.cs @@ -5,9 +5,9 @@ using SharpCompress.Common; namespace SharpCompress.Readers; -public static class IReaderAsyncExtensions +public static class IAsyncReaderExtensions { - extension(IReaderAsync reader) + extension(IAsyncReader reader) { /// /// Extract to specific directory asynchronously, retaining filename diff --git a/src/SharpCompress/Readers/IReader.cs b/src/SharpCompress/Readers/IReader.cs index 6f163bd5..a38d61d6 100644 --- a/src/SharpCompress/Readers/IReader.cs +++ b/src/SharpCompress/Readers/IReader.cs @@ -1,7 +1,5 @@ using System; using System.IO; -using System.Threading; -using System.Threading.Tasks; using SharpCompress.Common; namespace SharpCompress.Readers; @@ -33,34 +31,3 @@ public interface IReader : IDisposable /// EntryStream OpenEntryStream(); } - -public interface IReaderAsync : IAsyncDisposable -{ - ArchiveType ArchiveType { get; } - - IEntry Entry { get; } - - /// - /// Decompresses the current entry to the stream asynchronously. This cannot be called twice for the current entry. - /// - /// - /// - Task WriteEntryToAsync(Stream writableStream, CancellationToken cancellationToken = default); - - bool Cancelled { get; } - void Cancel(); - - /// - /// Moves to the next entry asynchronously by reading more data from the underlying stream. This skips if data has not been read. - /// - /// - /// - Task MoveToNextEntryAsync(CancellationToken cancellationToken = default); - - /// - /// Opens the current entry asynchronously as a stream that will decompress as it is read. - /// Read the entire stream or use SkipEntry on EntryStream. - /// - /// - Task OpenEntryStreamAsync(CancellationToken cancellationToken = default); -} diff --git a/src/SharpCompress/Readers/IReaderFactory.cs b/src/SharpCompress/Readers/IReaderFactory.cs index 9dec99d9..4757644b 100644 --- a/src/SharpCompress/Readers/IReaderFactory.cs +++ b/src/SharpCompress/Readers/IReaderFactory.cs @@ -13,7 +13,7 @@ public interface IReaderFactory : Factories.IFactory /// /// IReader OpenReader(Stream stream, ReaderOptions? options); - ValueTask OpenReaderAsync( + ValueTask OpenReaderAsync( Stream stream, ReaderOptions? options, CancellationToken cancellationToken diff --git a/src/SharpCompress/Readers/ReaderFactory.cs b/src/SharpCompress/Readers/ReaderFactory.cs index 8f937528..6102f146 100644 --- a/src/SharpCompress/Readers/ReaderFactory.cs +++ b/src/SharpCompress/Readers/ReaderFactory.cs @@ -24,7 +24,7 @@ public static class ReaderFactory /// /// /// - public static ValueTask OpenAsync( + public static ValueTask OpenAsync( string filePath, ReaderOptions? options = null, CancellationToken cancellationToken = default @@ -47,7 +47,7 @@ public static class ReaderFactory /// /// /// - public static ValueTask OpenAsync( + public static ValueTask OpenAsync( FileInfo fileInfo, ReaderOptions? options = null, CancellationToken cancellationToken = default @@ -110,7 +110,7 @@ public static class ReaderFactory ); } - public static async ValueTask OpenAsync( + public static async ValueTask OpenAsync( Stream stream, ReaderOptions? options = null, CancellationToken cancellationToken = default diff --git a/tests/SharpCompress.Test/GZip/GZipReaderAsyncTests.cs b/tests/SharpCompress.Test/GZip/GZipReaderAsyncTests.cs index 6eb46783..139750c8 100644 --- a/tests/SharpCompress.Test/GZip/GZipReaderAsyncTests.cs +++ b/tests/SharpCompress.Test/GZip/GZipReaderAsyncTests.cs @@ -82,7 +82,7 @@ public class GZipReaderAsyncTests : ReaderTests Assert.True(options.LeaveStreamOpen != testStream.IsDisposed, message); } - private async Task UseReaderAsync(IReaderAsync reader, CompressionType expectedCompression) + private async Task UseReaderAsync(IAsyncReader reader, CompressionType expectedCompression) { while (await reader.MoveToNextEntryAsync()) { diff --git a/tests/SharpCompress.Test/ReaderTests.cs b/tests/SharpCompress.Test/ReaderTests.cs index 0f12feeb..d2755cc8 100644 --- a/tests/SharpCompress.Test/ReaderTests.cs +++ b/tests/SharpCompress.Test/ReaderTests.cs @@ -164,7 +164,7 @@ public abstract class ReaderTests : TestBase } public async Task UseReaderAsync( - IReaderAsync reader, + IAsyncReader reader, CompressionType? expectedCompression, CancellationToken cancellationToken = default )