AkiraPixelWind/Assets/Scripts/Main/Luban/LubanLib/ByteBuf.cs

1569 lines
45 KiB
C#
Raw Permalink Normal View History

2022-12-29 18:20:40 +08:00
using System;
using System.Diagnostics.CodeAnalysis;
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Text;
namespace Bright.Serialization
{
public enum EDeserializeError
{
OK,
NOT_ENOUGH,
EXCEED_SIZE,
// UNMARSHAL_ERR,
}
public class SerializationException : Exception
{
public SerializationException() { }
public SerializationException(string msg) : base(msg) { }
public SerializationException(string message, Exception innerException) : base(message, innerException)
{
}
}
public readonly struct SegmentSaveState
{
public SegmentSaveState(int readerIndex, int writerIndex)
{
ReaderIndex = readerIndex;
WriterIndex = writerIndex;
}
public int ReaderIndex { get; }
public int WriterIndex { get; }
}
public sealed class ByteBuf : ICloneable, IEquatable<ByteBuf>
{
public ByteBuf()
{
Bytes = Array.Empty<byte>();
ReaderIndex = WriterIndex = 0;
}
public ByteBuf(int capacity)
{
Bytes = capacity > 0 ? new byte[capacity] : Array.Empty<byte>();
ReaderIndex = 0;
WriterIndex = 0;
}
public ByteBuf(byte[] bytes)
{
Bytes = bytes;
ReaderIndex = 0;
WriterIndex = Capacity;
}
public ByteBuf(byte[] bytes, int readIndex, int writeIndex)
{
Bytes = bytes;
ReaderIndex = readIndex;
WriterIndex = writeIndex;
}
public ByteBuf(int capacity, Action<ByteBuf> releaser) : this(capacity)
{
_releaser = releaser;
}
public static ByteBuf Wrap(byte[] bytes)
{
return new ByteBuf(bytes, 0, bytes.Length);
}
public void Replace(byte[] bytes)
{
Bytes = bytes;
ReaderIndex = 0;
WriterIndex = Capacity;
}
public void Replace(byte[] bytes, int beginPos, int endPos)
{
Bytes = bytes;
ReaderIndex = beginPos;
WriterIndex = endPos;
}
public int ReaderIndex { get; set; }
public int WriterIndex { get; set; }
private readonly Action<ByteBuf> _releaser;
public int Capacity => Bytes.Length;
public int Size { get { return WriterIndex - ReaderIndex; } }
public bool Empty => WriterIndex <= ReaderIndex;
public bool NotEmpty => WriterIndex > ReaderIndex;
public void AddWriteIndex(int add)
{
WriterIndex += add;
}
public void AddReadIndex(int add)
{
ReaderIndex += add;
}
#pragma warning disable CA1819 // 属性不应返回数组
public byte[] Bytes { get; private set; }
#pragma warning restore CA1819 // 属性不应返回数组
public byte[] CopyData()
{
var n = Remaining;
if (n > 0)
{
var arr = new byte[n];
Buffer.BlockCopy(Bytes, ReaderIndex, arr, 0, n);
return arr;
}
else
{
return Array.Empty<byte>();
}
}
public int Remaining { get { return WriterIndex - ReaderIndex; } }
public void DiscardReadBytes()
{
WriterIndex -= ReaderIndex;
Array.Copy(Bytes, ReaderIndex, Bytes, 0, WriterIndex);
ReaderIndex = 0;
}
public int NotCompactWritable { get { return Capacity - WriterIndex; } }
public void WriteBytesWithoutSize(byte[] bs)
{
WriteBytesWithoutSize(bs, 0, bs.Length);
}
public void WriteBytesWithoutSize(byte[] bs, int offset, int len)
{
EnsureWrite(len);
Buffer.BlockCopy(bs, offset, Bytes, WriterIndex, len);
WriterIndex += len;
}
public void Clear()
{
ReaderIndex = WriterIndex = 0;
}
private const int MIN_CAPACITY = 16;
private static int PropSize(int initSize, int needSize)
{
for (int i = Math.Max(initSize, MIN_CAPACITY); ; i <<= 1)
{
if (i >= needSize)
{
return i;
}
}
}
private void EnsureWrite0(int size)
{
var needSize = WriterIndex + size - ReaderIndex;
if (needSize < Capacity)
{
WriterIndex -= ReaderIndex;
Array.Copy(Bytes, ReaderIndex, Bytes, 0, WriterIndex);
ReaderIndex = 0;
}
else
{
int newCapacity = PropSize(Capacity, needSize);
var newBytes = new byte[newCapacity];
WriterIndex -= ReaderIndex;
Buffer.BlockCopy(Bytes, ReaderIndex, newBytes, 0, WriterIndex);
ReaderIndex = 0;
Bytes = newBytes;
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void EnsureWrite(int size)
{
if (WriterIndex + size > Capacity)
{
EnsureWrite0(size);
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void EnsureRead(int size)
{
if (ReaderIndex + size > WriterIndex)
{
throw new SerializationException();
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private bool CanRead(int size)
{
return (ReaderIndex + size <= WriterIndex);
}
public void Append(byte x)
{
EnsureWrite(1);
Bytes[WriterIndex++] = x;
}
public void WriteBool(bool b)
{
EnsureWrite(1);
Bytes[WriterIndex++] = (byte)(b ? 1 : 0);
}
public bool ReadBool()
{
EnsureRead(1);
return Bytes[ReaderIndex++] != 0;
}
public void WriteByte(byte x)
{
EnsureWrite(1);
Bytes[WriterIndex++] = x;
}
public byte ReadByte()
{
EnsureRead(1);
return Bytes[ReaderIndex++];
}
public void WriteShort(short x)
{
if (x >= 0)
{
if (x < 0x80)
{
EnsureWrite(1);
Bytes[WriterIndex++] = (byte)x;
return;
}
else if (x < 0x4000)
{
EnsureWrite(2);
Bytes[WriterIndex + 1] = (byte)x;
Bytes[WriterIndex] = (byte)((x >> 8) | 0x80);
WriterIndex += 2;
return;
}
}
EnsureWrite(3);
Bytes[WriterIndex] = 0xff;
Bytes[WriterIndex + 2] = (byte)x;
Bytes[WriterIndex + 1] = (byte)(x >> 8);
WriterIndex += 3;
}
public short ReadShort()
{
EnsureRead(1);
int h = Bytes[ReaderIndex];
if (h < 0x80)
{
ReaderIndex++;
return (short)h;
}
else if (h < 0xc0)
{
EnsureRead(2);
int x = ((h & 0x3f) << 8) | Bytes[ReaderIndex + 1];
ReaderIndex += 2;
return (short)x;
}
else if ((h == 0xff))
{
EnsureRead(3);
int x = (Bytes[ReaderIndex + 1] << 8) | Bytes[ReaderIndex + 2];
ReaderIndex += 3;
return (short)x;
}
else
{
throw new SerializationException();
}
}
public short ReadFshort()
{
EnsureRead(2);
short x;
#if CPU_SUPPORT_MEMORY_NOT_ALIGN
unsafe
{
fixed (byte* b = &Bytes[ReaderIndex])
{
x = *(short*)b;
}
}
#else
x = (short)((Bytes[ReaderIndex + 1] << 8) | Bytes[ReaderIndex]);
#endif
ReaderIndex += 2;
return x;
}
public void WriteFshort(short x)
{
EnsureWrite(2);
#if CPU_SUPPORT_MEMORY_NOT_ALIGN
unsafe
{
fixed (byte* b = &Bytes[WriterIndex])
{
*(short*)b = x;
}
}
#else
Bytes[WriterIndex] = (byte)x;
Bytes[WriterIndex + 1] = (byte)(x >> 8);
#endif
WriterIndex += 2;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void WriteInt(int x)
{
WriteUint((uint)x);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public int ReadInt()
{
return (int)ReadUint();
}
public void WriteUint(uint x)
{
// 如果有修改,记得也把 EndWriteSegment改了
// 0 111 1111
if (x < 0x80)
{
EnsureWrite(1);
Bytes[WriterIndex++] = (byte)x;
}
else if (x < 0x4000) // 10 11 1111, -
{
EnsureWrite(2);
Bytes[WriterIndex + 1] = (byte)x;
Bytes[WriterIndex] = (byte)((x >> 8) | 0x80);
WriterIndex += 2;
}
else if (x < 0x200000) // 110 1 1111, -,-
{
EnsureWrite(3);
Bytes[WriterIndex + 2] = (byte)x;
Bytes[WriterIndex + 1] = (byte)(x >> 8);
Bytes[WriterIndex] = (byte)((x >> 16) | 0xc0);
WriterIndex += 3;
}
else if (x < 0x10000000) // 1110 1111,-,-,-
{
EnsureWrite(4);
Bytes[WriterIndex + 3] = (byte)x;
Bytes[WriterIndex + 2] = (byte)(x >> 8);
Bytes[WriterIndex + 1] = (byte)(x >> 16);
Bytes[WriterIndex] = (byte)((x >> 24) | 0xe0);
WriterIndex += 4;
}
else
{
EnsureWrite(5);
Bytes[WriterIndex] = 0xf0;
Bytes[WriterIndex + 4] = (byte)x;
Bytes[WriterIndex + 3] = (byte)(x >> 8);
Bytes[WriterIndex + 2] = (byte)(x >> 16);
Bytes[WriterIndex + 1] = (byte)(x >> 24);
WriterIndex += 5;
}
}
public uint ReadUint()
{
///
/// 警告! 如有修改,记得调整 TryDeserializeInplaceOctets
EnsureRead(1);
uint h = Bytes[ReaderIndex];
if (h < 0x80)
{
ReaderIndex++;
return h;
}
else if (h < 0xc0)
{
EnsureRead(2);
uint x = ((h & 0x3f) << 8) | Bytes[ReaderIndex + 1];
ReaderIndex += 2;
return x;
}
else if (h < 0xe0)
{
EnsureRead(3);
uint x = ((h & 0x1f) << 16) | ((uint)Bytes[ReaderIndex + 1] << 8) | Bytes[ReaderIndex + 2];
ReaderIndex += 3;
return x;
}
else if (h < 0xf0)
{
EnsureRead(4);
uint x = ((h & 0x0f) << 24) | ((uint)Bytes[ReaderIndex + 1] << 16) | ((uint)Bytes[ReaderIndex + 2] << 8) | Bytes[ReaderIndex + 3];
ReaderIndex += 4;
return x;
}
else
{
EnsureRead(5);
uint x = ((uint)Bytes[ReaderIndex + 1] << 24) | ((uint)(Bytes[ReaderIndex + 2] << 16)) | ((uint)Bytes[ReaderIndex + 3] << 8) | Bytes[ReaderIndex + 4];
ReaderIndex += 5;
return x;
}
}
public unsafe void WriteUint_Unsafe(uint x)
{
// 0 111 1111
if (x < 0x80)
{
EnsureWrite(1);
Bytes[WriterIndex++] = (byte)(x << 1);
}
else if (x < 0x4000)// 10 11 1111, -
{
EnsureWrite(2);
fixed (byte* wb = &Bytes[WriterIndex])
{
*(uint*)(wb) = (x << 2 | 0b01);
}
WriterIndex += 2;
}
else if (x < 0x200000) // 110 1 1111, -,-
{
EnsureWrite(3);
fixed (byte* wb = &Bytes[WriterIndex])
{
*(uint*)(wb) = (x << 3 | 0b011);
}
WriterIndex += 3;
}
else if (x < 0x10000000) // 1110 1111,-,-,-
{
EnsureWrite(4);
fixed (byte* wb = &Bytes[WriterIndex])
{
*(uint*)(wb) = (x << 4 | 0b0111);
}
WriterIndex += 4;
}
else
{
EnsureWrite(5);
fixed (byte* wb = &Bytes[WriterIndex])
{
*(uint*)(wb) = (x << 5 | 0b01111);
}
WriterIndex += 5;
}
}
public unsafe uint ReadUint_Unsafe()
{
///
/// 警告! 如有修改,记得调整 TryDeserializeInplaceOctets
EnsureRead(1);
uint h = Bytes[ReaderIndex];
if ((h & 0b1) == 0b0)
{
ReaderIndex++;
return (h >> 1);
}
else if ((h & 0b11) == 0b01)
{
EnsureRead(2);
fixed (byte* rb = &Bytes[ReaderIndex])
{
ReaderIndex += 2;
return (*(uint*)rb) >> 2;
}
}
else if ((h & 0b111) == 0b011)
{
EnsureRead(3);
fixed (byte* rb = &Bytes[ReaderIndex])
{
ReaderIndex += 3;
return (*(uint*)rb) >> 3;
}
}
else if ((h & 0b1111) == 0b0111)
{
EnsureRead(4);
fixed (byte* rb = &Bytes[ReaderIndex])
{
ReaderIndex += 4;
return (*(uint*)rb) >> 4;
}
}
else
{
EnsureRead(5);
fixed (byte* rb = &Bytes[ReaderIndex])
{
ReaderIndex += 5;
return (*(uint*)rb) >> 5;
}
}
}
public int ReadFint()
{
EnsureRead(4);
int x;
#if CPU_SUPPORT_MEMORY_NOT_ALIGN
unsafe
{
fixed (byte* b = &Bytes[ReaderIndex])
{
x = *(int*)b;
}
}
#else
x = (Bytes[ReaderIndex + 3] << 24) | (Bytes[ReaderIndex + 2] << 16) | (Bytes[ReaderIndex + 1] << 8) | (Bytes[ReaderIndex]);
#endif
ReaderIndex += 4;
return x;
}
public void WriteFint(int x)
{
EnsureWrite(4);
#if CPU_SUPPORT_MEMORY_NOT_ALIGN
unsafe
{
fixed (byte* b = &Bytes[WriterIndex])
{
*(int*)b = x;
}
}
#else
Bytes[WriterIndex] = (byte)x;
Bytes[WriterIndex + 1] = (byte)(x >> 8);
Bytes[WriterIndex + 2] = (byte)(x >> 16);
Bytes[WriterIndex + 3] = (byte)(x >> 24);
#endif
WriterIndex += 4;
}
public int ReadFint_Safe()
{
EnsureRead(4);
int x;
x = (Bytes[ReaderIndex + 3] << 24) | (Bytes[ReaderIndex + 2] << 16) | (Bytes[ReaderIndex + 1] << 8) | (Bytes[ReaderIndex]);
ReaderIndex += 4;
return x;
}
public void WriteFint_Safe(int x)
{
EnsureWrite(4);
Bytes[WriterIndex] = (byte)x;
Bytes[WriterIndex + 1] = (byte)(x >> 8);
Bytes[WriterIndex + 2] = (byte)(x >> 16);
Bytes[WriterIndex + 3] = (byte)(x >> 24);
WriterIndex += 4;
}
public void WriteLong(long x)
{
WriteUlong((ulong)x);
}
public long ReadLong()
{
return (long)ReadUlong();
}
public void WriteNumberAsLong(double x)
{
WriteLong((long)x);
}
public double ReadLongAsNumber()
{
return ReadLong();
}
private void WriteUlong(ulong x)
{
// 0 111 1111
if (x < 0x80)
{
EnsureWrite(1);
Bytes[WriterIndex++] = (byte)x;
}
else if (x < 0x4000) // 10 11 1111, -
{
EnsureWrite(2);
Bytes[WriterIndex + 1] = (byte)x;
Bytes[WriterIndex] = (byte)((x >> 8) | 0x80);
WriterIndex += 2;
}
else if (x < 0x200000) // 110 1 1111, -,-
{
EnsureWrite(3);
Bytes[WriterIndex + 2] = (byte)x;
Bytes[WriterIndex + 1] = (byte)(x >> 8);
Bytes[WriterIndex] = (byte)((x >> 16) | 0xc0);
WriterIndex += 3;
}
else if (x < 0x10000000) // 1110 1111,-,-,-
{
EnsureWrite(4);
Bytes[WriterIndex + 3] = (byte)x;
Bytes[WriterIndex + 2] = (byte)(x >> 8);
Bytes[WriterIndex + 1] = (byte)(x >> 16);
Bytes[WriterIndex] = (byte)((x >> 24) | 0xe0);
WriterIndex += 4;
}
else if (x < 0x800000000L) // 1111 0xxx,-,-,-,-
{
EnsureWrite(5);
Bytes[WriterIndex + 4] = (byte)x;
Bytes[WriterIndex + 3] = (byte)(x >> 8);
Bytes[WriterIndex + 2] = (byte)(x >> 16);
Bytes[WriterIndex + 1] = (byte)(x >> 24);
Bytes[WriterIndex] = (byte)((x >> 32) | 0xf0);
WriterIndex += 5;
}
else if (x < 0x40000000000L) // 1111 10xx,
{
EnsureWrite(6);
Bytes[WriterIndex + 5] = (byte)x;
Bytes[WriterIndex + 4] = (byte)(x >> 8);
Bytes[WriterIndex + 3] = (byte)(x >> 16);
Bytes[WriterIndex + 2] = (byte)(x >> 24);
Bytes[WriterIndex + 1] = (byte)(x >> 32);
Bytes[WriterIndex] = (byte)((x >> 40) | 0xf8);
WriterIndex += 6;
}
else if (x < 0x200000000000L) // 1111 110x,
{
EnsureWrite(7);
Bytes[WriterIndex + 6] = (byte)x;
Bytes[WriterIndex + 5] = (byte)(x >> 8);
Bytes[WriterIndex + 4] = (byte)(x >> 16);
Bytes[WriterIndex + 3] = (byte)(x >> 24);
Bytes[WriterIndex + 2] = (byte)(x >> 32);
Bytes[WriterIndex + 1] = (byte)(x >> 40);
Bytes[WriterIndex] = (byte)((x >> 48) | 0xfc);
WriterIndex += 7;
}
else if (x < 0x100000000000000L) // 1111 1110
{
EnsureWrite(8);
Bytes[WriterIndex + 7] = (byte)x;
Bytes[WriterIndex + 6] = (byte)(x >> 8);
Bytes[WriterIndex + 5] = (byte)(x >> 16);
Bytes[WriterIndex + 4] = (byte)(x >> 24);
Bytes[WriterIndex + 3] = (byte)(x >> 32);
Bytes[WriterIndex + 2] = (byte)(x >> 40);
Bytes[WriterIndex + 1] = (byte)(x >> 48);
Bytes[WriterIndex] = 0xfe;
WriterIndex += 8;
}
else // 1111 1111
{
EnsureWrite(9);
Bytes[WriterIndex] = 0xff;
Bytes[WriterIndex + 8] = (byte)x;
Bytes[WriterIndex + 7] = (byte)(x >> 8);
Bytes[WriterIndex + 6] = (byte)(x >> 16);
Bytes[WriterIndex + 5] = (byte)(x >> 24);
Bytes[WriterIndex + 4] = (byte)(x >> 32);
Bytes[WriterIndex + 3] = (byte)(x >> 40);
Bytes[WriterIndex + 2] = (byte)(x >> 48);
Bytes[WriterIndex + 1] = (byte)(x >> 56);
WriterIndex += 9;
}
}
public ulong ReadUlong()
{
EnsureRead(1);
uint h = Bytes[ReaderIndex];
if (h < 0x80)
{
ReaderIndex++;
return h;
}
else if (h < 0xc0)
{
EnsureRead(2);
uint x = ((h & 0x3f) << 8) | Bytes[ReaderIndex + 1];
ReaderIndex += 2;
return x;
}
else if (h < 0xe0)
{
EnsureRead(3);
uint x = ((h & 0x1f) << 16) | ((uint)Bytes[ReaderIndex + 1] << 8) | Bytes[ReaderIndex + 2];
ReaderIndex += 3;
return x;
}
else if (h < 0xf0)
{
EnsureRead(4);
uint x = ((h & 0x0f) << 24) | ((uint)Bytes[ReaderIndex + 1] << 16) | ((uint)Bytes[ReaderIndex + 2] << 8) | Bytes[ReaderIndex + 3];
ReaderIndex += 4;
return x;
}
else if (h < 0xf8)
{
EnsureRead(5);
uint xl = ((uint)Bytes[ReaderIndex + 1] << 24) | ((uint)(Bytes[ReaderIndex + 2] << 16)) | ((uint)Bytes[ReaderIndex + 3] << 8) | (Bytes[ReaderIndex + 4]);
uint xh = h & 0x07;
ReaderIndex += 5;
return ((ulong)xh << 32) | xl;
}
else if (h < 0xfc)
{
EnsureRead(6);
uint xl = ((uint)Bytes[ReaderIndex + 2] << 24) | ((uint)(Bytes[ReaderIndex + 3] << 16)) | ((uint)Bytes[ReaderIndex + 4] << 8) | (Bytes[ReaderIndex + 5]);
uint xh = ((h & 0x03) << 8) | Bytes[ReaderIndex + 1];
ReaderIndex += 6;
return ((ulong)xh << 32) | xl;
}
else if (h < 0xfe)
{
EnsureRead(7);
uint xl = ((uint)Bytes[ReaderIndex + 3] << 24) | ((uint)(Bytes[ReaderIndex + 4] << 16)) | ((uint)Bytes[ReaderIndex + 5] << 8) | (Bytes[ReaderIndex + 6]);
uint xh = ((h & 0x01) << 16) | ((uint)Bytes[ReaderIndex + 1] << 8) | Bytes[ReaderIndex + 2];
ReaderIndex += 7;
return ((ulong)xh << 32) | xl;
}
else if (h < 0xff)
{
EnsureRead(8);
uint xl = ((uint)Bytes[ReaderIndex + 4] << 24) | ((uint)(Bytes[ReaderIndex + 5] << 16)) | ((uint)Bytes[ReaderIndex + 6] << 8) | (Bytes[ReaderIndex + 7]);
uint xh = /*((h & 0x01) << 24) |*/ ((uint)Bytes[ReaderIndex + 1] << 16) | ((uint)Bytes[ReaderIndex + 2] << 8) | Bytes[ReaderIndex + 3];
ReaderIndex += 8;
return ((ulong)xh << 32) | xl;
}
else
{
EnsureRead(9);
uint xl = ((uint)Bytes[ReaderIndex + 5] << 24) | ((uint)(Bytes[ReaderIndex + 6] << 16)) | ((uint)Bytes[ReaderIndex + 7] << 8) | (Bytes[ReaderIndex + 8]);
uint xh = ((uint)Bytes[ReaderIndex + 1] << 24) | ((uint)Bytes[ReaderIndex + 2] << 16) | ((uint)Bytes[ReaderIndex + 3] << 8) | Bytes[ReaderIndex + 4];
ReaderIndex += 9;
return ((ulong)xh << 32) | xl;
}
}
public void WriteFlong(long x)
{
EnsureWrite(8);
#if CPU_SUPPORT_MEMORY_NOT_ALIGN
unsafe
{
fixed (byte* b = &Bytes[WriterIndex])
{
*(long*)b = x;
}
}
#else
Bytes[WriterIndex] = (byte)x;
Bytes[WriterIndex + 1] = (byte)(x >> 8);
Bytes[WriterIndex + 2] = (byte)(x >> 16);
Bytes[WriterIndex + 3] = (byte)(x >> 24);
Bytes[WriterIndex + 4] = (byte)(x >> 32);
Bytes[WriterIndex + 5] = (byte)(x >> 40);
Bytes[WriterIndex + 6] = (byte)(x >> 48);
Bytes[WriterIndex + 7] = (byte)(x >> 56);
#endif
WriterIndex += 8;
}
public long ReadFlong()
{
EnsureRead(8);
long x;
#if CPU_SUPPORT_MEMORY_NOT_ALIGN
unsafe
{
fixed (byte* b = &Bytes[ReaderIndex])
{
x = *(long*)b;
}
}
#else
int xl = (Bytes[ReaderIndex + 3] << 24) | ((Bytes[ReaderIndex + 2] << 16)) | (Bytes[ReaderIndex + 1] << 8) | (Bytes[ReaderIndex]);
int xh = (Bytes[ReaderIndex + 7] << 24) | (Bytes[ReaderIndex + 6] << 16) | (Bytes[ReaderIndex + 5] << 8) | Bytes[ReaderIndex + 4];
x = ((long)xh << 32) | (long)xl;
#endif
ReaderIndex += 8;
return x;
}
private static unsafe void Copy8(byte* dst, byte* src)
{
dst[0] = src[0];
dst[1] = src[1];
dst[2] = src[2];
dst[3] = src[3];
dst[4] = src[4];
dst[5] = src[5];
dst[6] = src[6];
dst[7] = src[7];
}
private static unsafe void Copy4(byte* dst, byte* src)
{
dst[0] = src[0];
dst[1] = src[1];
dst[2] = src[2];
dst[3] = src[3];
}
//const bool isLittleEndian = true;
public void WriteFloat(float x)
{
EnsureWrite(4);
unsafe
{
fixed (byte* b = &Bytes[WriterIndex])
{
#if !CPU_SUPPORT_MEMORY_NOT_ALIGN
if ((long)b % 4 == 0)
{
*(float*)b = x;
}
else
{
Copy4(b, (byte*)&x);
}
#else
*(float*)b = x;
#endif
}
}
//if (!BitConverter.IsLittleEndian)
//{
// Array.Reverse(data, endPos, 4);
//}
WriterIndex += 4;
}
public float ReadFloat()
{
EnsureRead(4);
//if (!BitConverter.IsLittleEndian)
//{
// Array.Reverse(data, beginPos, 4);
//}
float x;
unsafe
{
fixed (byte* b = &Bytes[ReaderIndex])
{
#if !CPU_SUPPORT_MEMORY_NOT_ALIGN
if ((long)b % 4 == 0)
{
x = *(float*)b;
}
else
{
*((int*)&x) = (b[0]) | (b[1] << 8) | (b[2] << 16) | (b[3] << 24);
}
#else
x = *(float*)b;
#endif
}
}
ReaderIndex += 4;
return x;
}
public void WriteDouble(double x)
{
EnsureWrite(8);
unsafe
{
fixed (byte* b = &Bytes[WriterIndex])
{
#if !CPU_SUPPORT_MEMORY_NOT_ALIGN
if ((long)b % 8 == 0)
{
*(double*)b = x;
}
else
{
Copy8(b, (byte*)&x);
}
#else
*(double*)b = x;
#endif
}
//if (!BitConverter.IsLittleEndian)
//{
// Array.Reverse(data, endPos, 8);
//}
}
WriterIndex += 8;
}
public double ReadDouble()
{
EnsureRead(8);
//if (!BitConverter.IsLittleEndian)
//{
// Array.Reverse(data, beginPos, 8);
//}
double x;
unsafe
{
fixed (byte* b = &Bytes[ReaderIndex])
{
#if !CPU_SUPPORT_MEMORY_NOT_ALIGN
if ((long)b % 8 == 0)
{
x = *(double*)b;
}
else
{
int low = (b[0]) | (b[1] << 8) | (b[2] << 16) | (b[3] << 24);
int high = (b[4]) | (b[5] << 8) | (b[6] << 16) | (b[7] << 24);
*((long*)&x) = ((long)high << 32) | (uint)low;
}
#else
x = *(double*)b;
#endif
}
}
ReaderIndex += 8;
return x;
}
public void WriteSize(int n)
{
WriteUint((uint)n);
}
public int ReadSize()
{
return (int)ReadUint();
}
// marshal int
// n -> (n << 1) ^ (n >> 31)
// Read
// (x >>> 1) ^ ((x << 31) >> 31)
// (x >>> 1) ^ -(n&1)
public void WriteSint(int x)
{
WriteUint(((uint)x << 1) ^ ((uint)x >> 31));
}
public int ReadSint()
{
uint x = ReadUint();
return (int)((x >> 1) ^ ((x & 1) << 31));
}
// marshal long
// n -> (n << 1) ^ (n >> 63)
// Read
// (x >>> 1) ^((x << 63) >> 63)
// (x >>> 1) ^ -(n&1L)
public void WriteSlong(long x)
{
WriteUlong(((ulong)x << 1) ^ ((ulong)x >> 63));
}
public long ReadSlong()
{
long x = ReadLong();
return ((long)((ulong)x >> 1) ^ ((x & 1) << 63));
}
public void WriteString(string x)
{
var n = x != null ? Encoding.UTF8.GetByteCount(x) : 0;
WriteSize(n);
if (n > 0)
{
EnsureWrite(n);
Encoding.UTF8.GetBytes(x, 0, x.Length, Bytes, WriterIndex);
WriterIndex += n;
}
}
// byte[], [start, end)
public static Func<byte[], int, int, string> StringCacheFinder { get; set; }
public string ReadString()
{
var n = ReadSize();
if (n > 0)
{
EnsureRead(n);
string s;
if (StringCacheFinder == null)
{
s = Encoding.UTF8.GetString(Bytes, ReaderIndex, n);
}
else
{
// 只缓存比较小的字符串
s = StringCacheFinder(Bytes, ReaderIndex, n);
}
ReaderIndex += n;
return s;
}
else
{
return string.Empty;
}
}
public void WriteBytes(byte[] x)
{
var n = x != null ? x.Length : 0;
WriteSize(n);
if (n > 0)
{
EnsureWrite(n);
x.CopyTo(Bytes, WriterIndex);
WriterIndex += n;
}
}
public byte[] ReadBytes()
{
var n = ReadSize();
if (n > 0)
{
EnsureRead(n);
var x = new byte[n];
Buffer.BlockCopy(Bytes, ReaderIndex, x, 0, n);
ReaderIndex += n;
return x;
}
else
{
return Array.Empty<byte>();
}
}
// 以下是一些特殊类型
public void WriteComplex(Complex x)
{
WriteDouble(x.Real);
WriteDouble(x.Imaginary);
}
public Complex ReadComplex()
{
var x = ReadDouble();
var y = ReadDouble();
return new Complex(x, y);
}
public void WriteVector2(Vector2 x)
{
WriteFloat(x.X);
WriteFloat(x.Y);
}
public Vector2 ReadVector2()
{
float x = ReadFloat();
float y = ReadFloat();
return new Vector2(x, y);
}
public void WriteVector3(Vector3 x)
{
WriteFloat(x.X);
WriteFloat(x.Y);
WriteFloat(x.Z);
}
public Vector3 ReadVector3()
{
float x = ReadFloat();
float y = ReadFloat();
float z = ReadFloat();
return new Vector3(x, y, z);
}
public void WriteVector4(Vector4 x)
{
WriteFloat(x.X);
WriteFloat(x.Y);
WriteFloat(x.Z);
WriteFloat(x.W);
}
public Vector4 ReadVector4()
{
float x = ReadFloat();
float y = ReadFloat();
float z = ReadFloat();
float w = ReadFloat();
return new Vector4(x, y, z, w);
}
public void WriteQuaternion(Quaternion x)
{
WriteFloat(x.X);
WriteFloat(x.Y);
WriteFloat(x.Z);
WriteFloat(x.W);
}
public Quaternion ReadQuaternion()
{
float x = ReadFloat();
float y = ReadFloat();
float z = ReadFloat();
float w = ReadFloat();
return new Quaternion(x, y, z, w);
}
public void WriteMatrix4x4(Matrix4x4 x)
{
WriteFloat(x.M11);
WriteFloat(x.M12);
WriteFloat(x.M13);
WriteFloat(x.M14);
WriteFloat(x.M21);
WriteFloat(x.M22);
WriteFloat(x.M23);
WriteFloat(x.M24);
WriteFloat(x.M31);
WriteFloat(x.M32);
WriteFloat(x.M33);
WriteFloat(x.M34);
WriteFloat(x.M41);
WriteFloat(x.M42);
WriteFloat(x.M43);
WriteFloat(x.M44);
}
public Matrix4x4 ReadMatrix4x4()
{
float m11 = ReadFloat();
float m12 = ReadFloat();
float m13 = ReadFloat();
float m14 = ReadFloat();
float m21 = ReadFloat();
float m22 = ReadFloat();
float m23 = ReadFloat();
float m24 = ReadFloat();
float m31 = ReadFloat();
float m32 = ReadFloat();
float m33 = ReadFloat();
float m34 = ReadFloat();
float m41 = ReadFloat();
float m42 = ReadFloat();
float m43 = ReadFloat();
float m44 = ReadFloat();
return new Matrix4x4(m11, m12, m13, m14,
m21, m22, m23, m24,
m31, m32, m33, m34,
m41, m42, m43, m44);
}
internal void SkipBytes()
{
int n = ReadSize();
EnsureRead(n);
ReaderIndex += n;
}
public void WriteByteBufWithSize(ByteBuf o)
{
int n = o.Size;
if (n > 0)
{
WriteSize(n);
WriteBytesWithoutSize(o.Bytes, o.ReaderIndex, n);
}
else
{
WriteByte(0);
}
}
public void WriteByteBufWithoutSize(ByteBuf o)
{
int n = o.Size;
if (n > 0)
{
WriteBytesWithoutSize(o.Bytes, o.ReaderIndex, n);
}
}
public bool TryReadByte(out byte x)
{
if (CanRead(1))
{
x = Bytes[ReaderIndex++];
return true;
}
else
{
x = 0;
return false;
}
}
public EDeserializeError TryDeserializeInplaceByteBuf(int maxSize, ByteBuf inplaceTempBody)
{
//if (!CanRead(1)) { return EDeserializeError.NOT_ENOUGH; }
int oldReadIndex = ReaderIndex;
bool commit = false;
try
{
int n;
int h = Bytes[ReaderIndex];
if (h < 0x80)
{
ReaderIndex++;
n = h;
}
else if (h < 0xc0)
{
if (!CanRead(2)) { return EDeserializeError.NOT_ENOUGH; }
n = ((h & 0x3f) << 8) | Bytes[ReaderIndex + 1];
ReaderIndex += 2;
}
else if (h < 0xe0)
{
if (!CanRead(3)) { return EDeserializeError.NOT_ENOUGH; }
n = ((h & 0x1f) << 16) | (Bytes[ReaderIndex + 1] << 8) | Bytes[ReaderIndex + 2];
ReaderIndex += 3;
}
else if (h < 0xf0)
{
if (!CanRead(4)) { return EDeserializeError.NOT_ENOUGH; }
n = ((h & 0x0f) << 24) | (Bytes[ReaderIndex + 1] << 16) | (Bytes[ReaderIndex + 2] << 8) | Bytes[ReaderIndex + 3];
ReaderIndex += 4;
}
else
{
return EDeserializeError.EXCEED_SIZE;
}
if (n > maxSize)
{
return EDeserializeError.EXCEED_SIZE;
}
if (Remaining < n)
{
return EDeserializeError.NOT_ENOUGH;
}
int inplaceReadIndex = ReaderIndex;
ReaderIndex += n;
inplaceTempBody.Replace(Bytes, inplaceReadIndex, ReaderIndex);
commit = true;
}
finally
{
if (!commit)
{
ReaderIndex = oldReadIndex;
}
}
return EDeserializeError.OK;
}
public void WriteRawTag(byte b1)
{
EnsureWrite(1);
Bytes[WriterIndex++] = b1;
}
public void WriteRawTag(byte b1, byte b2)
{
EnsureWrite(2);
Bytes[WriterIndex] = b1;
Bytes[WriterIndex + 1] = b2;
WriterIndex += 2;
}
public void WriteRawTag(byte b1, byte b2, byte b3)
{
EnsureWrite(3);
Bytes[WriterIndex] = b1;
Bytes[WriterIndex + 1] = b2;
Bytes[WriterIndex + 2] = b3;
WriterIndex += 3;
}
#region segment
public void BeginWriteSegment(out int oldSize)
{
oldSize = Size;
EnsureWrite(1);
WriterIndex += 1;
}
public void EndWriteSegment(int oldSize)
{
int startPos = ReaderIndex + oldSize;
int segmentSize = WriterIndex - startPos - 1;
// 0 111 1111
if (segmentSize < 0x80)
{
Bytes[startPos] = (byte)segmentSize;
}
else if (segmentSize < 0x4000) // 10 11 1111, -
{
EnsureWrite(1);
Bytes[WriterIndex] = Bytes[startPos + 1];
Bytes[startPos + 1] = (byte)segmentSize;
Bytes[startPos] = (byte)((segmentSize >> 8) | 0x80);
WriterIndex += 1;
}
else if (segmentSize < 0x200000) // 110 1 1111, -,-
{
EnsureWrite(2);
Bytes[WriterIndex + 1] = Bytes[startPos + 2];
Bytes[startPos + 2] = (byte)segmentSize;
Bytes[WriterIndex] = Bytes[startPos + 1];
Bytes[startPos + 1] = (byte)(segmentSize >> 8);
Bytes[startPos] = (byte)((segmentSize >> 16) | 0xc0);
WriterIndex += 2;
}
else if (segmentSize < 0x10000000) // 1110 1111,-,-,-
{
EnsureWrite(3);
Bytes[WriterIndex + 2] = Bytes[startPos + 3];
Bytes[startPos + 3] = (byte)segmentSize;
Bytes[WriterIndex + 1] = Bytes[startPos + 2];
Bytes[startPos + 2] = (byte)(segmentSize >> 8);
Bytes[WriterIndex] = Bytes[startPos + 1];
Bytes[startPos + 1] = (byte)(segmentSize >> 16);
Bytes[startPos] = (byte)((segmentSize >> 24) | 0xe0);
WriterIndex += 3;
}
else
{
throw new SerializationException("exceed max segment size");
}
}
public void ReadSegment(out int startIndex, out int segmentSize)
{
EnsureRead(1);
int h = Bytes[ReaderIndex++];
startIndex = ReaderIndex;
if (h < 0x80)
{
segmentSize = h;
ReaderIndex += segmentSize;
}
else if (h < 0xc0)
{
EnsureRead(1);
segmentSize = ((h & 0x3f) << 8) | Bytes[ReaderIndex];
int endPos = ReaderIndex + segmentSize;
Bytes[ReaderIndex] = Bytes[endPos];
ReaderIndex += segmentSize + 1;
}
else if (h < 0xe0)
{
EnsureRead(2);
segmentSize = ((h & 0x1f) << 16) | ((int)Bytes[ReaderIndex] << 8) | Bytes[ReaderIndex + 1];
int endPos = ReaderIndex + segmentSize;
Bytes[ReaderIndex] = Bytes[endPos];
Bytes[ReaderIndex + 1] = Bytes[endPos + 1];
ReaderIndex += segmentSize + 2;
}
else if (h < 0xf0)
{
EnsureRead(3);
segmentSize = ((h & 0x0f) << 24) | ((int)Bytes[ReaderIndex] << 16) | ((int)Bytes[ReaderIndex + 1] << 8) | Bytes[ReaderIndex + 2];
int endPos = ReaderIndex + segmentSize;
Bytes[ReaderIndex] = Bytes[endPos];
Bytes[ReaderIndex + 1] = Bytes[endPos + 1];
Bytes[ReaderIndex + 2] = Bytes[endPos + 2];
ReaderIndex += segmentSize + 3;
}
else
{
throw new SerializationException("exceed max size");
}
if (ReaderIndex > WriterIndex)
{
throw new SerializationException("segment data not enough");
}
}
public void ReadSegment(ByteBuf buf)
{
ReadSegment(out int startPos, out var size);
buf.Bytes = Bytes;
buf.ReaderIndex = startPos;
buf.WriterIndex = startPos + size;
}
public void EnterSegment(out SegmentSaveState saveState)
{
ReadSegment(out int startPos, out int size);
saveState = new SegmentSaveState(ReaderIndex, WriterIndex);
ReaderIndex = startPos;
WriterIndex = startPos + size;
}
public void LeaveSegment(SegmentSaveState saveState)
{
ReaderIndex = saveState.ReaderIndex;
WriterIndex = saveState.WriterIndex;
}
#endregion
public override string ToString()
{
string[] datas = new string[WriterIndex - ReaderIndex];
for (var i = ReaderIndex; i < WriterIndex; i++)
{
datas[i - ReaderIndex] = Bytes[i].ToString("X2");
}
return string.Join(".", datas);
}
public override bool Equals(object obj)
{
return (obj is ByteBuf other) && Equals(other);
}
public bool Equals(ByteBuf other)
{
if (other == null)
{
return false;
}
if (Size != other.Size)
{
return false;
}
for (int i = 0, n = Size; i < n; i++)
{
if (Bytes[ReaderIndex + i] != other.Bytes[other.ReaderIndex + i])
{
return false;
}
}
return true;
}
public object Clone()
{
return new ByteBuf(CopyData());
}
public static ByteBuf FromString(string value)
{
var ss = value.Split(',');
byte[] data = new byte[ss.Length];
for (int i = 0; i < data.Length; i++)
{
data[i] = byte.Parse(ss[i]);
}
return new ByteBuf(data);
}
public override int GetHashCode()
{
int hash = 17;
for (int i = ReaderIndex; i < WriterIndex; i++)
{
hash = hash * 23 + Bytes[i];
}
return hash;
}
public void Release()
{
_releaser?.Invoke(this);
}
#if SUPPORT_PUERTS_ARRAYBUF
// -- add for puerts
public Puerts.ArrayBuffer ReadArrayBuffer()
{
return new Puerts.ArrayBuffer(ReadBytes());
}
public void WriteArrayBuffer(Puerts.ArrayBuffer bytes)
{
WriteBytes(bytes.Bytes);
}
#endif
}
}