using System;
using System.IO;
namespace Robust.Shared.Utility
{
///
/// Extension methods for working with streams.
///
public static class StreamExt
{
///
/// Copies any stream into a byte array.
///
/// The stream to copy.
/// The byte array.
public static byte[] CopyToArray(this Stream stream)
{
using (var memStream = new MemoryStream())
{
stream.CopyTo(memStream);
return memStream.ToArray();
}
}
///
/// but to the Pinned Object Heap.
///
internal static byte[] CopyToPinnedArray(this Stream stream)
{
var ms = new MemoryStream();
stream.CopyTo(ms);
var count = (int)ms.Length;
var array = GC.AllocateUninitializedArray(count, pinned: true);
ms.GetBuffer().AsSpan(0, count).CopyTo(array);
return array;
}
internal static MemoryStream ConsumeToMemoryStream(this Stream stream)
{
var ms = stream.CopyToMemoryStream();
stream.Dispose();
return ms;
}
internal static MemoryStream CopyToMemoryStream(this Stream stream)
{
var ms = new MemoryStream();
stream.CopyTo(ms);
ms.Seek(0, SeekOrigin.Begin);
return ms;
}
///
/// Thrown if not exactly bytes could be read.
///
public static byte[] ReadExact(this Stream stream, int amount)
{
var buffer = new byte[amount];
var read = 0;
while (read < amount)
{
var cRead = stream.Read(buffer, read, amount - read);
if (cRead == 0)
{
throw new EndOfStreamException();
}
read += cRead;
}
return buffer;
}
///
/// Thrown if not exactly bytes could be read.
///
public static void ReadExact(this Stream stream, Span buffer)
{
while (buffer.Length > 0)
{
var cRead = stream.Read(buffer);
if (cRead == 0)
throw new EndOfStreamException();
buffer = buffer[cRead..];
}
}
public static int ReadToEnd(this Stream stream, Span buffer)
{
var totalRead = 0;
while (true)
{
var read = stream.Read(buffer);
totalRead += read;
if (read == 0)
return totalRead;
buffer = buffer[read..];
}
}
public static int ReadToEnd(this Stream stream, byte[] buffer)
{
var totalRead = 0;
while (true)
{
var read = stream.Read(buffer, totalRead, buffer.Length - totalRead);
totalRead += read;
if (read == 0)
return totalRead;
}
}
///
/// Gets the span over the currently filled region of the memory stream, based on its length.
///
public static Span AsSpan(this MemoryStream ms)
{
// Let it be forever immortalized that, while I was writing this function,
// Julian suggested that I should name it "AssSpan" to test if that would slip through review.
var buf = ms.GetBuffer();
return buf.AsSpan(0, (int) ms.Length);
}
///
/// Gets the memory over the currently filled region of the memory stream, based on its length.
///
public static Memory AsMemory(this MemoryStream ms)
{
var buf = ms.GetBuffer();
return buf.AsMemory(0, (int) ms.Length);
}
}
}