This commit is contained in:
Adam Hathcock
2026-01-13 14:29:10 +00:00
parent fc85f1fa2c
commit a1a86cdde8
8 changed files with 65 additions and 38 deletions

View File

@@ -119,7 +119,7 @@ public partial class GZipArchive : AbstractWritableArchive<GZipArchiveEntry, GZi
var stream = volumes.Single().Stream;
yield return new GZipArchiveEntry(
this,
GZipFilePart.Create(stream, ReaderOptions.ArchiveEncoding)
GZipFilePart.Create(stream, ReaderOptions.ArchiveEncoding)
);
}

View File

@@ -37,7 +37,11 @@ internal sealed class GZipFilePart : FilePart
return part;
}
internal static async ValueTask<GZipFilePart> CreateAsync(Stream stream, IArchiveEncoding archiveEncoding, CancellationToken cancellationToken = default)
internal static async ValueTask<GZipFilePart> CreateAsync(
Stream stream,
IArchiveEncoding archiveEncoding,
CancellationToken cancellationToken = default
)
{
var part = new GZipFilePart(stream, archiveEncoding);
@@ -59,10 +63,8 @@ internal sealed class GZipFilePart : FilePart
return part;
}
private GZipFilePart(Stream stream, IArchiveEncoding archiveEncoding)
: base(archiveEncoding) =>
_stream = stream;
: base(archiveEncoding) => _stream = stream;
internal long EntryStartPosition { get; private set; }
@@ -149,7 +151,9 @@ internal sealed class GZipFilePart : FilePart
}
}
private async ValueTask ReadAndValidateGzipHeaderAsync(CancellationToken cancellationToken = default)
private async ValueTask ReadAndValidateGzipHeaderAsync(
CancellationToken cancellationToken = default
)
{
// read the header on the first read
var header = new byte[10];
@@ -228,7 +232,10 @@ internal sealed class GZipFilePart : FilePart
return ArchiveEncoding.Decode(buffer);
}
private async ValueTask<string> ReadZeroTerminatedStringAsync(Stream stream, CancellationToken cancellationToken = default)
private async ValueTask<string> ReadZeroTerminatedStringAsync(
Stream stream,
CancellationToken cancellationToken = default
)
{
var buf1 = new byte[1];
var list = new List<byte>();
@@ -253,5 +260,4 @@ internal sealed class GZipFilePart : FilePart
var buffer = list.ToArray();
return ArchiveEncoding.Decode(buffer);
}
}

View File

@@ -33,31 +33,35 @@ public static class AsyncEnumerableExtensions
{
public static async IAsyncEnumerable<TResult> Select<T, TResult>(
this IAsyncEnumerable<T> source,
Func<T, TResult> selector)
Func<T, TResult> selector
)
{
await foreach (var element in source)
{
yield return selector(element);
}
await foreach (var element in source)
{
yield return selector(element);
}
}
public static async ValueTask<int> CountAsync<T>(
this IAsyncEnumerable<T> source,
CancellationToken cancellationToken = default)
CancellationToken cancellationToken = default
)
{
await using var e = source.GetAsyncEnumerator(cancellationToken);
var count = 0;
while (await e.MoveNextAsync())
{
checked { count++; }
checked
{
count++;
}
}
return count;
}
public static async IAsyncEnumerable<T> TakeAsync<T>(
this IAsyncEnumerable<T> source,
int count)
public static async IAsyncEnumerable<T> TakeAsync<T>(this IAsyncEnumerable<T> source, int count)
{
await foreach (var element in source)
{

View File

@@ -652,7 +652,9 @@ public class ArchiveTests : ReaderTests
// Open with a pre-wrapped stream
using (var fileStream = File.OpenRead(testArchive))
using (var wrappedStream = SharpCompressStream.Create(fileStream, bufferSize: 32768))
await using (var archive = await ArchiveFactory.OpenAsync(new AsyncOnlyStream(wrappedStream)))
await using (
var archive = await ArchiveFactory.OpenAsync(new AsyncOnlyStream(wrappedStream))
)
{
Assert.Equal(ArchiveType.Zip, archive.Type);
Assert.Equal(3, await archive.EntriesAsync.CountAsync());

View File

@@ -74,9 +74,13 @@ public class AsyncTests : TestBase
public async ValueTask Archive_Entry_Async_Open_Stream()
{
var testArchive = Path.Combine(TEST_ARCHIVES_PATH, "Tar.tar.gz");
await using var archive = await ArchiveFactory.OpenAsync(new AsyncOnlyStream(File.OpenRead(testArchive)));
await using var archive = await ArchiveFactory.OpenAsync(
new AsyncOnlyStream(File.OpenRead(testArchive))
);
await foreach (var entry in archive.EntriesAsync.WhereAsync(e => !e.IsDirectory).TakeAsync(1))
await foreach (
var entry in archive.EntriesAsync.WhereAsync(e => !e.IsDirectory).TakeAsync(1)
)
{
#if NETFRAMEWORK
using var entryStream = await entry.OpenEntryStreamAsync();
@@ -104,7 +108,11 @@ public class AsyncTests : TestBase
await using (var stream = File.Create(outputPath))
#endif
using (
var writer = WriterFactory.OpenAsync(new AsyncOnlyStream(stream), ArchiveType.Zip, CompressionType.Deflate)
var writer = WriterFactory.OpenAsync(
new AsyncOnlyStream(stream),
ArchiveType.Zip,
CompressionType.Deflate
)
)
{
var testFile = Path.Combine(TEST_ARCHIVES_PATH, "Tar.tar.gz");

View File

@@ -156,7 +156,7 @@ public class GZipArchiveAsyncTests : ArchiveTests
}
[Fact]
public async Task TestGzArchiveTypeGzip_Async()
public async Task TestGzArchiveTypeGzip_Async()
{
using var stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "Tar.tar.gz"));
await using var archive = GZipArchive.OpenAsync(new AsyncOnlyStream(stream));

View File

@@ -27,22 +27,21 @@ public class AsyncOnlyStream : Stream
public override void Flush() => _stream.Flush();
public override int Read(byte[] buffer, int offset, int count) => throw new NotSupportedException("Synchronous Read is not supported");
public override int Read(byte[] buffer, int offset, int count) =>
throw new NotSupportedException("Synchronous Read is not supported");
public override Task<int> ReadAsync(
byte[] buffer,
int offset,
int count,
CancellationToken cancellationToken
) =>
_stream.ReadAsync(buffer, offset, count, cancellationToken);
) => _stream.ReadAsync(buffer, offset, count, cancellationToken);
#if NET8_0_OR_GREATER
public override ValueTask<int> ReadAsync(
Memory<byte> buffer,
CancellationToken cancellationToken = default
) =>
_stream.ReadAsync(buffer, cancellationToken);
) => _stream.ReadAsync(buffer, cancellationToken);
#endif
public override long Seek(long offset, SeekOrigin origin) => _stream.Seek(offset, origin);
@@ -54,15 +53,13 @@ public class AsyncOnlyStream : Stream
int offset,
int count,
CancellationToken cancellationToken
) =>
throw new NotSupportedException("Synchronous Read is not supported");
) => throw new NotSupportedException("Synchronous Read is not supported");
#if NET8_0_OR_GREATER
public override ValueTask WriteAsync(
ReadOnlyMemory<byte> buffer,
CancellationToken cancellationToken = default
) =>
_stream.WriteAsync(buffer, cancellationToken);
) => _stream.WriteAsync(buffer, cancellationToken);
#endif
public override void Write(byte[] buffer, int offset, int count) =>

View File

@@ -46,10 +46,15 @@ public class TarArchiveAsyncTests : ArchiveTests
// Step 2: check if the written tar file can be read correctly
var unmodified = Path.Combine(SCRATCH2_FILES_PATH, archive);
await using (var archive2 = TarArchive.OpenAsync(new AsyncOnlyStream(File.OpenRead(unmodified))))
await using (
var archive2 = TarArchive.OpenAsync(new AsyncOnlyStream(File.OpenRead(unmodified)))
)
{
Assert.Equal(1, await archive2.EntriesAsync.CountAsync());
Assert.Contains(filename, await archive2.EntriesAsync.Select(entry => entry.Key).ToListAsync());
Assert.Contains(
filename,
await archive2.EntriesAsync.Select(entry => entry.Key).ToListAsync()
);
await foreach (var entry in archive2.EntriesAsync)
{
@@ -90,10 +95,15 @@ public class TarArchiveAsyncTests : ArchiveTests
// Step 2: check if the written tar file can be read correctly
var unmodified = Path.Combine(SCRATCH2_FILES_PATH, archive);
await using (var archive2 = TarArchive.OpenAsync(new AsyncOnlyStream(File.OpenRead(unmodified))))
await using (
var archive2 = TarArchive.OpenAsync(new AsyncOnlyStream(File.OpenRead(unmodified)))
)
{
Assert.Equal(1, await archive2.EntriesAsync.CountAsync());
Assert.Contains(longFilename, await archive2.EntriesAsync.Select(entry => entry.Key).ToListAsync());
Assert.Contains(
longFilename,
await archive2.EntriesAsync.Select(entry => entry.Key).ToListAsync()
);
await foreach (var entry in archive2.EntriesAsync)
{
@@ -206,9 +216,9 @@ public class TarArchiveAsyncTests : ArchiveTests
var numberOfEntries = 0;
await using (var archiveFactory = TarArchive.OpenAsync(new AsyncOnlyStream(memoryStream)))
await using (var archiveFactory = TarArchive.OpenAsync(new AsyncOnlyStream(memoryStream)))
{
await foreach (var entry in archiveFactory.EntriesAsync)
await foreach (var entry in archiveFactory.EntriesAsync)
{
++numberOfEntries;