#if ENABLE_DUMMY_SPAN using System; using System.Diagnostics; using System.Runtime.CompilerServices; using EditorBrowsableAttribute = System.ComponentModel.EditorBrowsableAttribute; using EditorBrowsableState = System.ComponentModel.EditorBrowsableState; namespace DCFApixels.DragonECS { internal static class ThrowHelper { public static void ThrowIndexOutOfRangeException() => throw new IndexOutOfRangeException(); public static void ThrowArgumentOutOfRangeException() => throw new ArgumentOutOfRangeException(); public static void ThrowInvalidOperationException() => throw new InvalidOperationException(); } [DebuggerDisplay("{ToString(),raw}")] public readonly ref struct ReadOnlySpan { public static ReadOnlySpan Empty => new ReadOnlySpan(null); internal readonly T[] _array; private readonly int _start; private readonly int _length; #region Properties public int Length => _length; public bool IsEmpty => _length == 0; public ref readonly T this[int index] { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { if ((uint)index >= (uint)_length || (uint)index < 0) ThrowHelper.ThrowIndexOutOfRangeException(); return ref _array[index + _start]; } } #endregion #region Constructors public ReadOnlySpan(T[] array) { _array = array ?? Array.Empty(); _start = 0; _length = array.Length; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public ReadOnlySpan(T[] array, int start, int length) { if (array == null) { if (start != 0 || length != 0) ThrowHelper.ThrowArgumentOutOfRangeException(); _array = Array.Empty(); _start = 0; _length = 0; return; } if ((uint)start > (uint)array.Length || (uint)length > (uint)(array.Length - start)) ThrowHelper.ThrowArgumentOutOfRangeException(); _array = array; _start = start; _length = length; } #endregion #region Object [Obsolete("Equals() on ReadOnlySpan will always throw an exception. Use the equality operator instead.")] [EditorBrowsable(EditorBrowsableState.Never)] public override bool Equals(object obj) => throw new NotSupportedException(); [Obsolete("GetHashCode() on ReadOnlySpan will always throw an exception.")] [EditorBrowsable(EditorBrowsableState.Never)] public override int GetHashCode() => throw new NotSupportedException(); public override string ToString() { //if (typeof(T) == typeof(char)) // return new string(new ReadOnlySpan(ref Unsafe.As(ref _reference), _length)); return $"System.ReadOnlySpan<{typeof(T).Name}>[{_length}]"; } #endregion #region operators public static bool operator !=(ReadOnlySpan left, ReadOnlySpan right) => !(left == right); public static implicit operator ReadOnlySpan(T[] array) => new ReadOnlySpan(array); public static implicit operator ReadOnlySpan(ArraySegment segment) => new ReadOnlySpan(segment.Array, segment.Offset, segment.Count); public static bool operator ==(ReadOnlySpan left, ReadOnlySpan right) => left._length == right._length && left._array == right._array; #endregion #region Enumerator public Enumerator GetEnumerator() => new Enumerator(this); public ref struct Enumerator { private readonly ReadOnlySpan _span; private int _index; [MethodImpl(MethodImplOptions.AggressiveInlining)] internal Enumerator(ReadOnlySpan span) { _span = span; _index = span._start - 1; } public ref readonly T Current { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => ref _span[_index]; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool MoveNext() { int index = _index + 1; if (index < _span.Length) { _index = index; return true; } return false; } } #endregion #region Other [EditorBrowsable(EditorBrowsableState.Never)] public ref readonly T GetPinnableReference() { if (_length != 0) ThrowHelper.ThrowInvalidOperationException(); return ref _array[0]; } //[MethodImpl(MethodImplOptions.AggressiveInlining)] //public void CopyTo(Span destination) //{ // if ((uint)_length <= (uint)destination.Length) // { // Buffer.Memmove(ref destination._reference, ref _reference, (uint)_length); // } // else // { // ThrowHelper.ThrowArgumentException_DestinationTooShort(); // } //} //public bool TryCopyTo(Span destination) //{ // bool retVal = false; // if ((uint)_length <= (uint)destination.Length) // { // Buffer.Memmove(ref destination._reference, ref _reference, (uint)_length); // retVal = true; // } // return retVal; //} [MethodImpl(MethodImplOptions.AggressiveInlining)] public ReadOnlySpan Slice(int start) { if ((uint)start > (uint)_length) ThrowHelper.ThrowArgumentOutOfRangeException(); return new ReadOnlySpan(_array, _start + start, _length - start); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public ReadOnlySpan Slice(int start, int length) { if ((uint)start > (uint)_length || (uint)length > (uint)(_length - start)) ThrowHelper.ThrowArgumentOutOfRangeException(); return new ReadOnlySpan(_array, _start + start, length); } public T[] ToArray() { if (_length == 0) return Array.Empty(); var result = new T[_length]; Array.Copy(_array, _start, result, 0, _length); return result; } #endregion } } #endif