using Qrakhen.Qamp.Core.Values.Objects; using System.Runtime.InteropServices; using Qrakhen.Qamp.Core.Collections; namespace Qrakhen.Qamp.Core.Values; [StructLayout(LayoutKind.Sequential, Size = sizeof(ulong))] public readonly struct Ptr { private static readonly PushStack _register = new(); [Serialized] public readonly Address Address; //private readonly IntPtr _pointer; //public IntPtr Pointer => _pointer; public Obj? Value { get { if (_register.TryGet(Address, out Obj obj)) return obj; return null; //if (_pointer == IntPtr.Zero) // throw new ObjectDisposedException(nameof(Ptr)); //return (Obj)GCHandle.FromIntPtr(_pointer).Target!; } } private Ptr(Address address) { //_pointer = GCHandle.ToIntPtr(GCHandle.Alloc(obj, GCHandleType.Normal)); Address = address; } public static Ptr Create(Obj obj) { return new Ptr(_register.Add(obj)); } public T? As(bool throwWhenNull = true) where T : Obj { T? value = Value as T; if (value == null && throwWhenNull) throw new RuntimeException($"Could not convert Object {Value} to target type {typeof(T)}.", Value); return value; } public override string ToString() => $"0x{Value}"; public static byte[] SerializeFunctions() { List result = new(); for (int i = 0; i < _register.Count; i++) { Obj obj = _register.Get(i); if (obj == null || obj.__gcMarked) continue; byte[] bytes; if (obj is Function function) { bytes = function.Serialize(); } else if (obj is Context context) { bytes = context.Function.Serialize(); } else { continue; } result.AddRange(i.GetBytes()); result.AddRange(bytes.Length.GetBytes()); result.AddRange(bytes); result.Add(0); } return result.ToArray(); } }