using Misaki.HighPerformance.LowLevel.Buffer; using Misaki.HighPerformance.LowLevel.Collections.Contracts; using Misaki.HighPerformance.LowLevel.Contracts; using Misaki.HighPerformance.LowLevel.Utilities; using System.Collections; using System.Runtime.CompilerServices; namespace Misaki.HighPerformance.LowLevel.Collections; /// /// A collection that provides fast, unsafe operations for managing a set of unmanaged types. It supports adding, /// removing, and checking for values. /// /// Represents an unmanaged type that can be compared for equality. public unsafe struct UnsafeHashSet : IUnsafeCollection, IEnumerable where T : unmanaged, IEquatable { public struct Enumerator : IEnumerator { internal HashMapHelper.Enumerator _enumerator; public Enumerator(HashMapHelper* hashMap) { _enumerator = new HashMapHelper.Enumerator(hashMap); } public T Current { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => _enumerator.buffer->_keys[_enumerator.index]; } object IEnumerator.Current => Current; [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool MoveNext() => _enumerator.MoveNext(); public void Reset() => _enumerator.Reset(); public readonly void Dispose() { } } private HashMapHelper _hashMap; public readonly int Count => _hashMap.Count; public readonly int Capacity => _hashMap.Capacity; public readonly bool IsCreated => _hashMap.IsCreated; public IEnumerator GetEnumerator() => new Enumerator((HashMapHelper*)UnsafeUtilities.AddressOf(ref _hashMap)); IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); /// /// Invalid constructor. Use or instead."/> /// public UnsafeHashSet() : this(0, Allocator.Invalid) { } public UnsafeHashSet(int capacity, ref AllocationHandle handle, AllocationOption allocationOption = AllocationOption.None) { _hashMap = new HashMapHelper(capacity, 0, HashMapHelper.MINIMAL_CAPACITY, ref handle, allocationOption); } public UnsafeHashSet(int capacity, Allocator allocator, AllocationOption allocationOption = AllocationOption.None) : this(capacity, ref AllocationManager.GetAllocationHandle(allocator), allocationOption) { } /// /// Adds a new value (unless it is already present). /// /// The value to add. /// True if the value was not already present. public bool Add(T item) { return -1 != _hashMap.TryAdd(item); } /// /// Removes a particular value. /// /// The value to remove. /// True if the value was present. public bool Remove(T item) { return -1 != _hashMap.TryRemove(item); } /// /// Returns true if a particular value is present. /// /// The value to check for. /// True if the value was present. public bool Contains(T item) { return -1 != _hashMap.Find(item); } /// /// Sets the capacity to match what it would be if it had been originally initialized with all its entries. /// public void TrimExcess() => _hashMap.TrimExcess(); /// /// Returns an array with a copy of this set's values (in no particular order). /// /// The allocator to use. /// An array with a copy of the set's values. public UnsafeArray ToNativeArray(Allocator allocator) { return _hashMap.GetKeyArray(allocator); } public void Resize(int newSize) { _hashMap.Resize(newSize); } public void Clear() { _hashMap.Clear(); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public readonly void* GetUnsafePtr() { return _hashMap.Buffer; } public void Dispose() { _hashMap.Dispose(); } }