mirror of
https://github.com/adamhathcock/sharpcompress.git
synced 2026-09-23 07:25:11 +00:00
Fully implement FInishAsync
This commit is contained in:
@@ -49,6 +49,8 @@ public sealed partial class BZip2Stream : Stream, IFinishable
|
||||
return bZip2Stream;
|
||||
}
|
||||
|
||||
public ValueTask FinishAsync() => (stream as CBZip2OutputStream)?.FinishAsync() ?? default;
|
||||
|
||||
public void Finish() => (stream as CBZip2OutputStream)?.Finish();
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
|
||||
@@ -2088,7 +2088,7 @@ internal sealed class CBZip2OutputStream : Stream
|
||||
/// Asynchronously finalizes the BZip2 compressed stream, flushing all pending data.
|
||||
/// Writes the remaining compressed data to the underlying stream using async I/O.
|
||||
/// </summary>
|
||||
public async Task FinishAsync(CancellationToken cancellationToken = default)
|
||||
public async ValueTask FinishAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
if (finished)
|
||||
{
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Buffers.Binary;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
@@ -9,6 +10,82 @@ namespace SharpCompress.Compressors.LZMA;
|
||||
|
||||
public sealed partial class LZipStream
|
||||
{
|
||||
public static ValueTask<LZipStream> CreateAsync(
|
||||
Stream stream,
|
||||
CompressionMode mode,
|
||||
bool leaveOpen = false,
|
||||
CancellationToken cancellationToken = default
|
||||
)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
if (mode != CompressionMode.Compress)
|
||||
{
|
||||
return new ValueTask<LZipStream>(new LZipStream(stream, mode, leaveOpen));
|
||||
}
|
||||
|
||||
// The LZMA encoder used for LZip currently finalizes synchronously, so the async
|
||||
// creation path compresses to memory and writes the completed member asynchronously.
|
||||
var compressedBuffer = new MemoryStream();
|
||||
return new ValueTask<LZipStream>(
|
||||
new LZipStream(compressedBuffer, mode, leaveOpen, stream, compressedBuffer)
|
||||
);
|
||||
}
|
||||
|
||||
public async ValueTask FinishAsync()
|
||||
{
|
||||
if (_finished)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (Mode == CompressionMode.Compress)
|
||||
{
|
||||
var crc32Stream = (Crc32Stream)_stream;
|
||||
FinishWrappedStream(crc32Stream);
|
||||
var compressedCount = _countingWritableSubStream.NotNull().BytesWritten;
|
||||
|
||||
var intBuf = new byte[8];
|
||||
BinaryPrimitives.WriteUInt32LittleEndian(intBuf, crc32Stream.Crc);
|
||||
await _countingWritableSubStream
|
||||
.NotNull()
|
||||
.WriteAsync(intBuf, 0, 4, CancellationToken.None)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
BinaryPrimitives.WriteInt64LittleEndian(intBuf, _writeCount);
|
||||
await _countingWritableSubStream
|
||||
.NotNull()
|
||||
.WriteAsync(intBuf, 0, intBuf.Length, CancellationToken.None)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
// Total member size includes the 6-byte header and 20-byte trailer.
|
||||
BinaryPrimitives.WriteUInt64LittleEndian(
|
||||
intBuf,
|
||||
(ulong)compressedCount + (ulong)(6 + 20)
|
||||
);
|
||||
await _countingWritableSubStream
|
||||
.NotNull()
|
||||
.WriteAsync(intBuf, 0, intBuf.Length, CancellationToken.None)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
if (_asyncCompressedBuffer is not null && _asyncFinalDestination is not null)
|
||||
{
|
||||
_asyncCompressedBuffer.Position = 0;
|
||||
await _asyncCompressedBuffer
|
||||
.CopyToAsync(_asyncFinalDestination, 81920, CancellationToken.None)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
_finished = true;
|
||||
}
|
||||
|
||||
private static void FinishWrappedStream(Crc32Stream crc32Stream)
|
||||
{
|
||||
crc32Stream.WrappedStream.Dispose();
|
||||
crc32Stream.Dispose();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Asynchronously determines if the given stream is positioned at the start of a v1 LZip
|
||||
/// file, as indicated by the ASCII characters "LZIP" and a version byte
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using SharpCompress.Common;
|
||||
using SharpCompress.Compressors;
|
||||
using SharpCompress.Compressors.LZMA;
|
||||
@@ -19,6 +21,19 @@ public sealed class LZipCompressionProvider : CompressionProviderBase
|
||||
return new LZipStream(destination, CompressionMode.Compress);
|
||||
}
|
||||
|
||||
public override async ValueTask<Stream> CreateCompressStreamAsync(
|
||||
Stream destination,
|
||||
int compressionLevel,
|
||||
CancellationToken cancellationToken = default
|
||||
) =>
|
||||
await LZipStream
|
||||
.CreateAsync(
|
||||
destination,
|
||||
CompressionMode.Compress,
|
||||
cancellationToken: cancellationToken
|
||||
)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
public override Stream CreateDecompressStream(Stream source)
|
||||
{
|
||||
return new LZipStream(source, CompressionMode.Decompress);
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace SharpCompress.Providers;
|
||||
|
||||
/// <summary>
|
||||
@@ -16,4 +18,6 @@ public interface IFinishable
|
||||
/// and writing format-specific trailer/footer bytes.
|
||||
/// </summary>
|
||||
void Finish();
|
||||
|
||||
ValueTask FinishAsync();
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ public partial class TarWriter
|
||||
}
|
||||
if (OutputStream is IFinishable finishable)
|
||||
{
|
||||
finishable.Finish();
|
||||
await finishable.FinishAsync().ConfigureAwait(false);
|
||||
}
|
||||
OutputStream?.Dispose();
|
||||
// base.DisposeAsync() is a no-op since _isDisposed is already set
|
||||
|
||||
@@ -19,6 +19,9 @@ public class AsyncOnlyStream(Stream stream) : Stream
|
||||
set => _stream.Position = value;
|
||||
}
|
||||
|
||||
public override Task FlushAsync(CancellationToken cancellationToken) =>
|
||||
_stream.FlushAsync(cancellationToken);
|
||||
|
||||
public override void Flush() =>
|
||||
throw new NotSupportedException("Synchronous Flush is not supported");
|
||||
|
||||
|
||||
@@ -65,7 +65,7 @@ public class TarWriterAsyncTests : WriterTests
|
||||
{
|
||||
using var stream = new MemoryStream();
|
||||
using Stream content = File.OpenRead(Path.Combine(ORIGINAL_FILES_PATH, "jpg", "test.jpg"));
|
||||
using (
|
||||
await using (
|
||||
var writer = new TarWriter(
|
||||
new AsyncOnlyStream(stream),
|
||||
new TarWriterOptions(CompressionType.None, finalizeArchive)
|
||||
|
||||
Reference in New Issue
Block a user