using System; using System.Buffers; using System.IO; using System.Threading; using System.Threading.Tasks; namespace Nebula.Launcher.Utils; public static class StreamHelper { public static async ValueTask ReadExactAsync(this Stream stream, int amount, CancellationToken? cancel) { var data = new byte[amount]; await ReadExactAsync(stream, data, cancel); return data; } public static async ValueTask ReadExactAsync(this Stream stream, Memory into, CancellationToken? cancel) { while (into.Length > 0) { var read = await stream.ReadAsync(into); // Check EOF. if (read == 0) throw new EndOfStreamException(); into = into[read..]; } } public static async Task CopyAmountToAsync( this Stream stream, Stream to, int amount, int bufferSize, CancellationToken cancel) { var buffer = ArrayPool.Shared.Rent(bufferSize); while (amount > 0) { Memory readInto = buffer; if (amount < readInto.Length) readInto = readInto[..amount]; var read = await stream.ReadAsync(readInto, cancel); if (read == 0) throw new EndOfStreamException(); amount -= read; readInto = readInto[..read]; await to.WriteAsync(readInto, cancel); } } }