using System; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; namespace Ryujinx.Common.Memory { public ref struct SpanReader { private ReadOnlySpan _input; public readonly int Length => _input.Length; public SpanReader(ReadOnlySpan input) { _input = input; } public T Read() where T : unmanaged { T value = MemoryMarshal.Cast(_input)[0]; _input = _input[Unsafe.SizeOf()..]; return value; } public bool TryRead(out T value) where T : unmanaged { int valueSize = Unsafe.SizeOf(); if (valueSize > _input.Length) { value = default; return false; } value = MemoryMarshal.Cast(_input)[0]; _input = _input[valueSize..]; return true; } public ReadOnlySpan GetSpan(int size) { ReadOnlySpan data = _input[..size]; _input = _input[size..]; return data; } public ReadOnlySpan GetSpanSafe(int size) { return GetSpan((int)Math.Min((uint)_input.Length, (uint)size)); } public readonly T ReadAt(int offset) where T : unmanaged { return MemoryMarshal.Cast(_input[offset..])[0]; } public readonly ReadOnlySpan GetSpanAt(int offset, int size) { return _input.Slice(offset, size); } public void Skip(int size) { _input = _input[size..]; } } }