84 lines
2.2 KiB
C#
84 lines
2.2 KiB
C#
using Qrakhen.Qamp.Core.Values.Objects;
|
|
using System.Runtime.InteropServices;
|
|
using Qrakhen.Qamp.Core.Collections;
|
|
|
|
namespace Qrakhen.Qamp.Core.Values;
|
|
|
|
// generally interesting: GCHandle.ToIntPtr(GCHandle.Alloc(obj, GCHandleType.Normal));
|
|
|
|
[StructLayout(LayoutKind.Sequential, Size = sizeof(ulong))]
|
|
public readonly struct Ptr
|
|
{
|
|
private static readonly Table<Obj> _register = []; // should not be needed that anymore tbh.
|
|
|
|
[Serialized] public readonly Address Address;
|
|
|
|
public Obj? Value {
|
|
get {
|
|
if (ObjTable.Shared.TryGet(Address, out Obj? obj))
|
|
return obj;
|
|
return null;
|
|
}
|
|
}
|
|
|
|
private Ptr(Address address)
|
|
{
|
|
Address = address;
|
|
}
|
|
|
|
public static Ptr Create(Obj obj)
|
|
{
|
|
return new Ptr(_register.Add(obj));
|
|
}
|
|
|
|
public T? As<T>(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 Obj? As(Type type, bool throwWhenNull = true)
|
|
{
|
|
Obj? value = Convert.ChangeType(Value, type) as Obj;
|
|
if (value == null && throwWhenNull)
|
|
throw new RuntimeException($"Could not convert Object {Value} to target type {type}.", Value);
|
|
return value;
|
|
}
|
|
|
|
public override string ToString() => $"0x{Value}";
|
|
|
|
public static async Task __GC_Prepare()
|
|
{
|
|
await Task.Run(() => {
|
|
foreach (var obj in _register) {
|
|
obj.Value.__GC_Count = 0;
|
|
}
|
|
});
|
|
}
|
|
|
|
public static byte[] SerializeFunctions()
|
|
{
|
|
List<byte> result = new();
|
|
foreach (var element in _register) {
|
|
Obj obj = element.Value;
|
|
if (obj == null || obj.__GC_Marked)
|
|
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(((long)element.Key).GetBytes());
|
|
result.AddRange(bytes.Length.GetBytes());
|
|
result.AddRange(bytes);
|
|
result.Add(0);
|
|
}
|
|
return result.ToArray();
|
|
}
|
|
} |