Skip to content

Commit c96634f

Browse files
authored
Merge pull request #42 from TwoTenPvP/bit-serializer
Bit serializer
2 parents 2bde20b + a94acfe commit c96634f

File tree

4 files changed

+540
-0
lines changed

4 files changed

+540
-0
lines changed

MLAPI/MLAPI.csproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,9 @@
7878
<Compile Include="GlobalSuppressions.cs" />
7979
<Compile Include="MonoBehaviours\Prototyping\NetworkedAnimator.cs" />
8080
<Compile Include="MonoBehaviours\Prototyping\NetworkedNavMeshAgent.cs" />
81+
<Compile Include="NetworkingManagerComponents\Binary\BitWriter.cs" />
82+
<Compile Include="NetworkingManagerComponents\Binary\BitReader.cs" />
83+
<Compile Include="NetworkingManagerComponents\Binary\BinaryHelpers.cs" />
8184
<Compile Include="NetworkingManagerComponents\Binary\BinarySerializer.cs" />
8285
<Compile Include="NetworkingManagerComponents\Cryptography\CryptographyHelper.cs" />
8386
<Compile Include="NetworkingManagerComponents\Cryptography\DiffieHellman.cs" />
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
6+
namespace MLAPI.NetworkingManagerComponents.Binary
7+
{
8+
public static class BinaryHelpers
9+
{
10+
// Swap endianness of a given integer
11+
public static uint SwapEndian(uint value) => (uint)(((value >> 24) & (255 << 0)) | ((value >> 8) & (255 << 8)) | ((value << 8) & (255 << 16)) | ((value << 24) & (255 << 24)));
12+
public static ulong SwapEndian(ulong value) =>
13+
((value >> 56) & 0xFF) |
14+
((value >> 40) & (0xFFUL << 8)) |
15+
((value >> 24) & (0xFFUL << 16)) |
16+
((value >> 8) & (0xFFUL << 24)) |
17+
((value << 56) & (0xFFUL << 56)) |
18+
((value << 40) & (0xFFUL << 48)) |
19+
((value << 24) & (0xFFUL << 40)) |
20+
((value << 8) & (0xFFUL << 32)) ;
21+
}
22+
}
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
using System;
2+
using System.Runtime.InteropServices;
3+
using System.Text;
4+
5+
namespace MLAPI.NetworkingManagerComponents.Binary
6+
{
7+
public class BitReader
8+
{
9+
private delegate T Getter<T>();
10+
private static readonly float[] holder_f = new float[1];
11+
private static readonly double[] holder_d = new double[1];
12+
private static readonly ulong[] holder_u = new ulong[1];
13+
private static readonly uint[] holder_i = new uint[1];
14+
15+
private readonly byte[] readFrom;
16+
private long bitCount = 0;
17+
public BitReader(byte[] readFrom) => this.readFrom = readFrom;
18+
19+
public bool ReadBool()
20+
{
21+
bool result = (readFrom[bitCount / 8] & (byte)(1 << (int)(bitCount % 8))) != 0;
22+
++bitCount;
23+
return result;
24+
}
25+
26+
public float ReadFloat() => ReadFloating<float>();
27+
public double ReadDouble() => ReadFloating<double>();
28+
public byte ReadByte()
29+
{
30+
int shift = (int)(bitCount % 8);
31+
int index = (int)(bitCount / 8);
32+
byte lower_mask = (byte)(0xFF << shift);
33+
byte upper_mask = (byte)~lower_mask;
34+
byte result = (byte)(((readFrom[index] & lower_mask) >> shift) | (shift == 0 ? 0 : (readFrom[index + 1] & upper_mask) << (8 - shift)));
35+
bitCount += 8;
36+
return result;
37+
}
38+
public void SkipPadded() => bitCount += (8 - (bitCount % 8)) % 8;
39+
public ushort ReadUShort() => (ushort)ReadULong();
40+
public uint ReadUInt() => (uint)ReadULong();
41+
public sbyte ReadSByte() => (sbyte)ZigZagDecode(ReadByte(), 1);
42+
public short ReadShort() => (short)ZigZagDecode(ReadUShort(), 2);
43+
public int ReadInt() => (int)ZigZagDecode(ReadUInt(), 4);
44+
public long ReadLong() => ZigZagDecode(ReadULong(), 8);
45+
public float[] ReadFloatArray(int known = -1) => ReadArray(ReadFloat, known);
46+
public double[] ReadDoubleArray(int known = -1) => ReadArray(ReadDouble, known);
47+
public byte[] ReadByteArray(int known = -1) => ReadArray(ReadByte, known);
48+
public ushort[] ReadUShortArray(int known = -1) => ReadArray(ReadUShort, known);
49+
public uint[] ReadUIntArray(int known = -1) => ReadArray(ReadUInt, known);
50+
public ulong[] ReadULongArray(int known = -1) => ReadArray(ReadULong, known);
51+
public sbyte[] ReadSByteArray(int known = -1) => ReadArray(ReadSByte, known);
52+
public short[] ReadShortArray(int known = -1) => ReadArray(ReadShort, known);
53+
public int[] ReadIntArray(int known = -1) => ReadArray(ReadInt, known);
54+
public long[] ReadLongArray(int known = -1) => ReadArray(ReadLong, known);
55+
public string ReadString() => Encoding.UTF8.GetString(ReadByteArray());
56+
57+
public ulong ReadULong()
58+
{
59+
ulong header = ReadByte();
60+
if (header <= 240) return header;
61+
if (header <= 248) return 240 + 256 * (header - 241) + ReadByte();
62+
if (header == 249) return 2288 + 256UL * ReadByte() + ReadByte();
63+
ulong res = ReadByte() | ((ulong)ReadByte() << 8) | ((ulong)ReadByte() << 16);
64+
if(header > 250)
65+
{
66+
res |= (ulong) ReadByte() << 24;
67+
if(header > 251)
68+
{
69+
res |= (ulong)ReadByte() << 32;
70+
if(header > 252)
71+
{
72+
res |= (ulong)ReadByte() << 40;
73+
if (header > 253)
74+
{
75+
res |= (ulong)ReadByte() << 48;
76+
if (header > 254) res |= (ulong)ReadByte() << 56;
77+
}
78+
}
79+
}
80+
}
81+
return res;
82+
}
83+
private T[] ReadArray<T>(Getter<T> g, int knownSize = -1)
84+
{
85+
T[] result = new T[knownSize > 0 ? (uint)knownSize : ReadUInt()];
86+
for (ushort s = 0; s < result.Length; ++s)
87+
result[s] = g();
88+
return result;
89+
}
90+
91+
private T ReadFloating<T>()
92+
{
93+
int size = Marshal.SizeOf(typeof(T));
94+
Array type_holder = size == 4 ? holder_f as Array : holder_d as Array;
95+
Array result_holder = size == 4 ? holder_i as Array : holder_u as Array;
96+
T result;
97+
lock(result_holder)
98+
lock (type_holder)
99+
{
100+
//for (int i = 0; i < size; ++i)
101+
// holder.SetValue(ReadByte(), i);
102+
if (size == 4) result_holder.SetValue(BinaryHelpers.SwapEndian(ReadUInt()), 0);
103+
else result_holder.SetValue(BinaryHelpers.SwapEndian(ReadULong()), 0);
104+
Buffer.BlockCopy(result_holder, 0, type_holder, 0, size);
105+
result = (T)type_holder.GetValue(0);
106+
}
107+
return result;
108+
}
109+
private static long ZigZagDecode(ulong d, int bytes) => (long)(((d << (bytes * 8 - 1)) & 1) | (d >> 1));
110+
}
111+
}

0 commit comments

Comments
 (0)