using System; using System.Buffers.Binary; using System.Runtime.CompilerServices; namespace Impostor.Api { /// /// Priovides a StreamReader-like api throught extensions /// public static class SpanReaderExtensions { [MethodImpl(MethodImplOptions.AggressiveInlining)] public static byte ReadByte(this ref ReadOnlySpan input) { var original = Advance(ref input); return original[0]; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int ReadInt32(this ref ReadOnlySpan input) { var original = Advance(ref input); return BinaryPrimitives.ReadInt32LittleEndian(original); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static uint ReadUInt32(this ref ReadOnlySpan input) { var original = Advance(ref input); return BinaryPrimitives.ReadUInt32LittleEndian(original); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static float ReadSingle(this ref ReadOnlySpan input) { var original = Advance(ref input); // BitConverter.Int32BitsToSingle // Doesn't exist in net 2.0 for some reason return Int32BitsToSingle(BinaryPrimitives.ReadInt32LittleEndian(original)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool ReadBoolean(this ref ReadOnlySpan input) { return input.ReadByte() != 0; } [MethodImpl(MethodImplOptions.AggressiveInlining)] private static unsafe float Int32BitsToSingle(int value) { return *((float*)&value); } /// /// Advances the position of by the size of . /// /// Type that will be read. /// input "stream"/span. /// The original input [MethodImpl(MethodImplOptions.AggressiveInlining)] private static unsafe ReadOnlySpan Advance(ref ReadOnlySpan input) where T : unmanaged { var original = input; input = input.Slice(sizeof(T)); return original; } } }