using Misaki.HighPerformance.LowLevel.Buffer; using Misaki.HighPerformance.LowLevel.Collections.Contracts; using System.Diagnostics.CodeAnalysis; 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 : IUnsafeHashCollection where T : unmanaged, IEquatable { public ref struct Enumerator { internal HashMapHelper.Enumerator _enumerator; public readonly T Current => _enumerator.helper._keys[_enumerator.index]; public Enumerator(ref HashMapHelper hashMap) { _enumerator = new HashMapHelper.Enumerator(ref hashMap); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool MoveNext() { return _enumerator.MoveNext(); } public void Reset() { _enumerator.Reset(); } } private HashMapHelper _helper; public readonly int Count => _helper.Count; public readonly int Capacity => _helper.Capacity; public readonly bool IsCreated => _helper.IsCreated; /// /// Initializes a new instance of UnsafeHashSet with a default size of 1 and a persistent allocation handle. /// public UnsafeHashSet() : this(1, AllocationHandle.Persistent) { } public UnsafeHashSet(int capacity, AllocationHandle handle, AllocationOption allocationOption = AllocationOption.None) { _helper = new HashMapHelper(capacity, 0, 0, HashMapHelper.MINIMAL_CAPACITY, handle, allocationOption); } [Obsolete("Use AllocationHandle instead.")] public UnsafeHashSet(int capacity, Allocator allocator, AllocationOption allocationOption = AllocationOption.None) : this(capacity, AllocationManager.GetAllocationHandle(allocator), allocationOption) { } [MethodImpl(MethodImplOptions.AggressiveInlining)] [UnscopedRef] public Enumerator GetEnumerator() { return new Enumerator(ref _helper); } /// /// Adds a new value (unless it is already present). /// /// The value to add. /// True if the value was not already present. [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool Add(T item) { return -1 != _helper.TryAdd(item); } /// /// Removes a particular value. /// /// The value to remove. /// True if the value was present. [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool Remove(T item) { return -1 != _helper.TryRemove(item); } /// /// Returns true if a particular value is present. /// /// The value to check for. /// True if the value was present. [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool Contains(T item) { return -1 != _helper.Find(item); } /// /// Sets the capacity to match what it would be if it had been originally initialized with all its entries. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public void TrimExcess() { _helper.TrimExcess(); } /// /// Returns an array with a copy of this set's values (in no particular order). /// /// The allocation handle to use to allocate the array. /// An array with a copy of the set's values. [MethodImpl(MethodImplOptions.AggressiveInlining)] public UnsafeArray ToUnsafeArray(AllocationHandle allocationHandle) { return _helper.GetKeyArray(allocationHandle); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Resize(int newSize, AllocationOption option = AllocationOption.None) { _helper.Resize(newSize); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Clear() { _helper.Clear(); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public readonly void* GetUnsafePtr() { return _helper.Buffer; } public void Dispose() { _helper.Dispose(); } }