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.
418 lines
13 KiB
418 lines
13 KiB
4 years ago
|
#if ENABLE_UNSAFE_MSGPACK
|
||
|
|
||
|
using MessagePack.Formatters;
|
||
|
using System;
|
||
|
using System.Collections.Generic;
|
||
|
using System.Text;
|
||
|
using UnityEngine;
|
||
|
|
||
|
namespace MessagePack.Unity.Extension
|
||
|
{
|
||
|
internal static class MemoryUtil
|
||
|
{
|
||
|
// If you use memcpy or check alignment and word copy, can more improve performance
|
||
|
public static unsafe void SimpleMemoryCopy(void* dest, void* src, int byteCount)
|
||
|
{
|
||
|
var pDest = (byte*)dest;
|
||
|
var pSrc = (byte*)src;
|
||
|
for (int i = 0; i < byteCount; i++)
|
||
|
{
|
||
|
*pDest = *pSrc;
|
||
|
pDest++;
|
||
|
pSrc++;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public static class ReservedUnityExtensionTypeCode
|
||
|
{
|
||
|
public const sbyte Vector2 = 30;
|
||
|
public const sbyte Vector3 = 31;
|
||
|
public const sbyte Vector4 = 32;
|
||
|
public const sbyte Quaternion = 33;
|
||
|
public const sbyte Color = 34;
|
||
|
public const sbyte Bounds = 35;
|
||
|
public const sbyte Rect = 36;
|
||
|
public const sbyte Int = 37;
|
||
|
public const sbyte Float = 38;
|
||
|
public const sbyte Double = 39;
|
||
|
}
|
||
|
|
||
|
// use ext instead of ArrayFormatter for extremely boostup performance.
|
||
|
// Layout: [extHeader, byteSize(integer), isLittlEendian(bool), bytes()]
|
||
|
|
||
|
// Used Ext:30~36
|
||
|
|
||
|
public abstract class UnsafeBlitFormatterBase<T> : IMessagePackFormatter<T[]>
|
||
|
where T : struct
|
||
|
{
|
||
|
protected abstract sbyte TypeCode { get; }
|
||
|
protected abstract int StructLength { get; }
|
||
|
protected abstract void CopySerializeUnsafe(ref T[] src, ref byte[] dest, int destOffset, int byteLength);
|
||
|
protected abstract void CopyDeserializeUnsafe(ref byte[] src, int srcOffset, ref T[] dest, int byteLength);
|
||
|
|
||
|
public unsafe int Serialize(ref byte[] bytes, int offset, T[] value, IFormatterResolver formatterResolver)
|
||
|
{
|
||
|
if (value == null) return MessagePackBinary.WriteNil(ref bytes, offset);
|
||
|
|
||
|
var startOffset = offset;
|
||
|
|
||
|
var byteLen = value.Length * StructLength;
|
||
|
|
||
|
offset += MessagePackBinary.WriteExtensionFormatHeader(ref bytes, offset, TypeCode, byteLen);
|
||
|
offset += MessagePackBinary.WriteInt32(ref bytes, offset, byteLen); // write original header(not array header)
|
||
|
offset += MessagePackBinary.WriteBoolean(ref bytes, offset, BitConverter.IsLittleEndian);
|
||
|
|
||
|
MessagePackBinary.EnsureCapacity(ref bytes, offset, byteLen);
|
||
|
CopySerializeUnsafe(ref value, ref bytes, offset, byteLen);
|
||
|
|
||
|
offset += byteLen;
|
||
|
return offset - startOffset;
|
||
|
}
|
||
|
|
||
|
public unsafe T[] Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize)
|
||
|
{
|
||
|
if (MessagePackBinary.IsNil(bytes, offset))
|
||
|
{
|
||
|
readSize = 1;
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
var startOffset = offset;
|
||
|
var header = MessagePackBinary.ReadExtensionFormatHeader(bytes, offset, out readSize);
|
||
|
offset += readSize;
|
||
|
|
||
|
if (header.TypeCode != TypeCode) throw new InvalidOperationException("Invalid typeCode.");
|
||
|
|
||
|
var byteLength = MessagePackBinary.ReadInt32(bytes, offset, out readSize);
|
||
|
offset += readSize;
|
||
|
|
||
|
var isLittleEndian = MessagePackBinary.ReadBoolean(bytes, offset, out readSize);
|
||
|
offset += readSize;
|
||
|
|
||
|
if (isLittleEndian != BitConverter.IsLittleEndian)
|
||
|
{
|
||
|
Array.Reverse(bytes, offset, byteLength);
|
||
|
}
|
||
|
|
||
|
var result = new T[byteLength / StructLength];
|
||
|
CopyDeserializeUnsafe(ref bytes, offset, ref result, byteLength);
|
||
|
offset += byteLength;
|
||
|
|
||
|
readSize = offset - startOffset;
|
||
|
return result;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public class Vector2ArrayBlitFormatter : UnsafeBlitFormatterBase<Vector2>
|
||
|
{
|
||
|
protected override sbyte TypeCode
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return ReservedUnityExtensionTypeCode.Vector2;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
protected override int StructLength
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return 8;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
protected override unsafe void CopySerializeUnsafe(ref Vector2[] src, ref byte[] dest, int destOffset, int byteLength)
|
||
|
{
|
||
|
fixed (void* pSrc = src)
|
||
|
fixed (void* pDest = &dest[destOffset])
|
||
|
{
|
||
|
MemoryUtil.SimpleMemoryCopy(pDest, pSrc, byteLength);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
protected override unsafe void CopyDeserializeUnsafe(ref byte[] src, int srcOffset, ref Vector2[] dest, int byteLength)
|
||
|
{
|
||
|
fixed (void* pSrc = &src[srcOffset])
|
||
|
fixed (void* pDest = dest)
|
||
|
{
|
||
|
MemoryUtil.SimpleMemoryCopy(pDest, pSrc, byteLength);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public class Vector3ArrayBlitFormatter : UnsafeBlitFormatterBase<Vector3>
|
||
|
{
|
||
|
protected override sbyte TypeCode
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return ReservedUnityExtensionTypeCode.Vector3;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
protected override int StructLength
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return 12;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
protected override unsafe void CopySerializeUnsafe(ref Vector3[] src, ref byte[] dest, int destOffset, int byteLength)
|
||
|
{
|
||
|
fixed (void* pSrc = src)
|
||
|
fixed (void* pDest = &dest[destOffset])
|
||
|
{
|
||
|
MemoryUtil.SimpleMemoryCopy(pDest, pSrc, byteLength);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
protected override unsafe void CopyDeserializeUnsafe(ref byte[] src, int srcOffset, ref Vector3[] dest, int byteLength)
|
||
|
{
|
||
|
fixed (void* pSrc = &src[srcOffset])
|
||
|
fixed (void* pDest = dest)
|
||
|
{
|
||
|
MemoryUtil.SimpleMemoryCopy(pDest, pSrc, byteLength);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public class Vector4ArrayBlitFormatter : UnsafeBlitFormatterBase<Vector4>
|
||
|
{
|
||
|
protected override sbyte TypeCode
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return ReservedUnityExtensionTypeCode.Vector4;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
protected override int StructLength
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return 16;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
protected override unsafe void CopySerializeUnsafe(ref Vector4[] src, ref byte[] dest, int destOffset, int byteLength)
|
||
|
{
|
||
|
fixed (void* pSrc = src)
|
||
|
fixed (void* pDest = &dest[destOffset])
|
||
|
{
|
||
|
MemoryUtil.SimpleMemoryCopy(pDest, pSrc, byteLength);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
protected override unsafe void CopyDeserializeUnsafe(ref byte[] src, int srcOffset, ref Vector4[] dest, int byteLength)
|
||
|
{
|
||
|
fixed (void* pSrc = &src[srcOffset])
|
||
|
fixed (void* pDest = dest)
|
||
|
{
|
||
|
MemoryUtil.SimpleMemoryCopy(pDest, pSrc, byteLength);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public class QuaternionArrayBlitFormatter : UnsafeBlitFormatterBase<Quaternion>
|
||
|
{
|
||
|
protected override sbyte TypeCode
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return ReservedUnityExtensionTypeCode.Quaternion;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
protected override int StructLength
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return 16;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
protected override unsafe void CopySerializeUnsafe(ref Quaternion[] src, ref byte[] dest, int destOffset, int byteLength)
|
||
|
{
|
||
|
fixed (void* pSrc = src)
|
||
|
fixed (void* pDest = &dest[destOffset])
|
||
|
{
|
||
|
MemoryUtil.SimpleMemoryCopy(pDest, pSrc, byteLength);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
protected override unsafe void CopyDeserializeUnsafe(ref byte[] src, int srcOffset, ref Quaternion[] dest, int byteLength)
|
||
|
{
|
||
|
fixed (void* pSrc = &src[srcOffset])
|
||
|
fixed (void* pDest = dest)
|
||
|
{
|
||
|
MemoryUtil.SimpleMemoryCopy(pDest, pSrc, byteLength);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public class ColorArrayBlitFormatter : UnsafeBlitFormatterBase<Color>
|
||
|
{
|
||
|
protected override sbyte TypeCode
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return ReservedUnityExtensionTypeCode.Color;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
protected override int StructLength
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return 16;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
protected override unsafe void CopySerializeUnsafe(ref Color[] src, ref byte[] dest, int destOffset, int byteLength)
|
||
|
{
|
||
|
fixed (void* pSrc = src)
|
||
|
fixed (void* pDest = &dest[destOffset])
|
||
|
{
|
||
|
MemoryUtil.SimpleMemoryCopy(pDest, pSrc, byteLength);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
protected override unsafe void CopyDeserializeUnsafe(ref byte[] src, int srcOffset, ref Color[] dest, int byteLength)
|
||
|
{
|
||
|
fixed (void* pSrc = &src[srcOffset])
|
||
|
fixed (void* pDest = dest)
|
||
|
{
|
||
|
MemoryUtil.SimpleMemoryCopy(pDest, pSrc, byteLength);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public class BoundsArrayBlitFormatter : UnsafeBlitFormatterBase<Bounds>
|
||
|
{
|
||
|
protected override sbyte TypeCode
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return ReservedUnityExtensionTypeCode.Bounds;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
protected override int StructLength
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return 24;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
protected override unsafe void CopySerializeUnsafe(ref Bounds[] src, ref byte[] dest, int destOffset, int byteLength)
|
||
|
{
|
||
|
fixed (void* pSrc = src)
|
||
|
fixed (void* pDest = &dest[destOffset])
|
||
|
{
|
||
|
MemoryUtil.SimpleMemoryCopy(pDest, pSrc, byteLength);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
protected override unsafe void CopyDeserializeUnsafe(ref byte[] src, int srcOffset, ref Bounds[] dest, int byteLength)
|
||
|
{
|
||
|
fixed (void* pSrc = &src[srcOffset])
|
||
|
fixed (void* pDest = dest)
|
||
|
{
|
||
|
MemoryUtil.SimpleMemoryCopy(pDest, pSrc, byteLength);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public class RectArrayBlitFormatter : UnsafeBlitFormatterBase<Rect>
|
||
|
{
|
||
|
protected override sbyte TypeCode
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return ReservedUnityExtensionTypeCode.Rect;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
protected override int StructLength
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return 16;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
protected override unsafe void CopySerializeUnsafe(ref Rect[] src, ref byte[] dest, int destOffset, int byteLength)
|
||
|
{
|
||
|
fixed (void* pSrc = src)
|
||
|
fixed (void* pDest = &dest[destOffset])
|
||
|
{
|
||
|
MemoryUtil.SimpleMemoryCopy(pDest, pSrc, byteLength);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
protected override unsafe void CopyDeserializeUnsafe(ref byte[] src, int srcOffset, ref Rect[] dest, int byteLength)
|
||
|
{
|
||
|
fixed (void* pSrc = &src[srcOffset])
|
||
|
fixed (void* pDest = dest)
|
||
|
{
|
||
|
MemoryUtil.SimpleMemoryCopy(pDest, pSrc, byteLength);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public class IntArrayBlitFormatter : UnsafeBlitFormatterBase<int>
|
||
|
{
|
||
|
protected override sbyte TypeCode { get { return ReservedUnityExtensionTypeCode.Int; } }
|
||
|
|
||
|
protected override int StructLength { get { return 4; } }
|
||
|
|
||
|
protected override void CopyDeserializeUnsafe(ref byte[] src, int srcOffset, ref int[] dest, int byteLength)
|
||
|
{
|
||
|
Buffer.BlockCopy(src, srcOffset, dest, 0, byteLength);
|
||
|
}
|
||
|
|
||
|
protected override void CopySerializeUnsafe(ref int[] src, ref byte[] dest, int destOffset, int byteLength)
|
||
|
{
|
||
|
Buffer.BlockCopy(src, 0, dest, destOffset, byteLength);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public class FloatArrayBlitFormatter : UnsafeBlitFormatterBase<float>
|
||
|
{
|
||
|
protected override sbyte TypeCode { get { return ReservedUnityExtensionTypeCode.Float; } }
|
||
|
|
||
|
protected override int StructLength { get { return 4; } }
|
||
|
|
||
|
protected override void CopyDeserializeUnsafe(ref byte[] src, int srcOffset, ref float[] dest, int byteLength)
|
||
|
{
|
||
|
Buffer.BlockCopy(src, srcOffset, dest, 0, byteLength);
|
||
|
}
|
||
|
|
||
|
protected override void CopySerializeUnsafe(ref float[] src, ref byte[] dest, int destOffset, int byteLength)
|
||
|
{
|
||
|
Buffer.BlockCopy(src, 0, dest, destOffset, byteLength);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public class DoubleArrayBlitFormatter : UnsafeBlitFormatterBase<double>
|
||
|
{
|
||
|
protected override sbyte TypeCode { get { return ReservedUnityExtensionTypeCode.Double; } }
|
||
|
|
||
|
protected override int StructLength { get { return 8; } }
|
||
|
|
||
|
protected override void CopyDeserializeUnsafe(ref byte[] src, int srcOffset, ref double[] dest, int byteLength)
|
||
|
{
|
||
|
Buffer.BlockCopy(src, srcOffset, dest, 0, byteLength);
|
||
|
}
|
||
|
|
||
|
protected override void CopySerializeUnsafe(ref double[] src, ref byte[] dest, int destOffset, int byteLength)
|
||
|
{
|
||
|
Buffer.BlockCopy(src, 0, dest, destOffset, byteLength);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#endif
|