using System; using System.Runtime.InteropServices; using static flecs_hub.flecs; namespace gaemstone.ECS.Utility; public unsafe readonly struct ReferenceHandle : IDisposable { public static int NumActiveHandles { get; private set; } private readonly nint _value; public object? Target => (_value != default) ? ((GCHandle)_value).Target : null; private ReferenceHandle(nint value) => _value = value; public static ReferenceHandle Alloc(object? target) { if (target == null) return default; NumActiveHandles++; return new((nint)GCHandle.Alloc(target)); } public ReferenceHandle Clone() => Alloc(Target); public void Dispose() { if (_value == default) return; NumActiveHandles--; ((GCHandle)_value).Free(); } [UnmanagedCallersOnly] internal static void Construct(void* ptr, int count, ecs_type_info_t* _) => new Span(ptr, count).Clear(); [UnmanagedCallersOnly] internal static void Destruct(void* ptr, int count, ecs_type_info_t* _) { var span = new Span(ptr, count); foreach (var handle in span) handle.Dispose(); span.Clear(); } [UnmanagedCallersOnly] internal static void Move(void* dstPtr, void* srcPtr, int count, ecs_type_info_t* _) { var dst = new Span(dstPtr, count); var src = new Span(srcPtr, count); foreach (var handle in dst) handle.Dispose(); src.CopyTo(dst); src.Clear(); } [UnmanagedCallersOnly] internal static void Copy(void* dstPtr, void* srcPtr, int count, ecs_type_info_t* _) { var dst = new Span(dstPtr, count); var src = new Span(srcPtr, count); for (var i = 0; i < count; i++) { dst[i].Dispose(); dst[i] = src[i].Clone(); } } }