using System; using System.Collections.Generic; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; namespace MoonTools.ECS.Collections { public unsafe class IndexableSet : IDisposable where T : unmanaged { private Dictionary indices; private T* array; private int count; private int capacity; private bool disposed; public int Count => count; public ReverseSpanEnumerator GetEnumerator() => new ReverseSpanEnumerator(new Span(array, count)); public IndexableSet(int capacity = 32) { this.capacity = capacity; count = 0; indices = new Dictionary(capacity); array = (T*) NativeMemory.Alloc((nuint) (capacity * Unsafe.SizeOf())); } public T this[int i] => 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 >= capacity) { capacity *= 2; array = (T*) NativeMemory.Realloc(array, (nuint) (capacity * Unsafe.SizeOf())); } 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() { indices.Clear(); count = 0; } protected virtual void Dispose(bool disposing) { if (!disposed) { NativeMemory.Free(array); array = null; disposed = true; } } ~IndexableSet() { // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method Dispose(disposing: false); } public void Dispose() { // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method Dispose(disposing: true); GC.SuppressFinalize(this); } } }