forked from citizenfx/msgpack-cs
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathEnumFormatter.cs
More file actions
83 lines (68 loc) · 2.86 KB
/
EnumFormatter.cs
File metadata and controls
83 lines (68 loc) · 2.86 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
using System;
using System.Reflection;
using System.Reflection.Emit;
namespace CitizenFX.MsgPack.Formatters
{
internal static class EnumFormatter
{
public static Tuple<Serializer, MethodInfo> Build(Type enumType, Type unused = null)
{
string name = $"EnumFormatter_{enumType.FullName}";
Type buildType = MsgPackRegistry.m_moduleBuilder.GetType(name);
MethodInfo methodSerialize, methodDeserialize, methodObjectSerialize;
if (buildType == null)
{
TypeBuilder typeBuilder = MsgPackRegistry.m_moduleBuilder.DefineType(name);
methodSerialize = BuildSerializer(enumType, typeBuilder);
BuildDeserializer(enumType, typeBuilder);
BuildObjectSerializer(enumType, methodSerialize, typeBuilder);
buildType = typeBuilder.CreateType();
}
methodSerialize = buildType.GetMethod("Serialize", new[] { typeof(MsgPackSerializer), enumType });
methodDeserialize = buildType.GetMethod("Deserialize");
methodObjectSerialize = buildType.GetMethod("Serialize", new[] { typeof(MsgPackSerializer), typeof(object) });
Serializer serializer = new Serializer(methodSerialize, methodObjectSerialize);
MsgPackRegistry.RegisterSerializer(enumType, serializer);
MsgPackRegistry.RegisterDeserializer(enumType, methodDeserialize);
return new Tuple<Serializer, MethodInfo>(serializer, methodDeserialize);
}
private static MethodInfo BuildObjectSerializer(Type enumType, MethodInfo methodSerialize, TypeBuilder typeBuilder)
{
MethodBuilder method = typeBuilder.DefineMethod("Serialize",
MethodAttributes.Public | MethodAttributes.Static,
typeof(void),
new[] { typeof(MsgPackSerializer), typeof(object) });
var g = method.GetILGenerator();
g.Emit(OpCodes.Ldarg_0);
g.Emit(OpCodes.Ldarg_1);
g.Emit(OpCodes.Unbox_Any, enumType);
g.EmitCall(OpCodes.Call, methodSerialize, null);
g.Emit(OpCodes.Ret);
return method;
}
private static MethodInfo BuildSerializer(Type enumType, TypeBuilder typeBuilder)
{
MethodBuilder method = typeBuilder.DefineMethod("Serialize",
MethodAttributes.Public | MethodAttributes.Static,
typeof(void),
new[] { typeof(MsgPackSerializer), enumType });
var g = method.GetILGenerator();
g.Emit(OpCodes.Ldarg_0);
g.Emit(OpCodes.Ldarg_1);
g.EmitCall(OpCodes.Call, MsgPackRegistry.GetOrCreateSerializer(typeof(uint)), null);
g.Emit(OpCodes.Ret);
return method;
}
private static MethodInfo BuildDeserializer(Type enumType, TypeBuilder typeBuilder)
{
MethodBuilder methodDeserialize = typeBuilder.DefineMethod("Deserialize",
MethodAttributes.Public | MethodAttributes.Static,
enumType, new[] { typeof(MsgPackDeserializer).MakeByRefType() });
var g = methodDeserialize.GetILGenerator();
g.Emit(OpCodes.Ldarg_0);
g.EmitCall(OpCodes.Call, MsgPackRegistry.GetOrCreateDeserializer(typeof(uint)), null);
g.Emit(OpCodes.Ret);
return methodDeserialize;
}
}
}