SpanReader.cs
1 using System; 2 using System.Runtime.CompilerServices; 3 using System.Runtime.InteropServices; 4 5 namespace Ryujinx.Common.Memory 6 { 7 public ref struct SpanReader 8 { 9 private ReadOnlySpan<byte> _input; 10 11 public readonly int Length => _input.Length; 12 13 public SpanReader(ReadOnlySpan<byte> input) 14 { 15 _input = input; 16 } 17 18 public T Read<T>() where T : unmanaged 19 { 20 T value = MemoryMarshal.Cast<byte, T>(_input)[0]; 21 22 _input = _input[Unsafe.SizeOf<T>()..]; 23 24 return value; 25 } 26 27 public bool TryRead<T>(out T value) where T : unmanaged 28 { 29 int valueSize = Unsafe.SizeOf<T>(); 30 31 if (valueSize > _input.Length) 32 { 33 value = default; 34 35 return false; 36 } 37 38 value = MemoryMarshal.Cast<byte, T>(_input)[0]; 39 40 _input = _input[valueSize..]; 41 42 return true; 43 } 44 45 public ReadOnlySpan<byte> GetSpan(int size) 46 { 47 ReadOnlySpan<byte> data = _input[..size]; 48 49 _input = _input[size..]; 50 51 return data; 52 } 53 54 public ReadOnlySpan<byte> GetSpanSafe(int size) 55 { 56 return GetSpan((int)Math.Min((uint)_input.Length, (uint)size)); 57 } 58 59 public readonly T ReadAt<T>(int offset) where T : unmanaged 60 { 61 return MemoryMarshal.Cast<byte, T>(_input[offset..])[0]; 62 } 63 64 public readonly ReadOnlySpan<byte> GetSpanAt(int offset, int size) 65 { 66 return _input.Slice(offset, size); 67 } 68 69 public void Skip(int size) 70 { 71 _input = _input[size..]; 72 } 73 } 74 }