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); } } }