mysimulation/server/tso.common/Serialization/IoBufferUtils.cs
Tony Bark 22191ce648 Removed NioTSO client and server
- NioTSO client isn't needed because we're using RayLib
- Added FreeSO's API server to handle most backend operations
2024-05-01 02:55:43 -04:00

304 lines
8.6 KiB
C#
Executable file

using Mina.Core.Buffer;
using System;
using System.Collections.Generic;
using System.Text;
namespace FSO.Common.Serialization
{
public static class IoBufferUtils
{
public static void PutSerializable(this IoBuffer buffer, object obj, ISerializationContext context)
{
buffer.PutSerializable(context, obj, false);
}
public static byte[] GetBytes(this IoBuffer buffer)
{
var result = new byte[buffer.Limit];
buffer.Get(result, 0, buffer.Limit);
return result;
}
public static T Deserialize<T>(byte[] bytes, ISerializationContext context) where T : IoBufferDeserializable
{
var buffer = IoBuffer.Wrap(bytes);
return Deserialize<T>(buffer, context);
}
public static T Deserialize<T>(IoBuffer buffer, ISerializationContext context) where T : IoBufferDeserializable
{
var model = Activator.CreateInstance<T>();
model.Deserialize(buffer, context);
return (T)model;
}
public static IoBuffer SerializableToIoBuffer(object obj, ISerializationContext context)
{
if (obj is IoBuffer)
{
var ioBuffer = (IoBuffer)obj;
return (IoBuffer)ioBuffer;
}
else if (obj is byte[])
{
var byteArray = (byte[])obj;
return IoBuffer.Wrap(byteArray);
}
else if (obj is IoBufferSerializable)
{
var ioBuffer = IoBuffer.Allocate(0);
ioBuffer.AutoExpand = true;
ioBuffer.Order = ByteOrder.BigEndian;
var serializable = (IoBufferSerializable)obj;
serializable.Serialize(ioBuffer, context);
ioBuffer.Flip();
return ioBuffer;
}
throw new Exception("Unknown serializable type: " + obj);
}
public static void PutSerializable(this IoBuffer buffer, ISerializationContext context, object obj, bool writeLength)
{
if(obj is IoBuffer)
{
var ioBuffer = (IoBuffer)obj;
if (writeLength){
buffer.PutUInt32((uint)ioBuffer.Remaining);
}
buffer.Put(ioBuffer);
}else if(obj is byte[])
{
var byteArray = (byte[])obj;
if (writeLength)
{
buffer.PutUInt32((uint)byteArray.Length);
}
buffer.Put(byteArray);
}else if(obj is IoBufferSerializable)
{
var ioBuffer = IoBuffer.Allocate(0);
ioBuffer.AutoExpand = true;
ioBuffer.Order = ByteOrder.BigEndian;
var serializable = (IoBufferSerializable)obj;
serializable.Serialize(ioBuffer, context);
ioBuffer.Flip();
if (writeLength)
{
buffer.PutUInt32((uint)ioBuffer.Remaining);
}
buffer.Put(ioBuffer);
}
}
public static void PutBool(this IoBuffer buffer, bool value)
{
buffer.Put(value ? (byte)0x01 : (byte)0x00);
}
public static bool GetBool(this IoBuffer buffer)
{
return buffer.Get() == 1 ? true : false;
}
public static void PutUInt32(this IoBuffer buffer, uint value)
{
int converted = unchecked((int)value);
buffer.PutInt32(converted);
}
public static uint GetUInt32(this IoBuffer buffer)
{
return (uint)buffer.GetInt32();
}
public static void PutUInt16(this IoBuffer buffer, ushort value)
{
buffer.PutInt16((short)value);
}
public static void PutUInt64(this IoBuffer buffer, ulong value)
{
buffer.PutInt64((long)value);
}
public static void PutEnum<T>(this IoBuffer buffer, T enumValue)
{
ushort value = Convert.ToUInt16((object)enumValue);
buffer.PutUInt16(value);
}
public static void PutUTF8(this IoBuffer buffer, string value)
{
if (value == null)
{
buffer.PutInt16(-1);
}
else
{
buffer.PutInt16((short)value.Length);
buffer.PutString(value, Encoding.UTF8);
}
}
public static string GetUTF8(this IoBuffer buffer)
{
short len = buffer.GetInt16();
if (len == -1)
{
return null;
}
return buffer.GetString(len, Encoding.UTF8);
}
public static ushort GetUInt16(this IoBuffer buffer)
{
return (ushort)buffer.GetInt16();
}
public static ulong GetUInt64(this IoBuffer buffer)
{
return (ulong)buffer.GetInt64();
}
public static T GetEnum<T>(this IoBuffer buffer)
{
return (T)System.Enum.Parse(typeof(T), buffer.GetUInt16().ToString());
}
public static String GetPascalVLCString(this IoBuffer buffer)
{
byte lengthByte = 0;
uint length = 0;
int shift = 0;
do
{
lengthByte = buffer.Get();
length |= (uint)((lengthByte & (uint)0x7F) << shift);
shift += 7;
} while (
(lengthByte >> 7) == 1
);
if (length > 0)
{
var data = new List<byte>();
for (int i = 0; i < length; i++)
{
data.Add(buffer.Get());
}
return Encoding.UTF8.GetString(data.ToArray());
}
else
{
return "";
}
}
public static byte[] GetPascalVLCString(String value)
{
if(value == null)
{
return new byte[] { 0x00 };
}
//TODO: Support strings bigger than 128 chars
var buffer = new byte[1 + value.Length];
buffer[0] = (byte)value.Length;
var chars = value.ToCharArray();
for(int i=0; i < chars.Length; i++){
buffer[i + 1] = (byte)chars[i];
}
return buffer;
}
public static void PutPascalVLCString(this IoBuffer buffer, String value)
{
byte[] encode = null;
long strlen = 0;
if (value != null)
{
encode = Encoding.UTF8.GetBytes(value);
strlen = encode.Length;
}
bool write = strlen > 0;
bool first = true;
while (strlen > 0 || first)
{
buffer.Put((byte)(((strlen > 127) ? (uint)128 : 0) | (strlen & 127)));
strlen >>= 7;
first = false;
}
if (write)
{
buffer.Put(encode);
}
}
public static String GetPascalString(this IoBuffer buffer)
{
byte len1 = buffer.Get();
byte len2 = buffer.Get();
byte len3 = buffer.Get();
byte len4 = buffer.Get();
len1 &= 0x7F;
long len = len1 << 24 | len2 << 16 | len3 << 8 | len4;
if (len > 0)
{
StringBuilder str = new StringBuilder();
for (int i = 0; i < len; i++)
{
str.Append((char)buffer.Get());
}
return str.ToString();
}
else
{
return "";
}
}
public static void PutPascalString(this IoBuffer buffer, String value)
{
long strlen = 0;
if (value != null)
{
strlen = value.Length;
}
byte len1 = (byte)((strlen >> 24) | 0x80);
byte len2 = (byte)((strlen >> 16) & 0xFF);
byte len3 = (byte)((strlen >> 8) & 0xFF);
byte len4 = (byte)(strlen & 0xFF);
buffer.Put(len1);
buffer.Put(len2);
buffer.Put(len3);
buffer.Put(len4);
if (strlen > 0)
{
foreach (char ch in value.ToCharArray())
{
buffer.Put((byte)ch);
}
}
}
}
}