Files
sharpcompress/src/SharpCompress/Common/AsyncBinaryReader.cs

104 lines
3.1 KiB
C#
Raw Normal View History

2025-11-26 08:09:20 +00:00
using System;
using System.Buffers.Binary;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
namespace SharpCompress.Common
{
public sealed class AsyncBinaryReader : IDisposable
2025-11-26 08:09:20 +00:00
{
private readonly Stream _stream;
private readonly Stream _originalStream;
private readonly bool _leaveOpen;
2025-11-26 08:09:20 +00:00
private readonly byte[] _buffer = new byte[8];
private bool _disposed;
public AsyncBinaryReader(Stream stream, bool leaveOpen = false, int bufferSize = 4096)
{
_originalStream = stream ?? throw new ArgumentNullException(nameof(stream));
_leaveOpen = leaveOpen;
// Use the stream directly without wrapping in BufferedStream
// BufferedStream uses synchronous Read internally which doesn't work with async-only streams
// SharpCompress uses SharpCompressStream for buffering which supports true async reads
_stream = stream;
}
2025-11-26 08:09:20 +00:00
public Stream BaseStream => _stream;
public async ValueTask<byte> ReadByteAsync(CancellationToken ct = default)
{
await _stream.ReadExactAsync(_buffer, 0, 1, ct).ConfigureAwait(false);
2025-11-26 08:09:20 +00:00
return _buffer[0];
}
public async ValueTask<ushort> ReadUInt16Async(CancellationToken ct = default)
{
await _stream.ReadExactAsync(_buffer, 0, 2, ct).ConfigureAwait(false);
2025-11-26 08:09:20 +00:00
return BinaryPrimitives.ReadUInt16LittleEndian(_buffer);
}
public async ValueTask<uint> ReadUInt32Async(CancellationToken ct = default)
{
await _stream.ReadExactAsync(_buffer, 0, 4, ct).ConfigureAwait(false);
2025-11-26 08:09:20 +00:00
return BinaryPrimitives.ReadUInt32LittleEndian(_buffer);
}
2025-11-26 08:09:20 +00:00
public async ValueTask<ulong> ReadUInt64Async(CancellationToken ct = default)
{
await _stream.ReadExactAsync(_buffer, 0, 8, ct).ConfigureAwait(false);
2025-11-26 08:09:20 +00:00
return BinaryPrimitives.ReadUInt64LittleEndian(_buffer);
}
2026-01-15 15:20:52 +00:00
public async ValueTask ReadBytesAsync(
byte[] bytes,
int offset,
int count,
CancellationToken ct = default
)
2025-11-26 08:09:20 +00:00
{
2026-01-14 15:33:08 +00:00
await _stream.ReadExactAsync(bytes, offset, count, ct).ConfigureAwait(false);
}
public async ValueTask SkipAsync(int count, CancellationToken ct = default)
{
2026-01-15 15:20:52 +00:00
await _stream.SkipAsync(count, ct).ConfigureAwait(false);
2025-11-26 08:09:20 +00:00
}
public void Dispose()
{
if (_disposed)
2025-11-26 08:09:20 +00:00
{
return;
}
_disposed = true;
// Dispose the original stream if we own it
if (!_leaveOpen)
{
_originalStream.Dispose();
}
2025-11-26 08:09:20 +00:00
}
#if NET6_0_OR_GREATER
public async ValueTask DisposeAsync()
2025-11-26 08:09:20 +00:00
{
if (_disposed)
2025-11-26 08:09:20 +00:00
{
return;
2025-11-26 08:09:20 +00:00
}
_disposed = true;
// Dispose the original stream if we own it
if (!_leaveOpen)
{
await _originalStream.DisposeAsync().ConfigureAwait(false);
}
2025-11-26 08:09:20 +00:00
}
#endif
}
}