Remove unnecessary ValueTask wrappers from async factory methods

Change return types from ValueTask<T> to direct interface types (IAsyncArchive, IAsyncReader, IWriter) for wrapper methods that don't perform async work. This eliminates unnecessary async state machine allocations while maintaining the same public API behavior.

Changes:
- Interface definitions: Updated IArchiveFactory, IMultiArchiveFactory, IReaderFactory, IWriterFactory
- Concrete factories: Updated archive factories (Zip, Tar, Rar, GZip, SevenZip) and reader-only factories (Ace, Arc, Arj)
- Static factory methods: Updated ReaderFactory, ArchiveFactory, WriterFactory to use new signatures
- Archive classes: Updated static OpenAsync methods in ZipArchive, TarArchive, RarArchive, SevenZipArchive, GZipArchive
- Supporting changes: Updated Factory.cs and async polyfills

Performance benefit: Reduced GC pressure by eliminating unnecessary state machine overhead for non-async wrapper methods.
This commit is contained in:
Adam Hathcock
2026-01-12 13:16:44 +00:00
parent c5a6f900df
commit c1f8580d89
25 changed files with 209 additions and 178 deletions

View File

@@ -33,7 +33,7 @@ public static class ArchiveFactory
/// <param name="readerOptions"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public static async ValueTask<IAsyncArchive> OpenAsync(
public static IAsyncArchive OpenAsync(
Stream stream,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
@@ -41,11 +41,8 @@ public static class ArchiveFactory
{
readerOptions ??= new ReaderOptions();
stream = SharpCompressStream.Create(stream, bufferSize: readerOptions.BufferSize);
var factory = await FindFactoryAsync<IArchiveFactory>(stream, cancellationToken)
.ConfigureAwait(false);
return await factory
.OpenAsync(stream, readerOptions, cancellationToken)
.ConfigureAwait(false);
var factory = FindFactory<IArchiveFactory>(stream);
return factory.OpenAsync(stream, readerOptions, cancellationToken);
}
public static IWritableArchive Create(ArchiveType type)
@@ -79,7 +76,7 @@ public static class ArchiveFactory
/// <param name="filePath"></param>
/// <param name="options"></param>
/// <param name="cancellationToken"></param>
public static ValueTask<IAsyncArchive> OpenAsync(
public static IAsyncArchive OpenAsync(
string filePath,
ReaderOptions? options = null,
CancellationToken cancellationToken = default
@@ -107,7 +104,7 @@ public static class ArchiveFactory
/// <param name="fileInfo"></param>
/// <param name="options"></param>
/// <param name="cancellationToken"></param>
public static async ValueTask<IAsyncArchive> OpenAsync(
public static IAsyncArchive OpenAsync(
FileInfo fileInfo,
ReaderOptions? options = null,
CancellationToken cancellationToken = default
@@ -115,9 +112,8 @@ public static class ArchiveFactory
{
options ??= new ReaderOptions { LeaveStreamOpen = false };
var factory = await FindFactoryAsync<IArchiveFactory>(fileInfo, cancellationToken)
.ConfigureAwait(false);
return await factory.OpenAsync(fileInfo, options, cancellationToken).ConfigureAwait(false);
var factory = FindFactory<IArchiveFactory>(fileInfo);
return factory.OpenAsync(fileInfo, options, cancellationToken);
}
/// <summary>
@@ -152,7 +148,7 @@ public static class ArchiveFactory
/// <param name="fileInfos"></param>
/// <param name="options"></param>
/// <param name="cancellationToken"></param>
public static async ValueTask<IAsyncArchive> OpenAsync(
public static IAsyncArchive OpenAsync(
IEnumerable<FileInfo> fileInfos,
ReaderOptions? options = null,
CancellationToken cancellationToken = default
@@ -168,16 +164,14 @@ public static class ArchiveFactory
var fileInfo = filesArray[0];
if (filesArray.Length == 1)
{
return await OpenAsync(fileInfo, options, cancellationToken).ConfigureAwait(false);
return OpenAsync(fileInfo, options, cancellationToken);
}
fileInfo.NotNull(nameof(fileInfo));
options ??= new ReaderOptions { LeaveStreamOpen = false };
var factory = FindFactory<IMultiArchiveFactory>(fileInfo);
return await factory
.OpenAsync(filesArray, options, cancellationToken)
.ConfigureAwait(false);
return factory.OpenAsync(filesArray, options, cancellationToken);
}
/// <summary>
@@ -212,7 +206,7 @@ public static class ArchiveFactory
/// <param name="streams"></param>
/// <param name="options"></param>
/// <param name="cancellationToken"></param>
public static async ValueTask<IAsyncArchive> OpenAsync(
public static IAsyncArchive OpenAsync(
IEnumerable<Stream> streams,
ReaderOptions? options = null,
CancellationToken cancellationToken = default
@@ -229,16 +223,14 @@ public static class ArchiveFactory
var firstStream = streamsArray[0];
if (streamsArray.Length == 1)
{
return await OpenAsync(firstStream, options, cancellationToken).ConfigureAwait(false);
return OpenAsync(firstStream, options, cancellationToken);
}
firstStream.NotNull(nameof(firstStream));
options ??= new ReaderOptions();
var factory = FindFactory<IMultiArchiveFactory>(firstStream);
return await factory
.OpenAsync(streamsArray, options, cancellationToken)
.ConfigureAwait(false);
return factory.OpenAsync(streamsArray, options, cancellationToken);
}
/// <summary>

View File

@@ -34,18 +34,22 @@ internal class AutoArchiveFactory : IArchiveFactory
public IArchive Open(Stream stream, ReaderOptions? readerOptions = null) =>
ArchiveFactory.Open(stream, readerOptions);
public async ValueTask<IAsyncArchive> OpenAsync(
public IAsyncArchive OpenAsync(
Stream stream,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
) => await ArchiveFactory.OpenAsync(stream, readerOptions, cancellationToken);
) => (IAsyncArchive)Open(stream, readerOptions);
public IArchive Open(FileInfo fileInfo, ReaderOptions? readerOptions = null) =>
ArchiveFactory.Open(fileInfo, readerOptions);
public async ValueTask<IAsyncArchive> OpenAsync(
public IAsyncArchive OpenAsync(
FileInfo fileInfo,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
) => await ArchiveFactory.OpenAsync(fileInfo, readerOptions, cancellationToken);
)
{
cancellationToken.ThrowIfCancellationRequested();
return (IAsyncArchive)Open(fileInfo, readerOptions);
}
}

View File

@@ -108,14 +108,14 @@ public class GZipArchive : AbstractWritableArchive<GZipArchiveEntry, GZipVolume>
/// <param name="stream"></param>
/// <param name="readerOptions"></param>
/// <param name="cancellationToken"></param>
public static ValueTask<IAsyncArchive> OpenAsync(
public static IAsyncArchive OpenAsync(
Stream stream,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return new((IAsyncArchive)Open(stream, readerOptions));
return (IAsyncArchive)Open(stream, readerOptions);
}
/// <summary>
@@ -124,14 +124,14 @@ public class GZipArchive : AbstractWritableArchive<GZipArchiveEntry, GZipVolume>
/// <param name="fileInfo"></param>
/// <param name="readerOptions"></param>
/// <param name="cancellationToken"></param>
public static ValueTask<IAsyncArchive> OpenAsync(
public static IAsyncArchive OpenAsync(
FileInfo fileInfo,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return new((IAsyncArchive)Open(fileInfo, readerOptions));
return (IAsyncArchive)Open(fileInfo, readerOptions);
}
/// <summary>
@@ -140,14 +140,14 @@ public class GZipArchive : AbstractWritableArchive<GZipArchiveEntry, GZipVolume>
/// <param name="streams"></param>
/// <param name="readerOptions"></param>
/// <param name="cancellationToken"></param>
public static ValueTask<IAsyncArchive> OpenAsync(
public static IAsyncArchive OpenAsync(
IReadOnlyList<Stream> streams,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return new((IAsyncArchive)Open(streams, readerOptions));
return (IAsyncArchive)Open(streams, readerOptions);
}
/// <summary>
@@ -156,14 +156,14 @@ public class GZipArchive : AbstractWritableArchive<GZipArchiveEntry, GZipVolume>
/// <param name="fileInfos"></param>
/// <param name="readerOptions"></param>
/// <param name="cancellationToken"></param>
public static ValueTask<IAsyncArchive> OpenAsync(
public static IAsyncArchive OpenAsync(
IReadOnlyList<FileInfo> fileInfos,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return new((IAsyncArchive)Open(fileInfos, readerOptions));
return (IAsyncArchive)Open(fileInfos, readerOptions);
}
public static GZipArchive Create() => new();

View File

@@ -1,6 +1,5 @@
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using SharpCompress.Factories;
using SharpCompress.Readers;
@@ -34,7 +33,7 @@ public interface IArchiveFactory : IFactory
/// <param name="stream">An open, readable and seekable stream.</param>
/// <param name="readerOptions">reading options.</param>
/// <param name="cancellationToken">Cancellation token.</param>
ValueTask<IAsyncArchive> OpenAsync(
IAsyncArchive OpenAsync(
Stream stream,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
@@ -53,7 +52,7 @@ public interface IArchiveFactory : IFactory
/// <param name="fileInfo">the file to open.</param>
/// <param name="readerOptions">reading options.</param>
/// <param name="cancellationToken">Cancellation token.</param>
ValueTask<IAsyncArchive> OpenAsync(
IAsyncArchive OpenAsync(
FileInfo fileInfo,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default

View File

@@ -1,7 +1,6 @@
using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using SharpCompress.Factories;
using SharpCompress.Readers;
@@ -35,7 +34,7 @@ public interface IMultiArchiveFactory : IFactory
/// <param name="streams"></param>
/// <param name="readerOptions">reading options.</param>
/// <param name="cancellationToken">Cancellation token.</param>
ValueTask<IAsyncArchive> OpenAsync(
IAsyncArchive OpenAsync(
IReadOnlyList<Stream> streams,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
@@ -54,7 +53,7 @@ public interface IMultiArchiveFactory : IFactory
/// <param name="fileInfos"></param>
/// <param name="readerOptions">reading options.</param>
/// <param name="cancellationToken">Cancellation token.</param>
ValueTask<IAsyncArchive> OpenAsync(
IAsyncArchive OpenAsync(
IReadOnlyList<FileInfo> fileInfos,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default

View File

@@ -195,14 +195,14 @@ public class RarArchive : AbstractArchive<RarArchiveEntry, RarVolume>
/// <param name="stream"></param>
/// <param name="readerOptions"></param>
/// <param name="cancellationToken"></param>
public static ValueTask<IAsyncArchive> OpenAsync(
public static IAsyncArchive OpenAsync(
Stream stream,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return new((IAsyncArchive)Open(stream, readerOptions));
return (IAsyncArchive)Open(stream, readerOptions);
}
/// <summary>
@@ -211,14 +211,14 @@ public class RarArchive : AbstractArchive<RarArchiveEntry, RarVolume>
/// <param name="fileInfo"></param>
/// <param name="readerOptions"></param>
/// <param name="cancellationToken"></param>
public static ValueTask<IAsyncArchive> OpenAsync(
public static IAsyncArchive OpenAsync(
FileInfo fileInfo,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return new((IAsyncArchive)Open(fileInfo, readerOptions));
return (IAsyncArchive)Open(fileInfo, readerOptions);
}
/// <summary>
@@ -227,14 +227,14 @@ public class RarArchive : AbstractArchive<RarArchiveEntry, RarVolume>
/// <param name="streams"></param>
/// <param name="readerOptions"></param>
/// <param name="cancellationToken"></param>
public static ValueTask<IAsyncArchive> OpenAsync(
public static IAsyncArchive OpenAsync(
IReadOnlyList<Stream> streams,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return new((IAsyncArchive)Open(streams, readerOptions));
return (IAsyncArchive)Open(streams, readerOptions);
}
/// <summary>
@@ -243,14 +243,14 @@ public class RarArchive : AbstractArchive<RarArchiveEntry, RarVolume>
/// <param name="fileInfos"></param>
/// <param name="readerOptions"></param>
/// <param name="cancellationToken"></param>
public static ValueTask<IAsyncArchive> OpenAsync(
public static IAsyncArchive OpenAsync(
IReadOnlyList<FileInfo> fileInfos,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return new((IAsyncArchive)Open(fileInfos, readerOptions));
return (IAsyncArchive)Open(fileInfos, readerOptions);
}
public static bool IsRarFile(string filePath) => IsRarFile(new FileInfo(filePath));

View File

@@ -108,14 +108,14 @@ public class SevenZipArchive : AbstractArchive<SevenZipArchiveEntry, SevenZipVol
/// <param name="stream"></param>
/// <param name="readerOptions"></param>
/// <param name="cancellationToken"></param>
public static ValueTask<IAsyncArchive> OpenAsync(
public static IAsyncArchive OpenAsync(
Stream stream,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return new((IAsyncArchive)Open(stream, readerOptions));
return (IAsyncArchive)Open(stream, readerOptions);
}
/// <summary>
@@ -124,14 +124,14 @@ public class SevenZipArchive : AbstractArchive<SevenZipArchiveEntry, SevenZipVol
/// <param name="fileInfo"></param>
/// <param name="readerOptions"></param>
/// <param name="cancellationToken"></param>
public static ValueTask<IAsyncArchive> OpenAsync(
public static IAsyncArchive OpenAsync(
FileInfo fileInfo,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return new((IAsyncArchive)Open(fileInfo, readerOptions));
return (IAsyncArchive)Open(fileInfo, readerOptions);
}
/// <summary>
@@ -140,14 +140,14 @@ public class SevenZipArchive : AbstractArchive<SevenZipArchiveEntry, SevenZipVol
/// <param name="streams"></param>
/// <param name="readerOptions"></param>
/// <param name="cancellationToken"></param>
public static ValueTask<IAsyncArchive> OpenAsync(
public static IAsyncArchive OpenAsync(
IReadOnlyList<Stream> streams,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return new((IAsyncArchive)Open(streams, readerOptions));
return (IAsyncArchive)Open(streams, readerOptions);
}
/// <summary>
@@ -156,14 +156,14 @@ public class SevenZipArchive : AbstractArchive<SevenZipArchiveEntry, SevenZipVol
/// <param name="fileInfos"></param>
/// <param name="readerOptions"></param>
/// <param name="cancellationToken"></param>
public static ValueTask<IAsyncArchive> OpenAsync(
public static IAsyncArchive OpenAsync(
IReadOnlyList<FileInfo> fileInfos,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return new((IAsyncArchive)Open(fileInfos, readerOptions));
return (IAsyncArchive)Open(fileInfos, readerOptions);
}
/// <summary>

View File

@@ -109,14 +109,14 @@ public class TarArchive : AbstractWritableArchive<TarArchiveEntry, TarVolume>
/// <param name="stream"></param>
/// <param name="readerOptions"></param>
/// <param name="cancellationToken"></param>
public static ValueTask<IAsyncArchive> OpenAsync(
public static IAsyncArchive OpenAsync(
Stream stream,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return new((IAsyncArchive)Open(stream, readerOptions));
return (IAsyncArchive)Open(stream, readerOptions);
}
/// <summary>
@@ -125,14 +125,14 @@ public class TarArchive : AbstractWritableArchive<TarArchiveEntry, TarVolume>
/// <param name="fileInfo"></param>
/// <param name="readerOptions"></param>
/// <param name="cancellationToken"></param>
public static ValueTask<IAsyncArchive> OpenAsync(
public static IAsyncArchive OpenAsync(
FileInfo fileInfo,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return new((IAsyncArchive)Open(fileInfo, readerOptions));
return (IAsyncArchive)Open(fileInfo, readerOptions);
}
/// <summary>
@@ -141,14 +141,14 @@ public class TarArchive : AbstractWritableArchive<TarArchiveEntry, TarVolume>
/// <param name="streams"></param>
/// <param name="readerOptions"></param>
/// <param name="cancellationToken"></param>
public static ValueTask<IAsyncArchive> OpenAsync(
public static IAsyncArchive OpenAsync(
IReadOnlyList<Stream> streams,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return new((IAsyncArchive)Open(streams, readerOptions));
return (IAsyncArchive)Open(streams, readerOptions);
}
/// <summary>
@@ -157,14 +157,14 @@ public class TarArchive : AbstractWritableArchive<TarArchiveEntry, TarVolume>
/// <param name="fileInfos"></param>
/// <param name="readerOptions"></param>
/// <param name="cancellationToken"></param>
public static ValueTask<IAsyncArchive> OpenAsync(
public static IAsyncArchive OpenAsync(
IReadOnlyList<FileInfo> fileInfos,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return new((IAsyncArchive)Open(fileInfos, readerOptions));
return (IAsyncArchive)Open(fileInfos, readerOptions);
}
public static bool IsTarFile(string filePath) => IsTarFile(new FileInfo(filePath));

View File

@@ -124,14 +124,14 @@ public class ZipArchive : AbstractWritableArchive<ZipArchiveEntry, ZipVolume>
);
}
public static ValueTask<IAsyncArchive> OpenAsync(
public static IAsyncArchive OpenAsync(
string path,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return new((IAsyncArchive)Open(path, readerOptions));
return (IAsyncArchive)Open(path, readerOptions);
}
/// <summary>
@@ -140,14 +140,14 @@ public class ZipArchive : AbstractWritableArchive<ZipArchiveEntry, ZipVolume>
/// <param name="stream"></param>
/// <param name="readerOptions"></param>
/// <param name="cancellationToken"></param>
public static ValueTask<IAsyncArchive> OpenAsync(
public static IAsyncArchive OpenAsync(
Stream stream,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return new((IAsyncArchive)Open(stream, readerOptions));
return (IAsyncArchive)Open(stream, readerOptions);
}
/// <summary>
@@ -156,14 +156,14 @@ public class ZipArchive : AbstractWritableArchive<ZipArchiveEntry, ZipVolume>
/// <param name="fileInfo"></param>
/// <param name="readerOptions"></param>
/// <param name="cancellationToken"></param>
public static ValueTask<IAsyncArchive> OpenAsync(
public static IAsyncArchive OpenAsync(
FileInfo fileInfo,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return new((IAsyncArchive)Open(fileInfo, readerOptions));
return (IAsyncArchive)Open(fileInfo, readerOptions);
}
/// <summary>
@@ -172,14 +172,14 @@ public class ZipArchive : AbstractWritableArchive<ZipArchiveEntry, ZipVolume>
/// <param name="streams"></param>
/// <param name="readerOptions"></param>
/// <param name="cancellationToken"></param>
public static ValueTask<IAsyncArchive> OpenAsync(
public static IAsyncArchive OpenAsync(
IReadOnlyList<Stream> streams,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return new((IAsyncArchive)Open(streams, readerOptions));
return (IAsyncArchive)Open(streams, readerOptions);
}
/// <summary>
@@ -188,14 +188,14 @@ public class ZipArchive : AbstractWritableArchive<ZipArchiveEntry, ZipVolume>
/// <param name="fileInfos"></param>
/// <param name="readerOptions"></param>
/// <param name="cancellationToken"></param>
public static ValueTask<IAsyncArchive> OpenAsync(
public static IAsyncArchive OpenAsync(
IReadOnlyList<FileInfo> fileInfos,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return new((IAsyncArchive)Open(fileInfos, readerOptions));
return (IAsyncArchive)Open(fileInfos, readerOptions);
}
public static bool IsZipFile(

View File

@@ -32,11 +32,15 @@ namespace SharpCompress.Factories
public IReader OpenReader(Stream stream, ReaderOptions? options) =>
AceReader.Open(stream, options);
public ValueTask<IAsyncReader> OpenReaderAsync(
public IAsyncReader OpenReaderAsync(
Stream stream,
ReaderOptions? options,
CancellationToken cancellationToken = default
) => new((IAsyncReader)AceReader.Open(stream, options));
)
{
cancellationToken.ThrowIfCancellationRequested();
return (IAsyncReader)AceReader.Open(stream, options);
}
public override ValueTask<bool> IsArchiveAsync(
Stream stream,

View File

@@ -44,11 +44,15 @@ namespace SharpCompress.Factories
public IReader OpenReader(Stream stream, ReaderOptions? options) =>
ArcReader.Open(stream, options);
public ValueTask<IAsyncReader> OpenReaderAsync(
public IAsyncReader OpenReaderAsync(
Stream stream,
ReaderOptions? options,
CancellationToken cancellationToken = default
) => new((IAsyncReader)ArcReader.Open(stream, options));
)
{
cancellationToken.ThrowIfCancellationRequested();
return (IAsyncReader)ArcReader.Open(stream, options);
}
public override ValueTask<bool> IsArchiveAsync(
Stream stream,

View File

@@ -35,11 +35,15 @@ namespace SharpCompress.Factories
public IReader OpenReader(Stream stream, ReaderOptions? options) =>
ArjReader.Open(stream, options);
public ValueTask<IAsyncReader> OpenReaderAsync(
public IAsyncReader OpenReaderAsync(
Stream stream,
ReaderOptions? options,
CancellationToken cancellationToken = default
) => new((IAsyncReader)ArjReader.Open(stream, options));
)
{
cancellationToken.ThrowIfCancellationRequested();
return (IAsyncReader)ArjReader.Open(stream, options);
}
public override ValueTask<bool> IsArchiveAsync(
Stream stream,

View File

@@ -133,10 +133,7 @@ public abstract class Factory : IFactory
)
{
((IStreamStack)stream).StackSeek(pos);
return (
true,
await readerFactory.OpenReaderAsync(stream, options, cancellationToken)
);
return (true, readerFactory.OpenReaderAsync(stream, options, cancellationToken));
}
}

View File

@@ -65,11 +65,11 @@ public class GZipFactory
GZipArchive.Open(stream, readerOptions);
/// <inheritdoc/>
public ValueTask<IAsyncArchive> OpenAsync(
public IAsyncArchive OpenAsync(
Stream stream,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
) => GZipArchive.OpenAsync(stream, readerOptions, cancellationToken);
) => (IAsyncArchive)Open(stream, readerOptions);
public override ValueTask<bool> IsArchiveAsync(
Stream stream,
@@ -78,15 +78,15 @@ public class GZipFactory
) => new(IsArchive(stream, password, bufferSize));
/// <inheritdoc/>
public IArchive Open(FileInfo fileInfo, ReaderOptions? readerOptions = null) =>
GZipArchive.Open(fileInfo, readerOptions);
/// <inheritdoc/>
public ValueTask<IAsyncArchive> OpenAsync(
public IAsyncArchive OpenAsync(
FileInfo fileInfo,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
) => GZipArchive.OpenAsync(fileInfo, readerOptions, cancellationToken);
)
{
cancellationToken.ThrowIfCancellationRequested();
return (IAsyncArchive)Open(fileInfo, readerOptions);
}
#endregion
@@ -97,22 +97,26 @@ public class GZipFactory
GZipArchive.Open(streams, readerOptions);
/// <inheritdoc/>
public ValueTask<IAsyncArchive> OpenAsync(
public IAsyncArchive OpenAsync(
IReadOnlyList<Stream> streams,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
) => GZipArchive.OpenAsync(streams, readerOptions, cancellationToken);
) => (IAsyncArchive)Open(streams, readerOptions);
/// <inheritdoc/>
public IArchive Open(IReadOnlyList<FileInfo> fileInfos, ReaderOptions? readerOptions = null) =>
GZipArchive.Open(fileInfos, readerOptions);
/// <inheritdoc/>
public ValueTask<IAsyncArchive> OpenAsync(
public IAsyncArchive OpenAsync(
IReadOnlyList<FileInfo> fileInfos,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
) => GZipArchive.OpenAsync(fileInfos, readerOptions, cancellationToken);
)
{
cancellationToken.ThrowIfCancellationRequested();
return (IAsyncArchive)Open(fileInfos, readerOptions);
}
#endregion
@@ -153,16 +157,20 @@ public class GZipFactory
GZipReader.Open(stream, options);
/// <inheritdoc/>
public ValueTask<IAsyncReader> OpenReaderAsync(
public IAsyncReader OpenReaderAsync(
Stream stream,
ReaderOptions? options,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return new((IAsyncReader)GZipReader.Open(stream, options));
return (IAsyncReader)GZipReader.Open(stream, options);
}
/// <inheritdoc/>
public IArchive Open(FileInfo fileInfo, ReaderOptions? readerOptions = null) =>
GZipArchive.Open(fileInfo, readerOptions);
#endregion
#region IWriterFactory
@@ -178,14 +186,18 @@ public class GZipFactory
}
/// <inheritdoc/>
public ValueTask<IWriter> OpenAsync(
public IWriter OpenAsync(
Stream stream,
WriterOptions writerOptions,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return new(Open(stream, writerOptions));
if (writerOptions.CompressionType != CompressionType.GZip)
{
throw new InvalidFormatException("GZip archives only support GZip compression type.");
}
return Open(stream, writerOptions);
}
#endregion

View File

@@ -50,22 +50,26 @@ public class RarFactory : Factory, IArchiveFactory, IMultiArchiveFactory, IReade
RarArchive.Open(stream, readerOptions);
/// <inheritdoc/>
public ValueTask<IAsyncArchive> OpenAsync(
public IAsyncArchive OpenAsync(
Stream stream,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
) => RarArchive.OpenAsync(stream, readerOptions, cancellationToken);
) => (IAsyncArchive)Open(stream, readerOptions);
/// <inheritdoc/>
public IArchive Open(FileInfo fileInfo, ReaderOptions? readerOptions = null) =>
RarArchive.Open(fileInfo, readerOptions);
/// <inheritdoc/>
public ValueTask<IAsyncArchive> OpenAsync(
public IAsyncArchive OpenAsync(
FileInfo fileInfo,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
) => RarArchive.OpenAsync(fileInfo, readerOptions, cancellationToken);
)
{
cancellationToken.ThrowIfCancellationRequested();
return (IAsyncArchive)Open(fileInfo, readerOptions);
}
public override ValueTask<bool> IsArchiveAsync(
Stream stream,
@@ -82,22 +86,26 @@ public class RarFactory : Factory, IArchiveFactory, IMultiArchiveFactory, IReade
RarArchive.Open(streams, readerOptions);
/// <inheritdoc/>
public ValueTask<IAsyncArchive> OpenAsync(
public IAsyncArchive OpenAsync(
IReadOnlyList<Stream> streams,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
) => RarArchive.OpenAsync(streams, readerOptions, cancellationToken);
) => (IAsyncArchive)Open(streams, readerOptions);
/// <inheritdoc/>
public IArchive Open(IReadOnlyList<FileInfo> fileInfos, ReaderOptions? readerOptions = null) =>
RarArchive.Open(fileInfos, readerOptions);
/// <inheritdoc/>
public ValueTask<IAsyncArchive> OpenAsync(
public IAsyncArchive OpenAsync(
IReadOnlyList<FileInfo> fileInfos,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
) => RarArchive.OpenAsync(fileInfos, readerOptions, cancellationToken);
)
{
cancellationToken.ThrowIfCancellationRequested();
return (IAsyncArchive)Open(fileInfos, readerOptions);
}
#endregion
@@ -108,14 +116,14 @@ public class RarFactory : Factory, IArchiveFactory, IMultiArchiveFactory, IReade
RarReader.Open(stream, options);
/// <inheritdoc/>
public ValueTask<IAsyncReader> OpenReaderAsync(
public IAsyncReader OpenReaderAsync(
Stream stream,
ReaderOptions? options,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return new((IAsyncReader)RarReader.Open(stream, options));
return (IAsyncReader)RarReader.Open(stream, options);
}
#endregion

View File

@@ -45,22 +45,26 @@ public class SevenZipFactory : Factory, IArchiveFactory, IMultiArchiveFactory
SevenZipArchive.Open(stream, readerOptions);
/// <inheritdoc/>
public ValueTask<IAsyncArchive> OpenAsync(
public IAsyncArchive OpenAsync(
Stream stream,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
) => SevenZipArchive.OpenAsync(stream, readerOptions, cancellationToken);
) => (IAsyncArchive)Open(stream, readerOptions);
/// <inheritdoc/>
public IArchive Open(FileInfo fileInfo, ReaderOptions? readerOptions = null) =>
SevenZipArchive.Open(fileInfo, readerOptions);
/// <inheritdoc/>
public ValueTask<IAsyncArchive> OpenAsync(
public IAsyncArchive OpenAsync(
FileInfo fileInfo,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
) => SevenZipArchive.OpenAsync(fileInfo, readerOptions, cancellationToken);
)
{
cancellationToken.ThrowIfCancellationRequested();
return (IAsyncArchive)Open(fileInfo, readerOptions);
}
public override ValueTask<bool> IsArchiveAsync(
Stream stream,
@@ -77,22 +81,26 @@ public class SevenZipFactory : Factory, IArchiveFactory, IMultiArchiveFactory
SevenZipArchive.Open(streams, readerOptions);
/// <inheritdoc/>
public ValueTask<IAsyncArchive> OpenAsync(
public IAsyncArchive OpenAsync(
IReadOnlyList<Stream> streams,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
) => SevenZipArchive.OpenAsync(streams, readerOptions, cancellationToken);
) => (IAsyncArchive)Open(streams, readerOptions);
/// <inheritdoc/>
public IArchive Open(IReadOnlyList<FileInfo> fileInfos, ReaderOptions? readerOptions = null) =>
SevenZipArchive.Open(fileInfos, readerOptions);
/// <inheritdoc/>
public ValueTask<IAsyncArchive> OpenAsync(
public IAsyncArchive OpenAsync(
IReadOnlyList<FileInfo> fileInfos,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
) => SevenZipArchive.OpenAsync(fileInfos, readerOptions, cancellationToken);
)
{
cancellationToken.ThrowIfCancellationRequested();
return (IAsyncArchive)Open(fileInfos, readerOptions);
}
#endregion

View File

@@ -76,22 +76,26 @@ public class TarFactory
TarArchive.Open(stream, readerOptions);
/// <inheritdoc/>
public ValueTask<IAsyncArchive> OpenAsync(
public IAsyncArchive OpenAsync(
Stream stream,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
) => TarArchive.OpenAsync(stream, readerOptions, cancellationToken);
) => (IAsyncArchive)Open(stream, readerOptions);
/// <inheritdoc/>
public IArchive Open(FileInfo fileInfo, ReaderOptions? readerOptions = null) =>
TarArchive.Open(fileInfo, readerOptions);
/// <inheritdoc/>
public ValueTask<IAsyncArchive> OpenAsync(
public IAsyncArchive OpenAsync(
FileInfo fileInfo,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
) => TarArchive.OpenAsync(fileInfo, readerOptions, cancellationToken);
)
{
cancellationToken.ThrowIfCancellationRequested();
return (IAsyncArchive)Open(fileInfo, readerOptions);
}
#endregion
@@ -102,22 +106,26 @@ public class TarFactory
TarArchive.Open(streams, readerOptions);
/// <inheritdoc/>
public ValueTask<IAsyncArchive> OpenAsync(
public IAsyncArchive OpenAsync(
IReadOnlyList<Stream> streams,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
) => TarArchive.OpenAsync(streams, readerOptions, cancellationToken);
) => (IAsyncArchive)Open(streams, readerOptions);
/// <inheritdoc/>
public IArchive Open(IReadOnlyList<FileInfo> fileInfos, ReaderOptions? readerOptions = null) =>
TarArchive.Open(fileInfos, readerOptions);
/// <inheritdoc/>
public ValueTask<IAsyncArchive> OpenAsync(
public IAsyncArchive OpenAsync(
IReadOnlyList<FileInfo> fileInfos,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
) => TarArchive.OpenAsync(fileInfos, readerOptions, cancellationToken);
)
{
cancellationToken.ThrowIfCancellationRequested();
return (IAsyncArchive)Open(fileInfos, readerOptions);
}
#endregion
@@ -271,14 +279,14 @@ public class TarFactory
TarReader.Open(stream, options);
/// <inheritdoc/>
public ValueTask<IAsyncReader> OpenReaderAsync(
public IAsyncReader OpenReaderAsync(
Stream stream,
ReaderOptions? options,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return new((IAsyncReader)TarReader.Open(stream, options));
return (IAsyncReader)TarReader.Open(stream, options);
}
#endregion
@@ -290,14 +298,14 @@ public class TarFactory
new TarWriter(stream, new TarWriterOptions(writerOptions));
/// <inheritdoc/>
public ValueTask<IWriter> OpenAsync(
public IWriter OpenAsync(
Stream stream,
WriterOptions writerOptions,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return new(Open(stream, writerOptions));
return Open(stream, writerOptions);
}
#endregion

View File

@@ -143,22 +143,26 @@ public class ZipFactory
ZipArchive.Open(stream, readerOptions);
/// <inheritdoc/>
public ValueTask<IAsyncArchive> OpenAsync(
public IAsyncArchive OpenAsync(
Stream stream,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
) => ZipArchive.OpenAsync(stream, readerOptions, cancellationToken);
) => (IAsyncArchive)Open(stream, readerOptions);
/// <inheritdoc/>
public IArchive Open(FileInfo fileInfo, ReaderOptions? readerOptions = null) =>
ZipArchive.Open(fileInfo, readerOptions);
/// <inheritdoc/>
public ValueTask<IAsyncArchive> OpenAsync(
public IAsyncArchive OpenAsync(
FileInfo fileInfo,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
) => ZipArchive.OpenAsync(fileInfo, readerOptions, cancellationToken);
)
{
cancellationToken.ThrowIfCancellationRequested();
return (IAsyncArchive)Open(fileInfo, readerOptions);
}
#endregion
@@ -169,22 +173,26 @@ public class ZipFactory
ZipArchive.Open(streams, readerOptions);
/// <inheritdoc/>
public ValueTask<IAsyncArchive> OpenAsync(
public IAsyncArchive OpenAsync(
IReadOnlyList<Stream> streams,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
) => ZipArchive.OpenAsync(streams, readerOptions, cancellationToken);
) => (IAsyncArchive)Open(streams, readerOptions);
/// <inheritdoc/>
public IArchive Open(IReadOnlyList<FileInfo> fileInfos, ReaderOptions? readerOptions = null) =>
ZipArchive.Open(fileInfos, readerOptions);
/// <inheritdoc/>
public ValueTask<IAsyncArchive> OpenAsync(
public IAsyncArchive OpenAsync(
IReadOnlyList<FileInfo> fileInfos,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
) => ZipArchive.OpenAsync(fileInfos, readerOptions, cancellationToken);
)
{
cancellationToken.ThrowIfCancellationRequested();
return (IAsyncArchive)Open(fileInfos, readerOptions);
}
#endregion
@@ -195,14 +203,14 @@ public class ZipFactory
ZipReader.Open(stream, options);
/// <inheritdoc/>
public ValueTask<IAsyncReader> OpenReaderAsync(
public IAsyncReader OpenReaderAsync(
Stream stream,
ReaderOptions? options,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return new((IAsyncReader)ZipReader.Open(stream, options));
return (IAsyncReader)ZipReader.Open(stream, options);
}
#endregion
@@ -214,14 +222,14 @@ public class ZipFactory
new ZipWriter(stream, new ZipWriterOptions(writerOptions));
/// <inheritdoc/>
public ValueTask<IWriter> OpenAsync(
public IWriter OpenAsync(
Stream stream,
WriterOptions writerOptions,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return new(Open(stream, writerOptions));
return Open(stream, writerOptions);
}
#endregion

View File

@@ -84,7 +84,6 @@ public static class AsyncEnumerableExtensions
throw new InvalidOperationException("The source sequence is empty."); // Throws if the stream is empty
}
public async ValueTask<T?> FirstOrDefaultAsync()
{
await foreach (var item in source)

View File

@@ -1,6 +1,5 @@
using System.IO;
using System.Threading;
using System.Threading.Tasks;
namespace SharpCompress.Readers;
@@ -13,7 +12,7 @@ public interface IReaderFactory : Factories.IFactory
/// <param name="options"></param>
/// <returns></returns>
IReader OpenReader(Stream stream, ReaderOptions? options);
ValueTask<IAsyncReader> OpenReaderAsync(
IAsyncReader OpenReaderAsync(
Stream stream,
ReaderOptions? options,
CancellationToken cancellationToken

View File

@@ -24,7 +24,7 @@ public static class ReaderFactory
/// <param name="options"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public static ValueTask<IAsyncReader> OpenAsync(
public static IAsyncReader OpenAsync(
string filePath,
ReaderOptions? options = null,
CancellationToken cancellationToken = default
@@ -47,7 +47,7 @@ public static class ReaderFactory
/// <param name="options"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public static ValueTask<IAsyncReader> OpenAsync(
public static IAsyncReader OpenAsync(
FileInfo fileInfo,
ReaderOptions? options = null,
CancellationToken cancellationToken = default
@@ -110,7 +110,7 @@ public static class ReaderFactory
);
}
public static async ValueTask<IAsyncReader> OpenAsync(
public static IAsyncReader OpenAsync(
Stream stream,
ReaderOptions? options = null,
CancellationToken cancellationToken = default
@@ -136,19 +136,10 @@ public static class ReaderFactory
if (testedFactory is IReaderFactory readerFactory)
{
((IStreamStack)bStream).StackSeek(pos);
if (
await testedFactory.IsArchiveAsync(
bStream,
options.Password,
options.BufferSize,
cancellationToken
)
)
if (testedFactory.IsArchive(bStream))
{
((IStreamStack)bStream).StackSeek(pos);
return await readerFactory
.OpenReaderAsync(bStream, options, cancellationToken)
.ConfigureAwait(false);
return readerFactory.OpenReaderAsync(bStream, options, cancellationToken);
}
}
((IStreamStack)bStream).StackSeek(pos);
@@ -161,20 +152,10 @@ public static class ReaderFactory
continue; // Already tested above
}
((IStreamStack)bStream).StackSeek(pos);
if (
factory is IReaderFactory readerFactory
&& await factory.IsArchiveAsync(
bStream,
options.Password,
options.BufferSize,
cancellationToken
)
)
if (factory is IReaderFactory readerFactory && factory.IsArchive(bStream))
{
((IStreamStack)bStream).StackSeek(pos);
return await readerFactory
.OpenReaderAsync(bStream, options, cancellationToken)
.ConfigureAwait(false);
return readerFactory.OpenReaderAsync(bStream, options, cancellationToken);
}
}

View File

@@ -1,6 +1,5 @@
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using SharpCompress.Factories;
namespace SharpCompress.Writers;
@@ -9,7 +8,7 @@ public interface IWriterFactory : IFactory
{
IWriter Open(Stream stream, WriterOptions writerOptions);
ValueTask<IWriter> OpenAsync(
IWriter OpenAsync(
Stream stream,
WriterOptions writerOptions,
CancellationToken cancellationToken = default

View File

@@ -31,7 +31,7 @@ public static class WriterFactory
/// <param name="writerOptions">Writer options.</param>
/// <param name="cancellationToken">Cancellation token.</param>
/// <returns>A task that returns an IWriter.</returns>
public static async ValueTask<IWriter> OpenAsync(
public static IWriter OpenAsync(
Stream stream,
ArchiveType archiveType,
WriterOptions writerOptions,
@@ -44,9 +44,7 @@ public static class WriterFactory
if (factory != null)
{
return await factory
.OpenAsync(stream, writerOptions, cancellationToken)
.ConfigureAwait(false);
return factory.OpenAsync(stream, writerOptions, cancellationToken);
}
throw new NotSupportedException("Archive Type does not have a Writer: " + archiveType);

View File

@@ -103,7 +103,13 @@ public class AsyncTests : TestBase
#else
await using (var stream = File.Create(outputPath))
#endif
await using (var writer = await WriterFactory.OpenAsync(stream, ArchiveType.Zip, CompressionType.Deflate))
await using (
var writer = await WriterFactory.OpenAsync(
stream,
ArchiveType.Zip,
CompressionType.Deflate
)
)
{
var testFile = Path.Combine(TEST_ARCHIVES_PATH, "Tar.tar.gz");

View File

@@ -75,7 +75,9 @@ public class GZipArchiveAsyncTests : ArchiveTests
await using Stream stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "Tar.tar.gz"));
#endif
await using var archive = await GZipArchive.OpenAsync(stream);
await Assert.ThrowsAsync<InvalidFormatException>(() => archive.AddEntry("jpg\\test.jpg", jpg));
await Assert.ThrowsAsync<InvalidFormatException>(() =>
archive.AddEntry("jpg\\test.jpg", jpg)
);
await archive.SaveToAsync(Path.Combine(SCRATCH_FILES_PATH, "Tar.tar.gz"));
}