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

107 lines
2.7 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;
2026-02-04 16:07:06 +00:00
namespace SharpCompress.IO;
2026-02-04 09:25:48 +00:00
public sealed class AsyncBinaryReader : IDisposable
2026-02-04 16:07:06 +00:00
#if NET8_0_OR_GREATER
2026-02-04 16:14:48 +00:00
, IAsyncDisposable
2026-02-04 16:07:06 +00:00
#endif
2025-11-26 08:09:20 +00:00
{
2026-02-04 09:25:48 +00:00
private readonly Stream _stream;
private readonly Stream _originalStream;
private readonly bool _leaveOpen;
private readonly byte[] _buffer = new byte[8];
private bool _disposed;
2025-11-26 08:09:20 +00:00
2026-02-04 16:07:06 +00:00
public AsyncBinaryReader(Stream stream, bool leaveOpen = false)
2026-02-04 09:25:48 +00:00
{
if (!stream.CanRead)
{
2026-02-04 09:25:48 +00:00
throw new ArgumentException("Stream must be readable.");
}
2026-01-20 12:34:49 +00:00
2026-02-04 09:25:48 +00:00
_originalStream = stream ?? throw new ArgumentNullException(nameof(stream));
_leaveOpen = leaveOpen;
_stream = stream;
}
2026-02-04 09:25:48 +00:00
public Stream BaseStream => _stream;
2025-11-26 08:09:20 +00:00
2026-02-04 09:25:48 +00:00
public async ValueTask<byte> ReadByteAsync(CancellationToken ct = default)
{
await _stream.ReadExactAsync(_buffer, 0, 1, ct).ConfigureAwait(false);
return _buffer[0];
}
2025-11-26 08:09:20 +00:00
2026-02-04 09:25:48 +00:00
public async ValueTask<ushort> ReadUInt16Async(CancellationToken ct = default)
{
await _stream.ReadExactAsync(_buffer, 0, 2, ct).ConfigureAwait(false);
return BinaryPrimitives.ReadUInt16LittleEndian(_buffer);
}
2025-11-26 08:09:20 +00:00
2026-02-04 09:25:48 +00:00
public async ValueTask<uint> ReadUInt32Async(CancellationToken ct = default)
{
await _stream.ReadExactAsync(_buffer, 0, 4, ct).ConfigureAwait(false);
return BinaryPrimitives.ReadUInt32LittleEndian(_buffer);
}
2026-02-04 09:25:48 +00:00
public async ValueTask<ulong> ReadUInt64Async(CancellationToken ct = default)
{
await _stream.ReadExactAsync(_buffer, 0, 8, ct).ConfigureAwait(false);
return BinaryPrimitives.ReadUInt64LittleEndian(_buffer);
}
public async ValueTask ReadBytesAsync(
byte[] bytes,
int offset,
int count,
CancellationToken ct = default
)
{
await _stream.ReadExactAsync(bytes, offset, count, ct).ConfigureAwait(false);
}
public async ValueTask SkipAsync(int count, CancellationToken ct = default)
{
await _stream.SkipAsync(count, ct).ConfigureAwait(false);
}
2025-11-26 08:09:20 +00:00
2026-02-04 09:25:48 +00:00
public void Dispose()
{
if (_disposed)
2025-11-26 08:09:20 +00:00
{
2026-02-04 09:25:48 +00:00
return;
2026-01-14 15:33:08 +00:00
}
2026-02-04 09:25:48 +00:00
_disposed = true;
// Dispose the original stream if we own it
if (!_leaveOpen)
2026-01-14 15:33:08 +00:00
{
2026-02-04 09:25:48 +00:00
_originalStream.Dispose();
2025-11-26 08:09:20 +00:00
}
2026-02-04 09:25:48 +00:00
}
2025-11-26 08:09:20 +00:00
2026-02-04 09:25:48 +00:00
#if NET8_0_OR_GREATER
public async ValueTask DisposeAsync()
{
if (_disposed)
2025-11-26 08:09:20 +00:00
{
2026-02-04 09:25:48 +00:00
return;
2025-11-26 08:09:20 +00:00
}
2026-02-04 09:25:48 +00:00
_disposed = true;
// Dispose the original stream if we own it
if (!_leaveOpen)
2025-11-26 08:09:20 +00:00
{
2026-02-04 09:25:48 +00:00
await _originalStream.DisposeAsync().ConfigureAwait(false);
2025-11-26 08:09:20 +00:00
}
}
2026-02-04 09:25:48 +00:00
#endif
2025-11-26 08:09:20 +00:00
}