namespace Just.Core.Extensions;
///
/// Provides extension methods for to fully populate buffers.
///
public static class SystemIOStreamExtensions
{
///
/// Reads data from the stream until the specified section of the buffer is filled.
///
/// The stream to read from
/// The buffer to populate
/// The starting offset in the buffer
/// The number of bytes to read
/// Thrown when is null
/// Thrown when or is invalid
/// Thrown if the stream ends before filling the buffer
/// Thrown for I/O errors during reading
public static void Populate(this Stream stream, byte[] buffer, int offset, int length)
=> stream.Populate(buffer.AsSpan(offset, length));
///
/// Reads data from the stream until the entire buffer is filled.
///
/// The stream to read from
/// The buffer to populate
/// Thrown when is null
/// Thrown if the stream ends before filling the buffer
/// Thrown for I/O errors during reading
public static void Populate(this Stream stream, byte[] buffer)
=> stream.Populate(buffer.AsSpan());
///
/// Reads data from the stream until the specified span is filled.
///
/// The stream to read from
/// The span to populate
/// Thrown when is null
/// Thrown if the stream ends before filling the buffer
/// Thrown for I/O errors during reading
public static void Populate(this Stream stream, Span buffer)
{
ArgumentNullException.ThrowIfNull(stream);
while (!buffer.IsEmpty)
{
var bytesRead = stream.Read(buffer);
if (bytesRead == 0)
{
throw new EndOfStreamException();
}
buffer = buffer[bytesRead..];
}
}
///
/// Asynchronously reads data from the stream until the entire buffer is filled.
///
/// The stream to read from
/// The buffer to populate
/// Cancellation token
/// A ValueTask representing the asynchronous operation
/// Thrown when is null
/// Thrown if the stream ends before filling the buffer
/// Thrown if canceled via cancellation token
/// Thrown for I/O errors during reading
public static ValueTask PopulateAsync(this Stream stream, byte[] buffer, CancellationToken cancellationToken = default)
=> stream.PopulateAsync(buffer.AsMemory(), cancellationToken);
///
/// Asynchronously reads data from the stream until the specified section of the buffer is filled.
///
/// The stream to read from
/// The buffer to populate
/// The starting offset in the buffer
/// The number of bytes to read
/// Cancellation token
/// A ValueTask representing the asynchronous operation
/// Thrown when is null
/// Thrown when or is invalid
/// Thrown if the stream ends before filling the buffer
/// Thrown if canceled via cancellation token
/// Thrown for I/O errors during reading
public static ValueTask PopulateAsync(this Stream stream, byte[] buffer, int offset, int length, CancellationToken cancellationToken = default)
=> stream.PopulateAsync(buffer.AsMemory(offset, length), cancellationToken);
///
/// Asynchronously reads data from the stream until the specified memory region is filled.
///
/// The stream to read from
/// The memory region to populate
/// Cancellation token
/// A ValueTask representing the asynchronous operation
/// Thrown when is null
/// Thrown if the stream ends before filling the buffer
/// Thrown if canceled via cancellation token
/// Thrown for I/O errors during reading
public static async ValueTask PopulateAsync(this Stream stream, Memory buffer, CancellationToken cancellationToken = default)
{
ArgumentNullException.ThrowIfNull(stream);
while (!buffer.IsEmpty)
{
cancellationToken.ThrowIfCancellationRequested();
var bytesRead = await stream.ReadAsync(buffer, cancellationToken).ConfigureAwait(false);
if (bytesRead == 0)
{
throw new EndOfStreamException();
}
buffer = buffer[bytesRead..];
}
}
}