Skip to content

Commit 435141c

Browse files
committed
Added Binary Serializer
1 parent 0a922c7 commit 435141c

File tree

2 files changed

+197
-0
lines changed

2 files changed

+197
-0
lines changed

MLAPI/MLAPI.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@
7272
<Compile Include="Data\TrackedPointData.cs" />
7373
<Compile Include="MonoBehaviours\Prototyping\NetworkedAnimator.cs" />
7474
<Compile Include="MonoBehaviours\Prototyping\NetworkedNavMeshAgent.cs" />
75+
<Compile Include="NetworkingManagerComponents\BinarySerializer.cs" />
7576
<Compile Include="NetworkingManagerComponents\CryptographyHelper.cs" />
7677
<Compile Include="NetworkingManagerComponents\DiffieHellman.cs" />
7778
<Compile Include="NetworkingManagerComponents\EllipticCurve.cs" />
Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.IO;
4+
using System.Linq;
5+
using System.Reflection;
6+
using System.Text;
7+
8+
namespace MLAPI.NetworkingManagerComponents
9+
{
10+
/// <summary>
11+
/// Helper class for serializing classes to binary
12+
/// </summary>
13+
public static class BinarySerializer
14+
{
15+
private static Dictionary<string, FieldInfo[]> cachedFields = new Dictionary<string, FieldInfo[]>();
16+
17+
/// <summary>
18+
/// Clears the cache of the serializer
19+
/// </summary>
20+
public static void ClearCache()
21+
{
22+
cachedFields.Clear();
23+
}
24+
25+
/// <summary>
26+
/// Serializes a class instance to binary
27+
/// </summary>
28+
/// <typeparam name="T">The class type to serialize</typeparam>
29+
/// <param name="instance">The instance to serialize</param>
30+
/// <returns>Binary serialized version of the instance</returns>
31+
public static byte[] Serialize<T>(T instance)
32+
{
33+
FieldInfo[] sortedFields;
34+
35+
if (cachedFields.ContainsKey(instance.GetType().FullName))
36+
sortedFields = cachedFields[instance.GetType().FullName];
37+
else
38+
{
39+
sortedFields = instance.GetType().GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance).OrderBy(x => x.Name).ToArray();
40+
cachedFields.Add(instance.GetType().FullName, sortedFields);
41+
}
42+
43+
int outputSize = 0;
44+
//Calculate output size
45+
for (int i = 0; i < sortedFields.Length; i++)
46+
{
47+
if (sortedFields[i].FieldType == typeof(bool))
48+
outputSize += 1;
49+
else if (sortedFields[i].FieldType == typeof(byte))
50+
outputSize += 1;
51+
else if (sortedFields[i].FieldType == typeof(char))
52+
outputSize += 2;
53+
else if (sortedFields[i].FieldType == typeof(double))
54+
outputSize += 8;
55+
else if (sortedFields[i].FieldType == typeof(float))
56+
outputSize += 4;
57+
else if (sortedFields[i].FieldType == typeof(decimal))
58+
outputSize += 16;
59+
else if (sortedFields[i].FieldType == typeof(int))
60+
outputSize += 4;
61+
else if (sortedFields[i].FieldType == typeof(long))
62+
outputSize += 8;
63+
else if (sortedFields[i].FieldType == typeof(sbyte))
64+
outputSize += 1;
65+
else if (sortedFields[i].FieldType == typeof(short))
66+
outputSize += 2;
67+
else if (sortedFields[i].FieldType == typeof(uint))
68+
outputSize += 4;
69+
else if (sortedFields[i].FieldType == typeof(ulong))
70+
outputSize += 8;
71+
else if (sortedFields[i].FieldType == typeof(ushort))
72+
outputSize += 2;
73+
else if (sortedFields[i].FieldType == typeof(string))
74+
outputSize += Encoding.UTF8.GetByteCount((string)sortedFields[i].GetValue(instance)) + 2;
75+
else if (sortedFields[i].FieldType == typeof(byte[]))
76+
outputSize += ((byte[])sortedFields[i].GetValue(instance)).Length + 2; //Two bytes to specify the size
77+
}
78+
79+
//Write data
80+
using (MemoryStream stream = new MemoryStream(outputSize))
81+
{
82+
using (BinaryWriter writer = new BinaryWriter(stream))
83+
{
84+
for (int i = 0; i < sortedFields.Length; i++)
85+
{
86+
if (sortedFields[i].FieldType == typeof(bool))
87+
writer.Write((bool)sortedFields[i].GetValue(instance));
88+
else if (sortedFields[i].FieldType == typeof(byte))
89+
writer.Write((byte)sortedFields[i].GetValue(instance));
90+
else if (sortedFields[i].FieldType == typeof(char))
91+
writer.Write((char)sortedFields[i].GetValue(instance));
92+
else if (sortedFields[i].FieldType == typeof(double))
93+
writer.Write((double)sortedFields[i].GetValue(instance));
94+
else if (sortedFields[i].FieldType == typeof(float))
95+
writer.Write((float)sortedFields[i].GetValue(instance));
96+
else if (sortedFields[i].FieldType == typeof(decimal))
97+
writer.Write((decimal)sortedFields[i].GetValue(instance));
98+
else if (sortedFields[i].FieldType == typeof(int))
99+
writer.Write((int)sortedFields[i].GetValue(instance));
100+
else if (sortedFields[i].FieldType == typeof(long))
101+
writer.Write((long)sortedFields[i].GetValue(instance));
102+
else if (sortedFields[i].FieldType == typeof(sbyte))
103+
writer.Write((sbyte)sortedFields[i].GetValue(instance));
104+
else if (sortedFields[i].FieldType == typeof(short))
105+
writer.Write((short)sortedFields[i].GetValue(instance));
106+
else if (sortedFields[i].FieldType == typeof(uint))
107+
writer.Write((uint)sortedFields[i].GetValue(instance));
108+
else if (sortedFields[i].FieldType == typeof(ulong))
109+
writer.Write((ulong)sortedFields[i].GetValue(instance));
110+
else if (sortedFields[i].FieldType == typeof(ushort))
111+
writer.Write((ushort)sortedFields[i].GetValue(instance));
112+
else if (sortedFields[i].FieldType == typeof(string))
113+
{
114+
writer.Write((ushort)Encoding.UTF8.GetByteCount((string)sortedFields[i].GetValue(instance))); //Size of string in bytes
115+
writer.Write(Encoding.UTF8.GetBytes((string)sortedFields[i].GetValue(instance)));
116+
}
117+
else if (sortedFields[i].FieldType == typeof(byte[]))
118+
{
119+
writer.Write((ushort)((byte[])sortedFields[i].GetValue(instance)).Length); //Size of byte array
120+
writer.Write((byte[])sortedFields[i].GetValue(instance));
121+
}
122+
}
123+
}
124+
return stream.ToArray();
125+
}
126+
}
127+
128+
/// <summary>
129+
/// Deserializes binary and turns it back into the original class
130+
/// </summary>
131+
/// <typeparam name="T">The type to return</typeparam>
132+
/// <param name="binary">The binary to deserialize</param>
133+
/// <returns>An instance of T</returns>
134+
public static T Deserialize<T>(byte[] binary) where T : new()
135+
{
136+
T instance = new T();
137+
138+
FieldInfo[] sortedFields;
139+
140+
if (cachedFields.ContainsKey(instance.GetType().FullName))
141+
sortedFields = cachedFields[instance.GetType().FullName];
142+
else
143+
{
144+
sortedFields = instance.GetType().GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance).OrderBy(x => x.Name).ToArray();
145+
cachedFields.Add(instance.GetType().FullName, sortedFields);
146+
}
147+
148+
using (MemoryStream stream = new MemoryStream(binary))
149+
{
150+
using (BinaryReader reader = new BinaryReader(stream))
151+
{
152+
for (int i = 0; i < sortedFields.Length; i++)
153+
{
154+
if (sortedFields[i].FieldType == typeof(bool))
155+
sortedFields[i].SetValue(instance, reader.ReadBoolean());
156+
else if (sortedFields[i].FieldType == typeof(byte))
157+
sortedFields[i].SetValue(instance, reader.ReadByte());
158+
else if (sortedFields[i].FieldType == typeof(char))
159+
sortedFields[i].SetValue(instance, reader.ReadChar());
160+
else if (sortedFields[i].FieldType == typeof(double))
161+
sortedFields[i].SetValue(instance, reader.ReadDouble());
162+
else if (sortedFields[i].FieldType == typeof(float))
163+
sortedFields[i].SetValue(instance, reader.ReadSingle());
164+
else if (sortedFields[i].FieldType == typeof(decimal))
165+
sortedFields[i].SetValue(instance, reader.ReadDecimal());
166+
else if (sortedFields[i].FieldType == typeof(int))
167+
sortedFields[i].SetValue(instance, reader.ReadInt32());
168+
else if (sortedFields[i].FieldType == typeof(long))
169+
sortedFields[i].SetValue(instance, reader.ReadInt64());
170+
else if (sortedFields[i].FieldType == typeof(sbyte))
171+
sortedFields[i].SetValue(instance, reader.ReadSByte());
172+
else if (sortedFields[i].FieldType == typeof(short))
173+
sortedFields[i].SetValue(instance, reader.ReadInt16());
174+
else if (sortedFields[i].FieldType == typeof(uint))
175+
sortedFields[i].SetValue(instance, reader.ReadUInt32());
176+
else if (sortedFields[i].FieldType == typeof(ulong))
177+
sortedFields[i].SetValue(instance, reader.ReadUInt64());
178+
else if (sortedFields[i].FieldType == typeof(ushort))
179+
sortedFields[i].SetValue(instance, reader.ReadUInt64());
180+
else if (sortedFields[i].FieldType == typeof(string))
181+
{
182+
ushort size = reader.ReadUInt16();
183+
sortedFields[i].SetValue(instance, Encoding.UTF8.GetString(reader.ReadBytes(size)));
184+
}
185+
else if (sortedFields[i].FieldType == typeof(byte[]))
186+
{
187+
ushort size = reader.ReadUInt16();
188+
sortedFields[i].SetValue(instance, reader.ReadBytes(size));
189+
}
190+
}
191+
}
192+
}
193+
return instance;
194+
}
195+
}
196+
}

0 commit comments

Comments
 (0)