既然是编写网络服务那对于网络数据读写分析是肯定少不了的,毕竟在编写程序中的数据类型最终都需要转化成相应的内存储方式进行交换。程序中常用的基础有:int,uint,ulong,string等;而编程语言中内存的存储方式一般都是用Byte[]来表示,不过随着C#的不停发展为了方便管理操作派生出Span<byte>,ReadOnlySequence<byte>,Stream等操作结构;然而这些存储结构都是基于Byte[]基础类型操作,要想和数据类型进行转换而需要其他的API来处理。
为了简化新版本BeetleX编写协议分析和为后期扩展使用的便利性出发,针对Byte[],Span<byte>,ReadOnlySequence<byte>和Stream等结构封装了一些基础类型转换的扩展方法,这样在使用起来就变得非常方便了(这些函数都支持Big Endian 和Little Endian,默认是Little Endian)。
以下是这个扩展类的一个类型单元测试方法
[Test]
public void Int_RW()
{
byte[] buffer = new byte[4];
Span<byte> span = buffer;
ReadOnlySpan<byte> rspan = span;
MemoryStream stream = new MemoryStream();
int[] values = [int.MaxValue, int.MinValue, 1, -1, 345, 5678, -1224];
int result;
for (int i = 0; i < values.Length; i++)
{
buffer.Write(0, values[i]);
result = buffer.ReadInt32(0);
Assert.AreEqual(result, values[i]);
buffer.Write(0, values[i], false);
result = buffer.ReadInt32(0, false);
Assert.AreEqual(result, values[i]);
span.Write(values[i]);
result = rspan.ReadInt32();
Assert.AreEqual(result, values[i]);
span.Write(values[i], false);
result = rspan.ReadInt32(false);
Assert.AreEqual(result, values[i]);
stream.Position = 0;
stream.Write(values[i]);
stream.Position = 0;
result = stream.ReadInt32();
Assert.AreEqual(result, values[i]);
stream.Position = 0;
stream.Write(values[i], false);
stream.Position = 0;
result = stream.ReadInt32(false);
Assert.AreEqual(result, values[i]);
}
}
接下来就是完全整的扩展类,内容有些多:
using System;
using System.Buffers;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
namespace BeetleX.Light.Extension
{
public static class BeetlexMemoryExtend
{
[ThreadStatic]
static byte[] _bytes2;
[ThreadStatic]
static byte[] _bytes4;
[ThreadStatic]
static byte[] _bytes8;
public static byte[] Get2Bytes()
{
if (_bytes2 == null)
_bytes2 = new byte[2];
return _bytes2;
}
public static byte[] Get4Bytes()
{
if (_bytes4 == null)
_bytes4 = new byte[4];
return _bytes4;
}
public static byte[] Get8Bytes()
{
if (_bytes8 == null)
_bytes8 = new byte[8];
return _bytes8;
}
public static short SwapInt16(short v)
{
return (short)(((v & 0xff) << 8) | ((v >> 8) & 0xff));
}
public static ushort SwapUInt16(ushort v)
{
return (ushort)(((v & 0xff) << 8) | ((v >> 8) & 0xff));
}
public static int SwapInt32(int v)
{
return (int)(((SwapInt16((short)v) & 0xffff) << 0x10) |
(SwapInt16((short)(v >> 0x10)) & 0xffff));
}
public static uint SwapUInt32(uint v)
{
return (uint)(((SwapUInt16((ushort)v) & 0xffff) << 0x10) |
(SwapUInt16((ushort)(v >> 0x10)) & 0xffff));
}
public static long SwapInt64(long v)
{
return (long)(((SwapInt32((int)v) & 0xffffffffL) << 0x20) |
(SwapInt32((int)(v >> 0x20)) & 0xffffffffL));
}
public static ulong SwapUInt64(ulong v)
{
return (ulong)(((SwapUInt32((uint)v) & 0xffffffffL) << 0x20) |
(SwapUInt32((uint)(v >> 0x20)) & 0xffffffffL));
}
public static void Write(this Span<byte> _buffer, short value, bool littleEndian = true)
{
if (!littleEndian)
value = SwapInt16(value);
_buffer[0] = (byte)value;
_buffer[1] = (byte)(value >> 8);
}
public static void Write(this Stream _buffer, short value, bool littleEndian = true)
{
var bytes = Get2Bytes();
Write(bytes, value, littleEndian);
_buffer.Write(bytes);
}
public static void Write(this Span<byte> _buffer, ushort value, bool littleEndian = true)
{
if (!littleEndian)
value = SwapUInt16(value);
_buffer[0] = (byte)value;
_buffer[1] = (byte)(value >> 8);
}
public static void Write(this Stream _buffer, ushort value, bool littleEndian = true)
{
var bytes = Get2Bytes();
Write(bytes, value, littleEndian);
_buffer.Write(bytes);
}
public static void Write(this Span<byte> _buffer, int value, bool littleEndian = true)
{
if (!littleEndian)
value = SwapInt32(value);
_buffer[0] = (byte)value;
_buffer[1] = (byte)(value >> 8);
_buffer[2] = (byte)(value >> 16);
_buffer[3] = (byte)(value >> 24);
}
public static void Write(this Stream _buffer, int value, bool littleEndian = true)
{
var bytes = Get4Bytes();
Write(bytes, value, littleEndian);
_buffer.Write(bytes);
}
public static void Write(this Span<byte> _buffer, uint value, bool littleEndian = true)
{
if (!littleEndian)
value = SwapUInt32(value);
_buffer[0] = (byte)value;
_buffer[1] = (byte)(value >> 8);
_buffer[2] = (byte)(value >> 16);
_buffer[3] = (byte)(value >> 24);
}
public static void Write(this Stream _buffer, uint value, bool littleEndian = true)
{
var bytes = Get4Bytes();
Write(bytes, value, littleEndian);
_buffer.Write(bytes);
}
public static void Write(this Span<byte> _buffer, long value, bool littleEndian = true)
{
if (!littleEndian)
value = SwapInt64(value);
_buffer[0] = (byte)value;
_buffer[1] = (byte)(value >> 8);
_buffer[2] = (byte)(value >> 16);
_buffer[3] = (byte)(value >> 24);
_buffer[4] = (byte)(value >> 32);
_buffer[5] = (byte)(value >> 40);
_buffer[6] = (byte)(value >> 48);
_buffer[7] = (byte)(value >> 56);
}
public static void Write(this Stream _buffer, long value, bool littleEndian = true)
{
var bytes = Get8Bytes();
Write(bytes, value, littleEndian);
_buffer.Write(bytes);
}
public static void Write(this Span<byte> _buffer, ulong value, bool littleEndian = true)
{
if (!littleEndian)
value = SwapUInt64(value);
_buffer[0] = (byte)value;
_buffer[1] = (byte)(value >> 8);
_buffer[2] = (byte)(value >> 16);
_buffer[3] = (byte)(value >> 24);
_buffer[4] = (byte)(value >> 32);
_buffer[5] = (byte)(value >> 40);
_buffer[6] = (byte)(value >> 48);
_buffer[7] = (byte)(value >> 56);
}
public static void Write(this Stream _buffer, ulong value, bool littleEndian = true)
{
var bytes = Get8Bytes();
Write(bytes, value, littleEndian);
_buffer.Write(bytes);
}
public static void Write(this byte[] _buffer, int postion, short value, bool littleEndian = true)
{
if (!littleEndian)
value = SwapInt16(value);
_buffer[postion + 0] = (byte)value;
_buffer[postion + 1] = (byte)(value >> 8);
}
public static void Write(this byte[] _buffer, int postion, ushort value, bool littleEndian = true)
{
if (!littleEndian)
value = SwapUInt16(value);
_buffer[postion + 0] = (byte)value;
_buffer[postion + 1] = (byte)(value >> 8);
}
public static void Write(this byte[] _buffer, int postion, int value, bool littleEndian = true)
{
if (!littleEndian)
value = SwapInt32(value);
_buffer[postion + 0] = (byte)value;
_buffer[postion + 1] = (byte)(value >> 8);
_buffer[postion + 2] = (byte)(value >> 16);
_buffer[postion + 3] = (byte)(value >> 24);
}
public static void Write(this byte[] _buffer, int postion, uint value, bool littleEndian = true)
{
if (!littleEndian)
value = SwapUInt32(value);
_buffer[postion + 0] = (byte)value;
_buffer[postion + 1] = (byte)(value >> 8);
_buffer[postion + 2] = (byte)(value >> 16);
_buffer[postion + 3] = (byte)(value >> 24);
}
public static void Write(this byte[] _buffer, int postion, long value, bool littleEndian = true)
{
if (!littleEndian)
value = SwapInt64(value);
_buffer[postion + 0] = (byte)value;
_buffer[postion + 1] = (byte)(value >> 8);
_buffer[postion + 2] = (byte)(value >> 16);
_buffer[postion + 3] = (byte)(value >> 24);
_buffer[postion + 4] = (byte)(value >> 32);
_buffer[postion + 5] = (byte)(value >> 40);
_buffer[postion + 6] = (byte)(value >> 48);
_buffer[postion + 7] = (byte)(value >> 56);
}
public static void Write(this byte[] _buffer, int postion, ulong value, bool littleEndian = true)
{
if (!littleEndian)
value = SwapUInt64(value);
_buffer[postion + 0] = (byte)value;
_buffer[postion + 1] = (byte)(value >> 8);
_buffer[postion + 2] = (byte)(value >> 16);
_buffer[postion + 3] = (byte)(value >> 24);
_buffer[postion + 4] = (byte)(value >> 32);
_buffer[postion + 5] = (byte)(value >> 40);
_buffer[postion + 6] = (byte)(value >> 48);
_buffer[postion + 7] = (byte)(value >> 56);
}
public static int Write(this Stream _buffer, string value, Encoding encoding)
{
if (string.IsNullOrEmpty(value))
return 0;
int result = 0;
using (TemporaryBuffer<byte> bytes = value.Length * 6)
{
result = encoding.GetBytes(value, 0, value.Length, bytes.Data, 0);
_buffer.Write(bytes.Data, 0, result);
return result;
}
}
public static int Write(this Span<byte> _buffer, string value, Encoding encoding)
{
if (string.IsNullOrEmpty(value))
return 0;
return encoding.GetBytes(value, _buffer);
}
public static int Write(this byte[] _buffer, int postion, string value, Encoding encoding)
{
if (string.IsNullOrEmpty(value))
return 0;
return encoding.GetBytes(value, 0, value.Length, _buffer, 0);
}
public static short ReadInt16(this byte[] m_buffer, int postion, bool littleEndian = true)
{
var result = (short)((int)m_buffer[postion + 0] | (int)m_buffer[postion + 1] << 8);
if (!littleEndian)
result = SwapInt16(result);
return result;
}
public static ushort ReadUInt16(this byte[] m_buffer, int postion, bool littleEndian = true)
{
var result = (ushort)((int)m_buffer[postion + 0] | (int)m_buffer[postion + 1] << 8);
if (!littleEndian)
result = SwapUInt16(result);
return result;
}
public static int ReadInt32(this byte[] m_buffer, int postion, bool littleEndian = true)
{
var result = (int)m_buffer[postion + 0] | (int)m_buffer[postion + 1] << 8 | (int)m_buffer[postion + 2] << 16 | (int)m_buffer[postion + 3] << 24;
if (!littleEndian)
result = SwapInt32(result);
return result;
}
public static uint ReadUInt32(this byte[] m_buffer, int postion, bool littleEndian = true)
{
var result = (uint)((int)m_buffer[postion + 0] | (int)m_buffer[postion + 1] << 8 | (int)m_buffer[postion + 2] << 16 | (int)m_buffer[postion + 3] << 24);
if (!littleEndian)
result = SwapUInt32(result);
return result;
}
public static long ReadInt64(this byte[] m_buffer, int postion, bool littleEndian = true)
{
uint num = (uint)((int)m_buffer[postion + 0] | (int)m_buffer[postion + 1] << 8 | (int)m_buffer[postion + 2] << 16 | (int)m_buffer[postion + 3] << 24);
uint num2 = (uint)((int)m_buffer[postion + 4] | (int)m_buffer[postion + 5] << 8 | (int)m_buffer[postion + 6] << 16 | (int)m_buffer[postion + 7] << 24);
var result = (long)((ulong)num2 << 32 | (ulong)num);
if (!littleEndian)
result = SwapInt64(result);
return result;
}
public static ulong ReadUInt64(this byte[] m_buffer, int postion, bool littleEndian = true)
{
uint num = (uint)((int)m_buffer[postion + 0] | (int)m_buffer[postion + 1] << 8 | (int)m_buffer[postion + 2] << 16 | (int)m_buffer[postion + 3] << 24);
uint num2 = (uint)((int)m_buffer[postion + 4] | (int)m_buffer[postion + 5] << 8 | (int)m_buffer[postion + 6] << 16 | (int)m_buffer[postion + 7] << 24);
var result = (ulong)num2 << 32 | (ulong)num;
if (!littleEndian)
result = SwapUInt64(result);
return result;
}
public static short ReadInt16(this ReadOnlySequence<byte> buffer, bool littleEndian = true)
{
short result = 0;
if (buffer.FirstSpan.Length >= 2)
result = ReadInt16(buffer.FirstSpan);
else
{
result = (short)(
(int)buffer.FirstSpan[0] |
(int)buffer.Slice(1).FirstSpan[0] << 8
);
}
if (!littleEndian)
result = SwapInt16(result);
return result;
}
public static short ReadInt16(this Stream m_buffer, bool littleEndian = true)
{
var bytes = Get2Bytes();
m_buffer.Read(bytes);
return ReadInt16(bytes, littleEndian);
}
public static short ReadInt16(this ReadOnlySpan<byte> m_buffer, bool littleEndian = true)
{
var result = (short)((int)m_buffer[0] | (int)m_buffer[1] << 8);
if (!littleEndian)
result = SwapInt16(result);
return result;
}
public static ushort ReadUInt16(this ReadOnlySequence<byte> m_buffer, bool littleEndian = true)
{
ushort result = 0;
if (m_buffer.FirstSpan.Length >= 2)
result = ReadUInt16(m_buffer.FirstSpan);
else
result = (ushort)(
(int)m_buffer.FirstSpan[0] |
(int)m_buffer.Slice(1).FirstSpan[0] << 8);
if (!littleEndian)
result = SwapUInt16(result);
return result;
}
public static ushort ReadUInt16(this Stream m_buffer, bool littleEndian = true)
{
var bytes = Get2Bytes();
m_buffer.Read(bytes);
return ReadUInt16(bytes, littleEndian);
}
public static ushort ReadUInt16(this ReadOnlySpan<byte> m_buffer, bool littleEndian = true)
{
var result = (ushort)((int)m_buffer[0] | (int)m_buffer[1] << 8);
if (!littleEndian)
result = SwapUInt16(result);
return result;
}
public static int ReadInt32(this Stream m_buffer, bool littleEndian = true)
{
var bytes = Get4Bytes();
m_buffer.Read(bytes);
return ReadInt32(bytes, littleEndian);
}
public static int ReadInt32(this ReadOnlySequence<byte> m_buffer, bool littleEndian = true)
{
int result = 0;
if (m_buffer.FirstSpan.Length >= 4)
result = ReadInt32(m_buffer.FirstSpan);
else
{
var bytes = Get4Bytes();
m_buffer.CopyTo(bytes);
result = ReadInt32(bytes);
}
if (!littleEndian)
result = SwapInt32(result);
return result;
}
public static int ReadInt32(this ReadOnlySpan<byte> m_buffer, bool littleEndian = true)
{
var result = (int)m_buffer[0] | (int)m_buffer[1] << 8 | (int)m_buffer[2] << 16 | (int)m_buffer[3] << 24;
if (!littleEndian)
result = SwapInt32(result);
return result;
}
public static uint ReadUInt32(this Stream m_buffer, bool littleEndian = true)
{
var bytes = Get4Bytes();
m_buffer.Read(bytes);
return ReadUInt32(bytes, littleEndian);
}
public static uint ReadUInt32(this ReadOnlySequence<byte> m_buffer, bool littleEndian = true)
{
UInt32 result = 0;
if (m_buffer.FirstSpan.Length >= 4)
result = ReadUInt32(m_buffer.FirstSpan);
else
{
var bytes = Get4Bytes();
m_buffer.CopyTo(bytes);
result = ReadUInt32(bytes);
}
if (!littleEndian)
result = SwapUInt32(result);
return result;
}
public static uint ReadUInt32(this ReadOnlySpan<byte> m_buffer, bool littleEndian = true)
{
var result = (uint)((int)m_buffer[0] | (int)m_buffer[1] << 8 | (int)m_buffer[2] << 16 | (int)m_buffer[3] << 24);
if (!littleEndian)
result = SwapUInt32(result);
return result;
}
public static long ReadInt64(this Stream m_buffer, bool littleEndian = true)
{
var bytes = Get8Bytes();
m_buffer.Read(bytes);
return ReadInt64(bytes, littleEndian);
}
public static long ReadInt64(this ReadOnlySequence<byte> m_buffer, bool littleEndian = true)
{
Int64 result = 0;
if (m_buffer.FirstSpan.Length >= 8)
result = ReadInt64(m_buffer.FirstSpan);
else
{
var bytes = Get8Bytes();
m_buffer.CopyTo(bytes);
result = ReadInt64(bytes);
}
if (!littleEndian)
result = SwapInt64(result);
return result;
}
public static long ReadInt64(this ReadOnlySpan<byte> m_buffer, bool littleEndian = true)
{
uint num = (uint)((int)m_buffer[0] | (int)m_buffer[1] << 8 | (int)m_buffer[2] << 16 | (int)m_buffer[3] << 24);
uint num2 = (uint)((int)m_buffer[4] | (int)m_buffer[5] << 8 | (int)m_buffer[6] << 16 | (int)m_buffer[7] << 24);
var result = (long)((ulong)num2 << 32 | (ulong)num);
if (!littleEndian)
result = SwapInt64(result);
return result;
}
public static ulong ReadUInt64(this Stream m_buffer, bool littleEndian = true)
{
var bytes = Get8Bytes();
m_buffer.Read(bytes);
return ReadUInt64(bytes, littleEndian);
}
public static ulong ReadUInt64(this ReadOnlySequence<byte> m_buffer, bool littleEndian = true)
{
ulong result = 0;
if (m_buffer.FirstSpan.Length >= 8)
result = ReadUInt64(m_buffer.FirstSpan);
else
{
var bytes = Get8Bytes();
m_buffer.CopyTo(bytes);
result = ReadUInt64(bytes);
}
if (!littleEndian)
result = SwapUInt64(result);
return result;
}
public static ulong ReadUInt64(this ReadOnlySpan<byte> m_buffer, bool littleEndian = true)
{
uint num = (uint)((int)m_buffer[0] | (int)m_buffer[1] << 8 | (int)m_buffer[2] << 16 | (int)m_buffer[3] << 24);
uint num2 = (uint)((int)m_buffer[4] | (int)m_buffer[5] << 8 | (int)m_buffer[6] << 16 | (int)m_buffer[7] << 24);
var result = (ulong)num2 << 32 | (ulong)num;
if (!littleEndian)
result = SwapUInt64(result);
return result;
}
public static string ReadString(this byte[] _buffer, int postion, int count, Encoding coding)
{
return coding.GetString(_buffer, postion, count);
}
public static string ReadString(this ReadOnlySpan<byte> _buffer, Encoding coding)
{
return coding.GetString(_buffer);
}
public static string ReadString(this Stream _buffer, int count, Encoding coding)
{
using (TemporaryBuffer<byte> bytes = count)
{
_buffer.Read(bytes.Data, 0, count);
return coding.GetString(bytes.Data, 0, count);
}
}
public static string ReadString(this ReadOnlySequence<byte> _buffer, Encoding coding)
{
return coding.GetString(_buffer);
}
}
}
BeetleX
开源跨平台通讯框架(支持TLS)
提供HTTP,Websocket,MQTT,Redis,RPC和服务网关开源组件
个人微信:henryfan128 QQ:28304340
关注公众号
https://github.com/beetlex-io/