|
|
- #nullable enable
- using IPA.Config.Data;
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Reflection;
- using System.Reflection.Emit;
- using System.Text;
- using System.Threading.Tasks;
-
- namespace IPA.Config.Stores
- {
- internal static partial class GeneratedStoreImpl
- {
-
- internal delegate Value SerializeObject<T>(T obj);
- internal delegate T DeserializeObject<T>(Value? val, object parent);
-
- private static class DelegateStore<T>
- {
- public static SerializeObject<T>? Serialize;
- public static DeserializeObject<T>? Deserialize;
- }
-
- internal static SerializeObject<T> GetSerializerDelegate<T>()
- => DelegateStore<T>.Serialize ??= GetSerializerDelegateInternal<T>();
-
- private static SerializeObject<T> GetSerializerDelegateInternal<T>()
- {
- var type = typeof(T);
- #if DEBUG
- var defType = Module.DefineType($"{type.FullName}<SerializeTypeContainer>", TypeAttributes.Public | TypeAttributes.Sealed | TypeAttributes.Abstract);
- var dynMethod = defType.DefineMethod("SerializeType", MethodAttributes.Public | MethodAttributes.Static, typeof(Value), new[] { type });
- #else
- var dynMethod = new DynamicMethod($"SerializeType>>{type.FullName}", typeof(Value), new[] { type }, Module, true);
- #endif
-
- var structure = ReadObjectMembers(type);
-
- //CreateAndInitializeConvertersFor(type, structure);
-
- var loadObject = type.IsValueType
- ? (Action<ILGenerator>)(il => il.Emit(OpCodes.Ldarga_S, 0))
- : il => il.Emit(OpCodes.Ldarg_0);
- var loadParent = type.IsValueType
- ? (Action<ILGenerator>)(il => il.Emit(OpCodes.Ldnull))
- : loadObject;
- {
- var il = dynMethod.GetILGenerator();
-
- var GetLocal = MakeLocalAllocator(il);
-
- if (!type.IsValueType)
- {
- var notIGeneratedStore = il.DefineLabel();
- var IGeneratedStore_t = typeof(IGeneratedStore);
- var IGeneratedStore_Serialize = IGeneratedStore_t.GetMethod(nameof(IGeneratedStore.Serialize));
-
- il.Emit(OpCodes.Ldarg_0);
- il.Emit(OpCodes.Isinst, IGeneratedStore_t);
- il.Emit(OpCodes.Brfalse, notIGeneratedStore);
-
- il.Emit(OpCodes.Ldarg_0);
- il.Emit(OpCodes.Castclass, IGeneratedStore_t);
- il.Emit(OpCodes.Callvirt, IGeneratedStore_Serialize);
- il.Emit(OpCodes.Ret);
-
- il.MarkLabel(notIGeneratedStore);
- }
-
- EmitSerializeStructure(il, structure, GetLocal, loadObject, loadParent);
-
- il.Emit(OpCodes.Ret);
- }
-
- #if DEBUG
- defType.CreateType();
- return (SerializeObject<T>)Delegate.CreateDelegate(typeof(SerializeObject<T>), dynMethod);
- #else
- return (SerializeObject<T>)dynMethod.CreateDelegate(typeof(SerializeObject<T>));
- #endif
- }
-
- internal static DeserializeObject<T> GetDeserializerDelegate<T>()
- => DelegateStore<T>.Deserialize ??= GetDeserializerDelegateInternal<T>();
-
- private static DeserializeObject<T> GetDeserializerDelegateInternal<T>()
- {
- var type = typeof(T);
- //var dynMethod = new DynamicMethod($"DeserializeType>>{type.FullName}", type, new[] { typeof(Value), typeof(object) }, Module, true);
-
- #if DEBUG
- var defType = Module.DefineType($"{type.FullName}<DeserializeTypeContainer>", TypeAttributes.Public | TypeAttributes.Sealed | TypeAttributes.Abstract);
- var dynMethod = defType.DefineMethod("DeserializeType", MethodAttributes.Public | MethodAttributes.Static, type, new[] { typeof(Value), typeof(object) });
- #else
- var dynMethod = new DynamicMethod($"DeserializeType>>{type.FullName}", type, new[] { typeof(Value), typeof(object) }, Module, true);
- #endif
-
- var structure = ReadObjectMembers(type);
-
- //CreateAndInitializeConvertersFor(type, structure);
-
- {
- var il = dynMethod.GetILGenerator();
-
- var GetLocal = MakeLocalAllocator(il);
-
- var IGeneratedStore_t = typeof(IGeneratedStore);
- var IGeneratedStore_Deserialize = IGeneratedStore_t.GetMethod(nameof(IGeneratedStore.Deserialize));
-
- void ParentObj(ILGenerator il)
- {
- il.Emit(OpCodes.Ldarg_1);
- il.Emit(OpCodes.Isinst, IGeneratedStore_t);
- }
-
- if (!type.IsValueType)
- {
- EmitCreateChildGenerated(il, type, ParentObj);
- il.Emit(OpCodes.Dup);
- il.Emit(OpCodes.Castclass, IGeneratedStore_t);
- il.Emit(OpCodes.Ldarg_0);
- il.Emit(OpCodes.Callvirt, IGeneratedStore_Deserialize);
- il.Emit(OpCodes.Ret);
- }
- else
- {
- var Map_t = typeof(Map);
- var Map_TryGetValue = Map_t.GetMethod(nameof(Map.TryGetValue));
- var Object_GetType = typeof(object).GetMethod(nameof(Object.GetType));
-
- var valueLocal = il.DeclareLocal(typeof(Value));
- var mapLocal = il.DeclareLocal(typeof(Map));
- var resultLocal = il.DeclareLocal(type);
-
- var nonNull = il.DefineLabel();
-
- il.Emit(OpCodes.Ldarg_0);
- il.Emit(OpCodes.Brtrue, nonNull);
-
- EmitLogError(il, "Attempting to deserialize null", tailcall: false);
- il.Emit(OpCodes.Ldloc, resultLocal);
- il.Emit(OpCodes.Ret);
-
- il.MarkLabel(nonNull);
- il.Emit(OpCodes.Ldarg_0);
- il.Emit(OpCodes.Isinst, Map_t);
- il.Emit(OpCodes.Dup); // duplicate cloned value
- il.Emit(OpCodes.Stloc, mapLocal);
- var notMapError = il.DefineLabel();
- il.Emit(OpCodes.Brtrue, notMapError);
- // handle error
- EmitLogError(il, $"Invalid root for deserializing {type.FullName}", tailcall: false,
- expected: il => EmitTypeof(il, Map_t), found: il =>
- {
- il.Emit(OpCodes.Ldarg_0);
- il.Emit(OpCodes.Callvirt, Object_GetType);
- });
- il.Emit(OpCodes.Ldloc, resultLocal);
- il.Emit(OpCodes.Ret);
-
- il.MarkLabel(notMapError);
-
- EmitDeserializeStructure(il, structure, mapLocal, valueLocal, GetLocal, il => il.Emit(OpCodes.Ldloca, resultLocal), ParentObj);
-
- il.Emit(OpCodes.Ldloc, resultLocal);
- il.Emit(OpCodes.Ret);
- }
- }
-
- #if DEBUG
- defType.CreateType();
- return (DeserializeObject<T>)Delegate.CreateDelegate(typeof(DeserializeObject<T>), dynMethod);
- #else
- return (DeserializeObject<T>)dynMethod.CreateDelegate(typeof(DeserializeObject<T>));
- #endif
- }
- }
- }
|