You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

183 lines
7.6 KiB

  1. using IPA.Config.Data;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using System.Reflection;
  6. using System.Reflection.Emit;
  7. using System.Text;
  8. using System.Threading.Tasks;
  9. namespace IPA.Config.Stores
  10. {
  11. internal static partial class GeneratedStoreImpl
  12. {
  13. internal delegate Value SerializeObject<T>(T obj);
  14. internal delegate T DeserializeObject<T>(Value val, object parent);
  15. private static class DelegateStore<T>
  16. {
  17. public static SerializeObject<T> Serialize;
  18. public static DeserializeObject<T> Deserialize;
  19. }
  20. internal static SerializeObject<T> GetSerializerDelegate<T>()
  21. => DelegateStore<T>.Serialize ??= GetSerializerDelegateInternal<T>();
  22. private static SerializeObject<T> GetSerializerDelegateInternal<T>()
  23. {
  24. var type = typeof(T);
  25. #if DEBUG
  26. var defType = Module.DefineType($"{type.FullName}<SerializeTypeContainer>", TypeAttributes.Public | TypeAttributes.Sealed | TypeAttributes.Abstract);
  27. var dynMethod = defType.DefineMethod("SerializeType", MethodAttributes.Public | MethodAttributes.Static, typeof(Value), new[] { type });
  28. #else
  29. var dynMethod = new DynamicMethod($"SerializeType>>{type.FullName}", typeof(Value), new[] { type }, Module, true);
  30. #endif
  31. var structure = ReadObjectMembers(type);
  32. //CreateAndInitializeConvertersFor(type, structure);
  33. var loadObject = type.IsValueType
  34. ? (Action<ILGenerator>)(il => il.Emit(OpCodes.Ldarga_S, 0))
  35. : il => il.Emit(OpCodes.Ldarg_0);
  36. {
  37. var il = dynMethod.GetILGenerator();
  38. var GetLocal = MakeLocalAllocator(il);
  39. EmitLogError(il, $"Entered SerializeType delegate for type {type}");
  40. if (!type.IsValueType)
  41. {
  42. var notIGeneratedStore = il.DefineLabel();
  43. var IGeneratedStore_t = typeof(IGeneratedStore);
  44. var IGeneratedStore_Serialize = IGeneratedStore_t.GetMethod(nameof(IGeneratedStore.Serialize));
  45. il.Emit(OpCodes.Ldarg_0);
  46. il.Emit(OpCodes.Isinst, IGeneratedStore_t);
  47. il.Emit(OpCodes.Brfalse, notIGeneratedStore);
  48. il.Emit(OpCodes.Ldarg_0);
  49. il.Emit(OpCodes.Castclass, IGeneratedStore_t);
  50. il.Emit(OpCodes.Callvirt, IGeneratedStore_Serialize);
  51. il.Emit(OpCodes.Ret);
  52. il.MarkLabel(notIGeneratedStore);
  53. }
  54. EmitLogError(il, $"Serializing structure of {type}");
  55. EmitSerializeStructure(il, structure, GetLocal, loadObject);
  56. il.Emit(OpCodes.Ret);
  57. }
  58. #if DEBUG
  59. defType.CreateType();
  60. return (SerializeObject<T>)Delegate.CreateDelegate(typeof(SerializeObject<T>), dynMethod);
  61. #else
  62. return (SerializeObject<T>)dynMethod.CreateDelegate(typeof(SerializeObject<T>));
  63. #endif
  64. }
  65. internal static DeserializeObject<T> GetDeserializerDelegate<T>()
  66. => DelegateStore<T>.Deserialize ??= GetDeserializerDelegateInternal<T>();
  67. private static DeserializeObject<T> GetDeserializerDelegateInternal<T>()
  68. {
  69. var type = typeof(T);
  70. //var dynMethod = new DynamicMethod($"DeserializeType>>{type.FullName}", type, new[] { typeof(Value), typeof(object) }, Module, true);
  71. #if DEBUG
  72. var defType = Module.DefineType($"{type.FullName}<DeserializeTypeContainer>", TypeAttributes.Public | TypeAttributes.Sealed | TypeAttributes.Abstract);
  73. var dynMethod = defType.DefineMethod("DeserializeType", MethodAttributes.Public | MethodAttributes.Static, type, new[] { typeof(Value), typeof(object) });
  74. #else
  75. var dynMethod = new DynamicMethod($"DeserializeType>>{type.FullName}", type, new[] { typeof(Value), typeof(object) }, Module, true);
  76. #endif
  77. var structure = ReadObjectMembers(type);
  78. //CreateAndInitializeConvertersFor(type, structure);
  79. {
  80. var il = dynMethod.GetILGenerator();
  81. var GetLocal = MakeLocalAllocator(il);
  82. var IGeneratedStore_t = typeof(IGeneratedStore);
  83. var IGeneratedStore_Deserialize = IGeneratedStore_t.GetMethod(nameof(IGeneratedStore.Deserialize));
  84. void ParentObj(ILGenerator il)
  85. {
  86. il.Emit(OpCodes.Ldarg_1);
  87. il.Emit(OpCodes.Isinst, IGeneratedStore_t);
  88. }
  89. EmitLogError(il, $"Entered DeserializeType delegate for type {type}");
  90. if (!type.IsValueType)
  91. {
  92. EmitLogError(il, $"Forwarding to created type serialization");
  93. EmitCreateChildGenerated(il, type, ParentObj);
  94. il.Emit(OpCodes.Dup);
  95. il.Emit(OpCodes.Castclass, IGeneratedStore_t);
  96. il.Emit(OpCodes.Ldarg_0);
  97. il.Emit(OpCodes.Callvirt, IGeneratedStore_Deserialize);
  98. il.Emit(OpCodes.Ret);
  99. }
  100. else
  101. {
  102. var Map_t = typeof(Map);
  103. var Map_TryGetValue = Map_t.GetMethod(nameof(Map.TryGetValue));
  104. var Object_GetType = typeof(object).GetMethod(nameof(Object.GetType));
  105. var valueLocal = il.DeclareLocal(typeof(Value));
  106. var mapLocal = il.DeclareLocal(typeof(Map));
  107. var resultLocal = il.DeclareLocal(type);
  108. var nonNull = il.DefineLabel();
  109. EmitLogError(il, $"Deserializing structure of {type}");
  110. il.Emit(OpCodes.Ldarg_0);
  111. il.Emit(OpCodes.Brtrue, nonNull);
  112. EmitLogError(il, "Attempting to deserialize null", tailcall: false);
  113. il.Emit(OpCodes.Ldloc, resultLocal);
  114. il.Emit(OpCodes.Ret);
  115. il.MarkLabel(nonNull);
  116. il.Emit(OpCodes.Ldarg_0);
  117. il.Emit(OpCodes.Isinst, Map_t);
  118. il.Emit(OpCodes.Dup); // duplicate cloned value
  119. il.Emit(OpCodes.Stloc, mapLocal);
  120. var notMapError = il.DefineLabel();
  121. il.Emit(OpCodes.Brtrue, notMapError);
  122. // handle error
  123. EmitLogError(il, $"Invalid root for deserializing {type.FullName}", tailcall: false,
  124. expected: il => EmitTypeof(il, Map_t), found: il =>
  125. {
  126. il.Emit(OpCodes.Ldarg_0);
  127. il.Emit(OpCodes.Callvirt, Object_GetType);
  128. });
  129. il.Emit(OpCodes.Ldloc, resultLocal);
  130. il.Emit(OpCodes.Ret);
  131. il.MarkLabel(notMapError);
  132. EmitDeserializeStructure(il, structure, mapLocal, valueLocal, GetLocal, il => il.Emit(OpCodes.Ldloca, resultLocal), ParentObj);
  133. il.Emit(OpCodes.Ldloc, resultLocal);
  134. il.Emit(OpCodes.Ret);
  135. }
  136. }
  137. #if DEBUG
  138. defType.CreateType();
  139. return (DeserializeObject<T>)Delegate.CreateDelegate(typeof(DeserializeObject<T>), dynMethod);
  140. #else
  141. return (DeserializeObject<T>)dynMethod.CreateDelegate(typeof(DeserializeObject<T>));
  142. #endif
  143. }
  144. }
  145. }