using System; using System.Collections.Generic; using System.Runtime.CompilerServices; namespace MoonTools.ECS { internal class IndexableSet where T : unmanaged { private Dictionary indices; private T[] array; public int Count { get; private set; } public Enumerator GetEnumerator() => new Enumerator(this); public IndexableSet(int size = 32) { indices = new Dictionary(size); array = new T[size]; } public T this[int i] { get { return array[i]; } } public bool Contains(T element) { return indices.ContainsKey(element); } public bool Add(T element) { if (!Contains(element)) { indices.Add(element, Count); if (Count >= array.Length) { Array.Resize(ref array, array.Length * 2); } array[Count] = element; Count += 1; return true; } return false; } public bool Remove(T element) { if (!Contains(element)) { return false; } var lastElement = array[Count - 1]; var index = indices[element]; array[index] = lastElement; indices[lastElement] = index; Count -= 1; indices.Remove(element); return true; } public void Clear() { Count = 0; } public struct Enumerator { /// The set being enumerated. private readonly IndexableSet _set; /// The next index to yield. private int _index; /// Initialize the enumerator. /// The set to enumerate. [MethodImpl(MethodImplOptions.AggressiveInlining)] internal Enumerator(IndexableSet set) { _set = set; _index = _set.Count; } /// Advances the enumerator to the next element of the span. [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool MoveNext() { int index = _index - 1; if (index >= 0) { _index = index; return true; } return false; } /// Gets the element at the current position of the enumerator. public T Current { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => _set[_index]; } } } }