using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Text; namespace Wabbajack.Common { public struct MemorySlice : IEnumerable { private T[] _arr; private int _startPos; private int _length; public int Length => _length; public int StartPosition => _startPos; [DebuggerStepThrough] public MemorySlice(T[] arr) { this._arr = arr; this._startPos = 0; this._length = arr.Length; } [DebuggerStepThrough] public MemorySlice(T[] arr, int startPos, int length) { this._arr = arr; this._startPos = startPos; this._length = length; } public Span Span => _arr.AsSpan(start: _startPos, length: _length); public T this[int index] { get => _arr[index + _startPos]; set => _arr[index + _startPos] = value; } [DebuggerStepThrough] public MemorySlice Slice(int start) { var startPos = _startPos + start; if (startPos < 0) { throw new ArgumentOutOfRangeException(); } return new MemorySlice() { _arr = _arr, _startPos = startPos, _length = _length - start }; } [DebuggerStepThrough] public MemorySlice Slice(int start, int length) { var startPos = _startPos + start; if (startPos < 0) { throw new ArgumentOutOfRangeException(); } if (startPos + length > _arr.Length) { throw new ArgumentOutOfRangeException(); } return new MemorySlice() { _arr = _arr, _startPos = startPos, _length = length }; } public IEnumerator GetEnumerator() { for (int i = 0; i < _length; i++) { yield return this._arr[i + _startPos]; } } IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator(); public static implicit operator ReadOnlyMemorySlice(MemorySlice mem) { return new ReadOnlyMemorySlice( mem._arr, mem._startPos, mem._length); } public static implicit operator ReadOnlySpan(MemorySlice mem) { return mem.Span; } public static implicit operator Span(MemorySlice mem) { return mem.Span; } public static implicit operator MemorySlice(T[] mem) { return new MemorySlice(mem); } public static implicit operator MemorySlice?(T[]? mem) { if (mem == null) return null; return new MemorySlice(mem); } } public struct ReadOnlyMemorySlice : IEnumerable { private T[] _arr; private int _startPos; private int _length; public int Length => _length; public int StartPosition => _startPos; [DebuggerStepThrough] public ReadOnlyMemorySlice(T[] arr) { this._arr = arr; this._startPos = 0; this._length = arr.Length; } [DebuggerStepThrough] public ReadOnlyMemorySlice(T[] arr, int startPos, int length) { this._arr = arr; this._startPos = startPos; this._length = length; } public ReadOnlySpan Span => _arr.AsSpan(start: _startPos, length: _length); public T this[int index] => _arr[index + _startPos]; [DebuggerStepThrough] public ReadOnlyMemorySlice Slice(int start) { var startPos = _startPos + start; if (startPos < 0) { throw new ArgumentOutOfRangeException(); } return new ReadOnlyMemorySlice() { _arr = _arr, _startPos = _startPos + start, _length = _length - start }; } [DebuggerStepThrough] public ReadOnlyMemorySlice Slice(int start, int length) { var startPos = _startPos + start; if (startPos < 0) { throw new ArgumentOutOfRangeException(); } if (startPos + length > _arr.Length) { throw new ArgumentOutOfRangeException(); } return new ReadOnlyMemorySlice() { _arr = _arr, _startPos = _startPos + start, _length = length }; } public IEnumerator GetEnumerator() { for (int i = 0; i < _length; i++) { yield return this._arr[i + _startPos]; } } IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator(); public static implicit operator ReadOnlySpan(ReadOnlyMemorySlice mem) { return mem.Span; } public static implicit operator ReadOnlyMemorySlice?(T[]? mem) { if (mem == null) return null; return new ReadOnlyMemorySlice(mem); } public static implicit operator ReadOnlyMemorySlice(T[] mem) { return new ReadOnlyMemorySlice(mem); } } public static class MemorySliceExt { public static bool Equal(ReadOnlyMemorySlice? lhs, ReadOnlyMemorySlice? rhs) where T : IEquatable { if (lhs == null && rhs == null) return true; if (lhs == null || rhs == null) return false; return MemoryExtensions.SequenceEqual(lhs.Value.Span, rhs.Value.Span); } } }