Skip to content

Instantly share code, notes, and snippets.

@AGeorgy
Created July 9, 2019 09:28
Show Gist options
  • Select an option

  • Save AGeorgy/58d56bb33aa91cf3bb1f094e3598b184 to your computer and use it in GitHub Desktop.

Select an option

Save AGeorgy/58d56bb33aa91cf3bb1f094e3598b184 to your computer and use it in GitHub Desktop.
CustomeSerialization
public struct BitInputStream : INetworkStream
{
public uint Length { get; }
private int SizeBytes => _currentByteIndex * sizeof(byte);
private readonly unsafe byte* _buffer;
private int _currentByteIndex;
public unsafe BitInputStream(byte[] buffer)
{
Length = (uint)buffer.Length;
fixed (byte* ptr = buffer)
{
_buffer = ptr;
}
_currentByteIndex = 0;
}
public unsafe void Process<T>(ref T value) where T : unmanaged
{
#if ENABLE_UNITY_COLLECTIONS_CHECKS
var newLength = _currentByteIndex + sizeof(T);
if (newLength > Length)
throw new IndexOutOfRangeException($"New length of buffer: {newLength} is out of range in buffer of '{Length}' Length.");
#endif
value = *(T*) (_buffer + _currentByteIndex);
_currentByteIndex += sizeof(T);
}
public unsafe void Process(ref bool value)
{
#if ENABLE_UNITY_COLLECTIONS_CHECKS
var newLength = _currentByteIndex + sizeof(byte);
if (newLength > Length)
throw new IndexOutOfRangeException($"New length of buffer: {newLength} is out of range in buffer of '{Length}' Length.");
#endif
value = *(_buffer + _currentByteIndex) != 0;
_currentByteIndex += sizeof(byte);
}
public void Process(ref float value, CastType castType = CastType.Float, int precision = 1)
{
switch (castType)
{
case CastType.Byte:
value = (float) Process<byte>() / precision;
break;
case CastType.Short:
value = (float) Process<short>() / precision;
break;
case CastType.Int:
value = (float) Process<int>() / precision;
break;
case CastType.Long:
value = (float) Process<long>() / precision;
break;
case CastType.Float:
value = Process<float>() / precision;
break;
}
}
public unsafe byte[] ToArrayAndFlush()
{
var data = new byte[SizeBytes];
fixed (byte* ptr = data)
{
Buffer.MemoryCopy(_buffer, ptr, SizeBytes, SizeBytes);
}
_currentByteIndex = 0;
return data;
}
private unsafe T Process<T>() where T : unmanaged
{
#if ENABLE_UNITY_COLLECTIONS_CHECKS
var newLength = _currentByteIndex + sizeof(T);
if (newLength > Length)
throw new IndexOutOfRangeException($"New length of buffer: {newLength} is out of range in buffer of '{Length}' Length.");
#endif
var value = *(T*) (_buffer + _currentByteIndex);
_currentByteIndex += sizeof(T);
return value;
}
public void Dispose()
{
}
}
public struct BitOutputStream : INetworkStream
{
public uint Length { get; }
private int SizeBytes => _currentByteIndex * sizeof(byte);
private readonly unsafe byte* _buffer;
private int _currentByteIndex;
private byte[] buffer;
public unsafe BitOutputStream(uint length)
{
Length = length;
buffer = new byte[length];
fixed (byte* ptr = buffer)
{
_buffer = ptr;
}
_currentByteIndex = 0;
}
public unsafe void Process<T>(ref T value) where T : unmanaged
{
#if ENABLE_UNITY_COLLECTIONS_CHECKS
var newLength = _currentByteIndex + sizeof(T);
if (newLength > Length)
throw new IndexOutOfRangeException($"New length of buffer: {newLength} is out of range in buffer of '{Length}' Length.");
#endif
*(T*) (_buffer + _currentByteIndex) = value;
_currentByteIndex += sizeof(T);
}
public unsafe void Process(ref bool value)
{
#if ENABLE_UNITY_COLLECTIONS_CHECKS
var newLength = _currentByteIndex + sizeof(byte);
if (newLength > Length)
throw new IndexOutOfRangeException($"New length of buffer: {newLength} is out of range in buffer of '{Length}' Length.");
#endif
*(_buffer + _currentByteIndex) = value ? (byte) 1 : (byte) 0;
_currentByteIndex += sizeof(byte);
}
public void Process(ref float value, CastType castType = CastType.Float, int precision = 1)
{
//DebugLogger.Instance.Log(LogType.Log, $"buffer length: {_buffer.Length}, current index: {_currentByteIndex}, type: {castType}");
var result = value * precision;
switch (castType)
{
case CastType.Byte:
DebugLogger.Assert(result > byte.MinValue && result < byte.MaxValue);
Process((byte) result);
break;
case CastType.Short:
DebugLogger.Assert(result > short.MinValue && result < short.MaxValue);
Process((short) result);
break;
case CastType.Int:
DebugLogger.Assert(result > int.MinValue && result < int.MaxValue);
Process((int) result);
break;
case CastType.Long:
DebugLogger.Assert(result > long.MinValue && result < long.MaxValue);
Process((long) result);
break;
case CastType.Float:
Process(ref result);
break;
}
}
public unsafe byte[] ToArrayAndFlush()
{
var data = new byte[SizeBytes];
fixed (byte* ptr = data)
{
Buffer.MemoryCopy(_buffer, ptr, SizeBytes, SizeBytes);
}
_currentByteIndex = 0;
return data;
}
private unsafe void Process<T>(T value) where T : unmanaged
{
#if ENABLE_UNITY_COLLECTIONS_CHECKS
var newLength = _currentByteIndex + sizeof(T);
if (newLength > Length)
throw new IndexOutOfRangeException($"New length of buffer: {newLength} is out of range in buffer of '{Length}' Length.");
#endif
*(T*) (_buffer + _currentByteIndex) = value;
_currentByteIndex += sizeof(T);
}
public void Dispose()
{
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment