switch Task to ValueTask

This commit is contained in:
Adam Hathcock
2026-01-08 10:22:53 +00:00
parent 60e5220bd0
commit 8e42296c3a
27 changed files with 387 additions and 199 deletions

View File

@@ -8,7 +8,7 @@ using SharpCompress.Readers;
namespace SharpCompress.Archives;
class AutoArchiveFactory : IArchiveFactory
internal class AutoArchiveFactory : IArchiveFactory
{
public string Name => nameof(AutoArchiveFactory);
@@ -22,7 +22,7 @@ class AutoArchiveFactory : IArchiveFactory
int bufferSize = ReaderOptions.DefaultBufferSize
) => throw new NotSupportedException();
public Task<bool> IsArchiveAsync(
public ValueTask<bool> IsArchiveAsync(
Stream stream,
string? password = null,
int bufferSize = ReaderOptions.DefaultBufferSize,
@@ -34,18 +34,18 @@ class AutoArchiveFactory : IArchiveFactory
public IArchive Open(Stream stream, ReaderOptions? readerOptions = null) =>
ArchiveFactory.Open(stream, readerOptions);
public Task<IArchiveAsync> OpenAsync(
public async ValueTask<IArchiveAsync> OpenAsync(
Stream stream,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
) => ArchiveFactory.OpenAsync(stream, readerOptions, cancellationToken);
) => await ArchiveFactory.OpenAsync(stream, readerOptions, cancellationToken);
public IArchive Open(FileInfo fileInfo, ReaderOptions? readerOptions = null) =>
ArchiveFactory.Open(fileInfo, readerOptions);
public Task<IArchiveAsync> OpenAsync(
public async ValueTask<IArchiveAsync> OpenAsync(
FileInfo fileInfo,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
) => ArchiveFactory.OpenAsync(fileInfo, readerOptions, cancellationToken);
) => await ArchiveFactory.OpenAsync(fileInfo, readerOptions, cancellationToken);
}

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 async Task<IArchiveAsync> OpenAsync(
public static ValueTask<IArchiveAsync> OpenAsync(
Stream stream,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return await Task.FromResult(Open(stream, readerOptions)).ConfigureAwait(false);
return new(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 async Task<IArchiveAsync> OpenAsync(
public static ValueTask<IArchiveAsync> OpenAsync(
FileInfo fileInfo,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return await Task.FromResult(Open(fileInfo, readerOptions)).ConfigureAwait(false);
return new(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 async Task<IArchiveAsync> OpenAsync(
public static ValueTask<IArchiveAsync> OpenAsync(
IReadOnlyList<Stream> streams,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return await Task.FromResult(Open(streams, readerOptions)).ConfigureAwait(false);
return new(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 async Task<IArchiveAsync> OpenAsync(
public static ValueTask<IArchiveAsync> OpenAsync(
IReadOnlyList<FileInfo> fileInfos,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return await Task.FromResult(Open(fileInfos, readerOptions)).ConfigureAwait(false);
return new(Open(fileInfos, readerOptions));
}
public static GZipArchive Create() => new();
@@ -231,7 +231,7 @@ public class GZipArchive : AbstractWritableArchive<GZipArchiveEntry, GZipVolume>
return true;
}
public static async Task<bool> IsGZipFileAsync(
public static async ValueTask<bool> IsGZipFileAsync(
Stream stream,
CancellationToken cancellationToken = default
)

View File

@@ -0,0 +1,100 @@
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
{
/// <param name="archive">The archive to extract.</param>
extension(IArchiveAsync archive)
{
/// <summary>
/// Extract to specific directory asynchronously with progress reporting and cancellation support
/// </summary>
/// <param name="destinationDirectory">The folder to extract into.</param>
/// <param name="options">Extraction options.</param>
/// <param name="progress">Optional progress reporter for tracking extraction progress.</param>
/// <param name="cancellationToken">Optional cancellation token.</param>
public async Task WriteToDirectoryAsync(
string destinationDirectory,
ExtractionOptions? options = null,
IProgress<ProgressReport>? progress = null,
CancellationToken cancellationToken = default
)
{
// For solid archives (Rar, 7Zip), use the optimized reader-based approach
if (await archive.IsSolidAsync() || archive.Type == ArchiveType.SevenZip)
{
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<ProgressReport>? progress,
CancellationToken cancellationToken
)
{
// Prepare for progress reporting
var totalBytes = await archive.TotalUncompressSizeAsync();
var bytesRead = 0L;
// Tracking for created directories.
var seenDirectories = new HashSet<string>();
// 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)
);
}
}
}
}

View File

@@ -1,8 +1,6 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using SharpCompress.Common;
using SharpCompress.Readers;
@@ -80,89 +78,5 @@ public static class IArchiveExtensions
);
}
}
/// <summary>
/// Extract to specific directory asynchronously with progress reporting and cancellation support
/// </summary>
/// <param name="destinationDirectory">The folder to extract into.</param>
/// <param name="options">Extraction options.</param>
/// <param name="progress">Optional progress reporter for tracking extraction progress.</param>
/// <param name="cancellationToken">Optional cancellation token.</param>
public async Task WriteToDirectoryAsync(
string destinationDirectory,
ExtractionOptions? options = null,
IProgress<ProgressReport>? progress = null,
CancellationToken cancellationToken = default
)
{
// For solid archives (Rar, 7Zip), use the optimized reader-based approach
if (archive.IsSolid || archive.Type == ArchiveType.SevenZip)
{
using var reader = archive.ExtractAllEntries();
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<ProgressReport>? progress,
CancellationToken cancellationToken
)
{
// Prepare for progress reporting
var totalBytes = archive.TotalUncompressSize;
var bytesRead = 0L;
// Tracking for created directories.
var seenDirectories = new HashSet<string>();
// Extract
foreach (var entry in archive.Entries)
{
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)
);
}
}
}
}

View File

@@ -34,7 +34,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>
Task<IArchiveAsync> OpenAsync(
ValueTask<IArchiveAsync> OpenAsync(
Stream stream,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
@@ -53,7 +53,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>
Task<IArchiveAsync> OpenAsync(
ValueTask<IArchiveAsync> OpenAsync(
FileInfo fileInfo,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default

View File

@@ -35,7 +35,7 @@ public interface IMultiArchiveFactory : IFactory
/// <param name="streams"></param>
/// <param name="readerOptions">reading options.</param>
/// <param name="cancellationToken">Cancellation token.</param>
Task<IArchiveAsync> OpenAsync(
ValueTask<IArchiveAsync> OpenAsync(
IReadOnlyList<Stream> streams,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
@@ -54,7 +54,7 @@ public interface IMultiArchiveFactory : IFactory
/// <param name="fileInfos"></param>
/// <param name="readerOptions">reading options.</param>
/// <param name="cancellationToken">Cancellation token.</param>
Task<IArchiveAsync> OpenAsync(
ValueTask<IArchiveAsync> OpenAsync(
IReadOnlyList<FileInfo> fileInfos,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default

View File

@@ -189,14 +189,14 @@ public class RarArchive : AbstractArchive<RarArchiveEntry, RarVolume>
/// <param name="stream"></param>
/// <param name="readerOptions"></param>
/// <param name="cancellationToken"></param>
public static async Task<IArchiveAsync> OpenAsync(
public static ValueTask<IArchiveAsync> OpenAsync(
Stream stream,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return await Task.FromResult(Open(stream, readerOptions)).ConfigureAwait(false);
return new(Open(stream, readerOptions));
}
/// <summary>
@@ -205,14 +205,14 @@ public class RarArchive : AbstractArchive<RarArchiveEntry, RarVolume>
/// <param name="fileInfo"></param>
/// <param name="readerOptions"></param>
/// <param name="cancellationToken"></param>
public static async Task<IArchiveAsync> OpenAsync(
public static ValueTask<IArchiveAsync> OpenAsync(
FileInfo fileInfo,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return await Task.FromResult(Open(fileInfo, readerOptions)).ConfigureAwait(false);
return new(Open(fileInfo, readerOptions));
}
/// <summary>
@@ -221,14 +221,14 @@ public class RarArchive : AbstractArchive<RarArchiveEntry, RarVolume>
/// <param name="streams"></param>
/// <param name="readerOptions"></param>
/// <param name="cancellationToken"></param>
public static async Task<IArchiveAsync> OpenAsync(
public static ValueTask<IArchiveAsync> OpenAsync(
IReadOnlyList<Stream> streams,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return await Task.FromResult(Open(streams, readerOptions)).ConfigureAwait(false);
return new(Open(streams, readerOptions));
}
/// <summary>
@@ -237,14 +237,14 @@ public class RarArchive : AbstractArchive<RarArchiveEntry, RarVolume>
/// <param name="fileInfos"></param>
/// <param name="readerOptions"></param>
/// <param name="cancellationToken"></param>
public static async Task<IArchiveAsync> OpenAsync(
public static ValueTask<IArchiveAsync> OpenAsync(
IReadOnlyList<FileInfo> fileInfos,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return await Task.FromResult(Open(fileInfos, readerOptions)).ConfigureAwait(false);
return new(Open(fileInfos, readerOptions));
}
public static bool IsRarFile(string filePath) => IsRarFile(new FileInfo(filePath));

View File

@@ -111,14 +111,14 @@ public class SevenZipArchive : AbstractArchive<SevenZipArchiveEntry, SevenZipVol
/// <param name="stream"></param>
/// <param name="readerOptions"></param>
/// <param name="cancellationToken"></param>
public static async Task<IArchiveAsync> OpenAsync(
public static ValueTask<IArchiveAsync> OpenAsync(
Stream stream,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return await Task.FromResult(Open(stream, readerOptions)).ConfigureAwait(false);
return new(Open(stream, readerOptions));
}
/// <summary>
@@ -127,14 +127,14 @@ public class SevenZipArchive : AbstractArchive<SevenZipArchiveEntry, SevenZipVol
/// <param name="fileInfo"></param>
/// <param name="readerOptions"></param>
/// <param name="cancellationToken"></param>
public static async Task<IArchiveAsync> OpenAsync(
public static ValueTask<IArchiveAsync> OpenAsync(
FileInfo fileInfo,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return await Task.FromResult(Open(fileInfo, readerOptions)).ConfigureAwait(false);
return new(Open(fileInfo, readerOptions));
}
/// <summary>
@@ -143,14 +143,14 @@ public class SevenZipArchive : AbstractArchive<SevenZipArchiveEntry, SevenZipVol
/// <param name="streams"></param>
/// <param name="readerOptions"></param>
/// <param name="cancellationToken"></param>
public static async Task<IArchiveAsync> OpenAsync(
public static ValueTask<IArchiveAsync> OpenAsync(
IReadOnlyList<Stream> streams,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return await Task.FromResult(Open(streams, readerOptions)).ConfigureAwait(false);
return new(Open(streams, readerOptions));
}
/// <summary>
@@ -159,14 +159,14 @@ public class SevenZipArchive : AbstractArchive<SevenZipArchiveEntry, SevenZipVol
/// <param name="fileInfos"></param>
/// <param name="readerOptions"></param>
/// <param name="cancellationToken"></param>
public static async Task<IArchiveAsync> OpenAsync(
public static ValueTask<IArchiveAsync> OpenAsync(
IReadOnlyList<FileInfo> fileInfos,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return await Task.FromResult(Open(fileInfos, readerOptions)).ConfigureAwait(false);
return new(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 async Task<IArchiveAsync> OpenAsync(
public static ValueTask<IArchiveAsync> OpenAsync(
Stream stream,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return await Task.FromResult(Open(stream, readerOptions)).ConfigureAwait(false);
return new(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 async Task<IArchiveAsync> OpenAsync(
public static ValueTask<IArchiveAsync> OpenAsync(
FileInfo fileInfo,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return await Task.FromResult(Open(fileInfo, readerOptions)).ConfigureAwait(false);
return new(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 async Task<IArchiveAsync> OpenAsync(
public static ValueTask<IArchiveAsync> OpenAsync(
IReadOnlyList<Stream> streams,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return await Task.FromResult(Open(streams, readerOptions)).ConfigureAwait(false);
return new(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 async Task<IArchiveAsync> OpenAsync(
public static ValueTask<IArchiveAsync> OpenAsync(
IReadOnlyList<FileInfo> fileInfos,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return await Task.FromResult(Open(fileInfos, readerOptions)).ConfigureAwait(false);
return new(Open(fileInfos, readerOptions));
}
public static bool IsTarFile(string filePath) => IsTarFile(new FileInfo(filePath));

View File

@@ -130,14 +130,14 @@ public class ZipArchive : AbstractWritableArchive<ZipArchiveEntry, ZipVolume>
/// <param name="stream"></param>
/// <param name="readerOptions"></param>
/// <param name="cancellationToken"></param>
public static async Task<IArchiveAsync> OpenAsync(
public static ValueTask<IArchiveAsync> OpenAsync(
Stream stream,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return await Task.FromResult(Open(stream, readerOptions)).ConfigureAwait(false);
return new(Open(stream, readerOptions));
}
/// <summary>
@@ -146,14 +146,14 @@ public class ZipArchive : AbstractWritableArchive<ZipArchiveEntry, ZipVolume>
/// <param name="fileInfo"></param>
/// <param name="readerOptions"></param>
/// <param name="cancellationToken"></param>
public static async Task<IArchiveAsync> OpenAsync(
public static ValueTask<IArchiveAsync> OpenAsync(
FileInfo fileInfo,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return await Task.FromResult(Open(fileInfo, readerOptions)).ConfigureAwait(false);
return new(Open(fileInfo, readerOptions));
}
/// <summary>
@@ -162,14 +162,14 @@ public class ZipArchive : AbstractWritableArchive<ZipArchiveEntry, ZipVolume>
/// <param name="streams"></param>
/// <param name="readerOptions"></param>
/// <param name="cancellationToken"></param>
public static async Task<IArchiveAsync> OpenAsync(
public static ValueTask<IArchiveAsync> OpenAsync(
IReadOnlyList<Stream> streams,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return await Task.FromResult(Open(streams, readerOptions)).ConfigureAwait(false);
return new(Open(streams, readerOptions));
}
/// <summary>
@@ -178,14 +178,14 @@ public class ZipArchive : AbstractWritableArchive<ZipArchiveEntry, ZipVolume>
/// <param name="fileInfos"></param>
/// <param name="readerOptions"></param>
/// <param name="cancellationToken"></param>
public static async Task<IArchiveAsync> OpenAsync(
public static ValueTask<IArchiveAsync> OpenAsync(
IReadOnlyList<FileInfo> fileInfos,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return await Task.FromResult(Open(fileInfos, readerOptions)).ConfigureAwait(false);
return new(Open(fileInfos, readerOptions));
}
public static bool IsZipFile(
@@ -283,7 +283,7 @@ public class ZipArchive : AbstractWritableArchive<ZipArchiveEntry, ZipVolume>
}
}
public static async Task<bool> IsZipFileAsync(
public static async ValueTask<bool> IsZipFileAsync(
Stream stream,
string? password = null,
int bufferSize = ReaderOptions.DefaultBufferSize,
@@ -319,7 +319,7 @@ public class ZipArchive : AbstractWritableArchive<ZipArchiveEntry, ZipVolume>
}
}
public static async Task<bool> IsZipMultiAsync(
public static async ValueTask<bool> IsZipMultiAsync(
Stream stream,
string? password = null,
int bufferSize = ReaderOptions.DefaultBufferSize,
@@ -345,7 +345,8 @@ public class ZipArchive : AbstractWritableArchive<ZipArchiveEntry, ZipVolume>
var z = new SeekableZipHeaderFactory(password, new ArchiveEncoding());
ZipHeader? x = null;
await foreach (
var h in z.ReadSeekableHeader(stream).WithCancellation(cancellationToken)
var h in z.ReadSeekableHeaderAsync(stream)
.WithCancellation(cancellationToken)
)
{
x = h;
@@ -451,6 +452,59 @@ public class ZipArchive : AbstractWritableArchive<ZipArchiveEntry, ZipVolume>
}
}
protected override async IAsyncEnumerable<ZipArchiveEntry> LoadEntriesAsync(
IAsyncEnumerable<ZipVolume> volumes
)
{
var vols = await volumes.ToListAsync();
var volsArray = vols.ToArray();
await foreach (
var h in headerFactory.NotNull().ReadSeekableHeaderAsync(volsArray.Last().Stream)
)
{
if (h != null)
{
switch (h.ZipHeaderType)
{
case ZipHeaderType.DirectoryEntry:
{
var deh = (DirectoryEntryHeader)h;
Stream s;
if (
deh.RelativeOffsetOfEntryHeader + deh.CompressedSize
> volsArray[deh.DiskNumberStart].Stream.Length
)
{
var v = volsArray.Skip(deh.DiskNumberStart).ToArray();
s = new SourceStream(
v[0].Stream,
i => i < v.Length ? v[i].Stream : null,
new ReaderOptions() { LeaveStreamOpen = true }
);
}
else
{
s = volsArray[deh.DiskNumberStart].Stream;
}
yield return new ZipArchiveEntry(
this,
new SeekableZipFilePart(headerFactory.NotNull(), deh, s)
);
}
break;
case ZipHeaderType.DirectoryEnd:
{
var bytes = ((DirectoryEndHeader)h).Comment ?? Array.Empty<byte>();
volsArray.Last().Comment = ReaderOptions.ArchiveEncoding.Decode(bytes);
yield break;
}
}
}
}
}
public void SaveTo(Stream stream) => SaveTo(stream, new WriterOptions(CompressionType.Deflate));
protected override void SaveTo(

View File

@@ -13,9 +13,17 @@ public class ZipArchiveEntry : ZipEntry, IArchiveEntry
public virtual Stream OpenEntryStream() => Parts.Single().GetCompressedStream().NotNull();
public virtual Task<Stream> OpenEntryStreamAsync(
public virtual async Task<Stream> OpenEntryStreamAsync(
CancellationToken cancellationToken = default
) => Task.FromResult(OpenEntryStream());
)
{
var part = Parts.Single();
if (part is SeekableZipFilePart seekablePart)
{
return (await seekablePart.GetCompressedStreamAsync(cancellationToken)).NotNull();
}
return OpenEntryStream();
}
#region IArchiveEntry Members

View File

@@ -1,4 +1,6 @@
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using SharpCompress.Common.Zip.Headers;
namespace SharpCompress.Common.Zip;
@@ -25,9 +27,24 @@ internal class SeekableZipFilePart : ZipFilePart
return base.GetCompressedStream();
}
internal override async Task<Stream?> GetCompressedStreamAsync(
CancellationToken cancellationToken = default
)
{
if (!_isLocalHeaderLoaded)
{
await LoadLocalHeaderAsync(cancellationToken);
_isLocalHeaderLoaded = true;
}
return await base.GetCompressedStreamAsync(cancellationToken);
}
private void LoadLocalHeader() =>
Header = _headerFactory.GetLocalHeader(BaseStream, (DirectoryEntryHeader)Header);
private async ValueTask LoadLocalHeaderAsync(CancellationToken cancellationToken = default) =>
Header = await _headerFactory.GetLocalHeaderAsync(BaseStream, (DirectoryEntryHeader)Header);
protected override Stream CreateBaseStream()
{
BaseStream.Position = Header.DataStartPosition.NotNull();

View File

@@ -19,11 +19,11 @@ internal sealed class SeekableZipHeaderFactory : ZipHeaderFactory
internal SeekableZipHeaderFactory(string? password, ArchiveEncoding archiveEncoding)
: base(StreamingMode.Seekable, password, archiveEncoding) { }
internal async IAsyncEnumerable<ZipHeader> ReadSeekableHeader(Stream stream)
internal async IAsyncEnumerable<ZipHeader> ReadSeekableHeaderAsync(Stream stream)
{
var reader = new AsyncBinaryReader(stream);
await SeekBackToHeader(stream, reader);
await SeekBackToHeaderAsync(stream, reader);
var eocd_location = stream.Position;
var entry = new DirectoryEndHeader();
@@ -153,6 +153,73 @@ internal sealed class SeekableZipHeaderFactory : ZipHeaderFactory
}
}
internal async IAsyncEnumerable<ZipHeader> 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)
{
for (var i = 0; i < needle.Length; i++)
@@ -166,7 +233,7 @@ internal sealed class SeekableZipHeaderFactory : ZipHeaderFactory
return true;
}
private static async ValueTask SeekBackToHeader(Stream stream, AsyncBinaryReader reader)
private static async ValueTask SeekBackToHeaderAsync(Stream stream, AsyncBinaryReader reader)
{
// Minimum EOCD length
if (stream.Length < MINIMUM_EOCD_LENGTH)
@@ -270,4 +337,31 @@ internal sealed class SeekableZipHeaderFactory : ZipHeaderFactory
}
return localEntryHeader;
}
internal async ValueTask<LocalEntryHeader> GetLocalHeaderAsync(
Stream stream,
DirectoryEntryHeader directoryEntryHeader
)
{
stream.Seek(directoryEntryHeader.RelativeOffsetOfEntryHeader, SeekOrigin.Begin);
var reader = new AsyncBinaryReader(stream);
var signature = await reader.ReadUInt32Async();
if (await ReadHeader(signature, reader, _zip64) is not LocalEntryHeader localEntryHeader)
{
throw new InvalidOperationException();
}
// populate fields only known from the DirectoryEntryHeader
localEntryHeader.HasData = directoryEntryHeader.HasData;
localEntryHeader.ExternalFileAttributes = directoryEntryHeader.ExternalFileAttributes;
localEntryHeader.Comment = directoryEntryHeader.Comment;
if (FlagUtility.HasFlag(localEntryHeader.Flags, HeaderFlags.UsePostDataDescriptor))
{
localEntryHeader.Crc = directoryEntryHeader.Crc;
localEntryHeader.CompressedSize = directoryEntryHeader.CompressedSize;
localEntryHeader.UncompressedSize = directoryEntryHeader.UncompressedSize;
}
return localEntryHeader;
}
}

View File

@@ -35,10 +35,10 @@ namespace SharpCompress.Factories
public IReader OpenReader(Stream stream, ReaderOptions? options) =>
AceReader.Open(stream, options);
public Task<IReader> OpenReaderAsync(
public ValueTask<IReader> OpenReaderAsync(
Stream stream,
ReaderOptions? options,
CancellationToken cancellationToken = default
) => Task.FromResult(OpenReader(stream, options));
) => new(OpenReader(stream, options));
}
}

View File

@@ -44,14 +44,14 @@ namespace SharpCompress.Factories
public IReader OpenReader(Stream stream, ReaderOptions? options) =>
ArcReader.Open(stream, options);
public async Task<IReader> OpenReaderAsync(
public ValueTask<IReader> OpenReaderAsync(
Stream stream,
ReaderOptions? options,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return await Task.FromResult(OpenReader(stream, options)).ConfigureAwait(false);
return new(OpenReader(stream, options));
}
}
}

View File

@@ -35,14 +35,14 @@ namespace SharpCompress.Factories
public IReader OpenReader(Stream stream, ReaderOptions? options) =>
ArjReader.Open(stream, options);
public async Task<IReader> OpenReaderAsync(
public ValueTask<IReader> OpenReaderAsync(
Stream stream,
ReaderOptions? options,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return await Task.FromResult(OpenReader(stream, options)).ConfigureAwait(false);
return new(OpenReader(stream, options));
}
}
}

View File

@@ -60,7 +60,7 @@ public abstract class Factory : IFactory
);
/// <inheritdoc/>
public virtual Task<bool> IsArchiveAsync(
public virtual ValueTask<bool> IsArchiveAsync(
Stream stream,
string? password = null,
int bufferSize = ReaderOptions.DefaultBufferSize,
@@ -68,7 +68,7 @@ public abstract class Factory : IFactory
)
{
cancellationToken.ThrowIfCancellationRequested();
return Task.FromResult(IsArchive(stream, password, bufferSize));
return new(IsArchive(stream, password, bufferSize));
}
/// <inheritdoc/>

View File

@@ -49,7 +49,7 @@ public class GZipFactory
) => GZipArchive.IsGZipFile(stream);
/// <inheritdoc/>
public override Task<bool> IsArchiveAsync(
public override ValueTask<bool> IsArchiveAsync(
Stream stream,
string? password = null,
int bufferSize = ReaderOptions.DefaultBufferSize,
@@ -65,7 +65,7 @@ public class GZipFactory
GZipArchive.Open(stream, readerOptions);
/// <inheritdoc/>
public Task<IArchiveAsync> OpenAsync(
public ValueTask<IArchiveAsync> OpenAsync(
Stream stream,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
@@ -76,7 +76,7 @@ public class GZipFactory
GZipArchive.Open(fileInfo, readerOptions);
/// <inheritdoc/>
public Task<IArchiveAsync> OpenAsync(
public ValueTask<IArchiveAsync> OpenAsync(
FileInfo fileInfo,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
@@ -91,7 +91,7 @@ public class GZipFactory
GZipArchive.Open(streams, readerOptions);
/// <inheritdoc/>
public Task<IArchiveAsync> OpenAsync(
public ValueTask<IArchiveAsync> OpenAsync(
IReadOnlyList<Stream> streams,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
@@ -102,7 +102,7 @@ public class GZipFactory
GZipArchive.Open(fileInfos, readerOptions);
/// <inheritdoc/>
public Task<IArchiveAsync> OpenAsync(
public ValueTask<IArchiveAsync> OpenAsync(
IReadOnlyList<FileInfo> fileInfos,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
@@ -147,14 +147,14 @@ public class GZipFactory
GZipReader.Open(stream, options);
/// <inheritdoc/>
public async Task<IReader> OpenReaderAsync(
public ValueTask<IReader> OpenReaderAsync(
Stream stream,
ReaderOptions? options,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return await Task.FromResult(OpenReader(stream, options)).ConfigureAwait(false);
return new(OpenReader(stream, options));
}
#endregion
@@ -172,14 +172,14 @@ public class GZipFactory
}
/// <inheritdoc/>
public async Task<IWriter> OpenAsync(
public ValueTask<IWriter> OpenAsync(
Stream stream,
WriterOptions writerOptions,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return await Task.FromResult(Open(stream, writerOptions)).ConfigureAwait(false);
return new(Open(stream, writerOptions));
}
#endregion

View File

@@ -51,7 +51,7 @@ public interface IFactory
/// <param name="password">optional password</param>
/// <param name="bufferSize">buffer size for reading</param>
/// <param name="cancellationToken">cancellation token</param>
Task<bool> IsArchiveAsync(
ValueTask<bool> IsArchiveAsync(
Stream stream,
string? password = null,
int bufferSize = ReaderOptions.DefaultBufferSize,

View File

@@ -50,7 +50,7 @@ public class RarFactory : Factory, IArchiveFactory, IMultiArchiveFactory, IReade
RarArchive.Open(stream, readerOptions);
/// <inheritdoc/>
public Task<IArchiveAsync> OpenAsync(
public ValueTask<IArchiveAsync> OpenAsync(
Stream stream,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
@@ -61,7 +61,7 @@ public class RarFactory : Factory, IArchiveFactory, IMultiArchiveFactory, IReade
RarArchive.Open(fileInfo, readerOptions);
/// <inheritdoc/>
public Task<IArchiveAsync> OpenAsync(
public ValueTask<IArchiveAsync> OpenAsync(
FileInfo fileInfo,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
@@ -76,7 +76,7 @@ public class RarFactory : Factory, IArchiveFactory, IMultiArchiveFactory, IReade
RarArchive.Open(streams, readerOptions);
/// <inheritdoc/>
public Task<IArchiveAsync> OpenAsync(
public ValueTask<IArchiveAsync> OpenAsync(
IReadOnlyList<Stream> streams,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
@@ -87,7 +87,7 @@ public class RarFactory : Factory, IArchiveFactory, IMultiArchiveFactory, IReade
RarArchive.Open(fileInfos, readerOptions);
/// <inheritdoc/>
public Task<IArchiveAsync> OpenAsync(
public ValueTask<IArchiveAsync> OpenAsync(
IReadOnlyList<FileInfo> fileInfos,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
@@ -102,14 +102,14 @@ public class RarFactory : Factory, IArchiveFactory, IMultiArchiveFactory, IReade
RarReader.Open(stream, options);
/// <inheritdoc/>
public async Task<IReader> OpenReaderAsync(
public ValueTask<IReader> OpenReaderAsync(
Stream stream,
ReaderOptions? options,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return await Task.FromResult(OpenReader(stream, options)).ConfigureAwait(false);
return new(OpenReader(stream, options));
}
#endregion

View File

@@ -45,7 +45,7 @@ public class SevenZipFactory : Factory, IArchiveFactory, IMultiArchiveFactory
SevenZipArchive.Open(stream, readerOptions);
/// <inheritdoc/>
public Task<IArchiveAsync> OpenAsync(
public ValueTask<IArchiveAsync> OpenAsync(
Stream stream,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
@@ -56,7 +56,7 @@ public class SevenZipFactory : Factory, IArchiveFactory, IMultiArchiveFactory
SevenZipArchive.Open(fileInfo, readerOptions);
/// <inheritdoc/>
public Task<IArchiveAsync> OpenAsync(
public ValueTask<IArchiveAsync> OpenAsync(
FileInfo fileInfo,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
@@ -71,7 +71,7 @@ public class SevenZipFactory : Factory, IArchiveFactory, IMultiArchiveFactory
SevenZipArchive.Open(streams, readerOptions);
/// <inheritdoc/>
public Task<IArchiveAsync> OpenAsync(
public ValueTask<IArchiveAsync> OpenAsync(
IReadOnlyList<Stream> streams,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
@@ -82,7 +82,7 @@ public class SevenZipFactory : Factory, IArchiveFactory, IMultiArchiveFactory
SevenZipArchive.Open(fileInfos, readerOptions);
/// <inheritdoc/>
public Task<IArchiveAsync> OpenAsync(
public ValueTask<IArchiveAsync> OpenAsync(
IReadOnlyList<FileInfo> fileInfos,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default

View File

@@ -70,7 +70,7 @@ public class TarFactory
TarArchive.Open(stream, readerOptions);
/// <inheritdoc/>
public Task<IArchiveAsync> OpenAsync(
public ValueTask<IArchiveAsync> OpenAsync(
Stream stream,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
@@ -81,7 +81,7 @@ public class TarFactory
TarArchive.Open(fileInfo, readerOptions);
/// <inheritdoc/>
public Task<IArchiveAsync> OpenAsync(
public ValueTask<IArchiveAsync> OpenAsync(
FileInfo fileInfo,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
@@ -96,7 +96,7 @@ public class TarFactory
TarArchive.Open(streams, readerOptions);
/// <inheritdoc/>
public Task<IArchiveAsync> OpenAsync(
public ValueTask<IArchiveAsync> OpenAsync(
IReadOnlyList<Stream> streams,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
@@ -107,7 +107,7 @@ public class TarFactory
TarArchive.Open(fileInfos, readerOptions);
/// <inheritdoc/>
public Task<IArchiveAsync> OpenAsync(
public ValueTask<IArchiveAsync> OpenAsync(
IReadOnlyList<FileInfo> fileInfos,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
@@ -265,14 +265,14 @@ public class TarFactory
TarReader.Open(stream, options);
/// <inheritdoc/>
public async Task<IReader> OpenReaderAsync(
public ValueTask<IReader> OpenReaderAsync(
Stream stream,
ReaderOptions? options,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return await Task.FromResult(OpenReader(stream, options)).ConfigureAwait(false);
return new(OpenReader(stream, options));
}
#endregion
@@ -284,14 +284,14 @@ public class TarFactory
new TarWriter(stream, new TarWriterOptions(writerOptions));
/// <inheritdoc/>
public async Task<IWriter> OpenAsync(
public ValueTask<IWriter> OpenAsync(
Stream stream,
WriterOptions writerOptions,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return await Task.FromResult(Open(stream, writerOptions)).ConfigureAwait(false);
return new(Open(stream, writerOptions));
}
#endregion

View File

@@ -82,7 +82,7 @@ public class ZipFactory
}
/// <inheritdoc/>
public override async Task<bool> IsArchiveAsync(
public override async ValueTask<bool> IsArchiveAsync(
Stream stream,
string? password = null,
int bufferSize = ReaderOptions.DefaultBufferSize,
@@ -137,7 +137,7 @@ public class ZipFactory
ZipArchive.Open(stream, readerOptions);
/// <inheritdoc/>
public Task<IArchiveAsync> OpenAsync(
public ValueTask<IArchiveAsync> OpenAsync(
Stream stream,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
@@ -148,7 +148,7 @@ public class ZipFactory
ZipArchive.Open(fileInfo, readerOptions);
/// <inheritdoc/>
public Task<IArchiveAsync> OpenAsync(
public ValueTask<IArchiveAsync> OpenAsync(
FileInfo fileInfo,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
@@ -163,7 +163,7 @@ public class ZipFactory
ZipArchive.Open(streams, readerOptions);
/// <inheritdoc/>
public Task<IArchiveAsync> OpenAsync(
public ValueTask<IArchiveAsync> OpenAsync(
IReadOnlyList<Stream> streams,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
@@ -174,7 +174,7 @@ public class ZipFactory
ZipArchive.Open(fileInfos, readerOptions);
/// <inheritdoc/>
public Task<IArchiveAsync> OpenAsync(
public ValueTask<IArchiveAsync> OpenAsync(
IReadOnlyList<FileInfo> fileInfos,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
@@ -189,14 +189,14 @@ public class ZipFactory
ZipReader.Open(stream, options);
/// <inheritdoc/>
public async Task<IReader> OpenReaderAsync(
public ValueTask<IReader> OpenReaderAsync(
Stream stream,
ReaderOptions? options,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return await Task.FromResult(OpenReader(stream, options)).ConfigureAwait(false);
return new(OpenReader(stream, options));
}
#endregion
@@ -208,14 +208,14 @@ public class ZipFactory
new ZipWriter(stream, new ZipWriterOptions(writerOptions));
/// <inheritdoc/>
public async Task<IWriter> OpenAsync(
public ValueTask<IWriter> OpenAsync(
Stream stream,
WriterOptions writerOptions,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return await Task.FromResult(Open(stream, writerOptions)).ConfigureAwait(false);
return new(Open(stream, writerOptions));
}
#endregion

View File

@@ -21,7 +21,7 @@ public interface IReaderFactory : Factories.IFactory
/// <param name="options"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<IReader> OpenReaderAsync(
ValueTask<IReader> OpenReaderAsync(
Stream stream,
ReaderOptions? options,
CancellationToken cancellationToken = default

View File

@@ -9,7 +9,7 @@ public interface IWriterFactory : IFactory
{
IWriter Open(Stream stream, WriterOptions writerOptions);
Task<IWriter> OpenAsync(
ValueTask<IWriter> OpenAsync(
Stream stream,
WriterOptions writerOptions,
CancellationToken cancellationToken = default

View File

@@ -23,7 +23,7 @@ public class ExtractAllTests : TestBase
var testArchive = Path.Combine(TEST_ARCHIVES_PATH, archivePath);
var options = new ExtractionOptions() { ExtractFullPath = true, Overwrite = true };
using var archive = ArchiveFactory.Open(testArchive);
await using var archive = await ArchiveFactory.OpenAsync(testArchive);
await archive.WriteToDirectoryAsync(SCRATCH_FILES_PATH, options);
}

View File

@@ -7,6 +7,7 @@ using SharpCompress.Archives;
using SharpCompress.Archives.Zip;
using SharpCompress.Common;
using SharpCompress.Compressors.Deflate;
using SharpCompress.Test.Mocks;
using SharpCompress.Writers;
using SharpCompress.Writers.Zip;
using Xunit;
@@ -118,7 +119,7 @@ public class ZipArchiveAsyncTests : ArchiveTests
}
[Fact]
public async Task Zip_Random_Write_Remove_Async()
public async Task Zip_Random_Write_Remove_Sync()
{
var scratchPath = Path.Combine(SCRATCH_FILES_PATH, "Zip.deflate.mod.zip");
var unmodified = Path.Combine(TEST_ARCHIVES_PATH, "Zip.deflate.noEmptyDirs.zip");
@@ -140,7 +141,7 @@ public class ZipArchiveAsyncTests : ArchiveTests
}
[Fact]
public async Task Zip_Random_Write_Add_Async()
public async Task Zip_Random_Write_Add_Sync()
{
var jpg = Path.Combine(ORIGINAL_FILES_PATH, "jpg", "test.jpg");
var scratchPath = Path.Combine(SCRATCH_FILES_PATH, "Zip.deflate.mod.zip");
@@ -182,9 +183,9 @@ public class ZipArchiveAsyncTests : ArchiveTests
public async Task Zip_Deflate_Entry_Stream_Async()
{
using (Stream stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "Zip.deflate.zip")))
using (var archive = ZipArchive.Open(stream))
await using (var archive = await ZipArchive.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))
{
await entry.WriteToDirectoryAsync(
SCRATCH_FILES_PATH,
@@ -199,7 +200,7 @@ public class ZipArchiveAsyncTests : ArchiveTests
public async Task Zip_Deflate_Archive_WriteToDirectoryAsync()
{
using (Stream stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "Zip.deflate.zip")))
using (var archive = ZipArchive.Open(stream))
await using (var archive = await ZipArchive.OpenAsync(new AsyncOnlyStream(stream)))
{
await archive.WriteToDirectoryAsync(
SCRATCH_FILES_PATH,
@@ -216,7 +217,7 @@ public class ZipArchiveAsyncTests : ArchiveTests
var progress = new Progress<ProgressReport>(report => progressReports.Add(report));
using (Stream stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "Zip.deflate.zip")))
using (var archive = ZipArchive.Open(stream))
await using (var archive = await ZipArchive.OpenAsync(new AsyncOnlyStream(stream)))
{
await archive.WriteToDirectoryAsync(
SCRATCH_FILES_PATH,