mirror of
https://github.com/esiur/esiur-dotnet.git
synced 2025-05-06 19:42:58 +00:00
251 lines
7.7 KiB
C#
251 lines
7.7 KiB
C#
using Esiur.Net.IIP;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Text;
|
|
|
|
namespace Esiur.Data;
|
|
|
|
public enum TransmissionTypeIdentifier : byte
|
|
{
|
|
Null = 0x0,
|
|
False = 0x1,
|
|
True = 0x2,
|
|
NotModified = 0x3,
|
|
UInt8 = 0x8,
|
|
Int8 = 0x9,
|
|
Char8 = 0xA,
|
|
Int16 = 0x10,
|
|
UInt16 = 0x11,
|
|
Char16 = 0x12,
|
|
Int32 = 0x18,
|
|
UInt32 = 0x19,
|
|
Float32 = 0x1A,
|
|
Resource = 0x1B,
|
|
ResourceLocal = 0x1C,
|
|
Int64 = 0x20,
|
|
UInt64 = 0x21,
|
|
Float64 = 0x22,
|
|
DateTime = 0x23,
|
|
Int128 = 0x28,
|
|
UInt128 = 0x29,
|
|
Float128 = 0x2A,
|
|
|
|
RawData = 0x40,
|
|
String = 0x41,
|
|
List = 0x42,
|
|
ResourceList = 0x43,
|
|
RecordList = 0x44,
|
|
Map = 0x45,
|
|
MapList = 0x46,
|
|
//Tuple = 0x47,
|
|
|
|
Record = 0x80,
|
|
TypedList = 0x81,
|
|
TypedMap = 0x82,
|
|
Tuple = 0x83,
|
|
Enum = 0x84,
|
|
Constant = 0x85
|
|
//TypedResourceList = 0x81,
|
|
//TypedRecordList = 0x82,
|
|
|
|
}
|
|
|
|
public enum TransmissionTypeClass
|
|
{
|
|
Fixed = 0,
|
|
Dynamic = 1,
|
|
Typed = 2
|
|
}
|
|
|
|
public struct TransmissionType
|
|
{
|
|
public TransmissionTypeIdentifier Identifier;
|
|
public int Index;
|
|
public TransmissionTypeClass Class;
|
|
public uint Offset;
|
|
public ulong ContentLength;
|
|
public byte Exponent;
|
|
|
|
|
|
public TransmissionType(TransmissionTypeIdentifier identifier, TransmissionTypeClass cls, int index, uint offset, ulong contentLength, byte exponent = 0)
|
|
{
|
|
Identifier = identifier;
|
|
Index = index;
|
|
Class = cls;
|
|
Offset=offset;
|
|
ContentLength = contentLength;
|
|
Exponent = exponent;
|
|
}
|
|
|
|
public static byte[] Compose(TransmissionTypeIdentifier identifier, byte[] data)
|
|
{
|
|
|
|
if (data == null || data.Length == 0)
|
|
return new byte[] { (byte)identifier };
|
|
|
|
var cls = (TransmissionTypeClass)((int)identifier >> 6);
|
|
if (cls == TransmissionTypeClass.Fixed)
|
|
{
|
|
return DC.Combine(new byte[] { (byte)identifier }, 0, 1, data, 0, (uint)data.Length);
|
|
}
|
|
else
|
|
{
|
|
var len = (ulong)data.LongLength;
|
|
|
|
if (len == 0)
|
|
{
|
|
return new byte[1] { (byte) identifier };
|
|
}
|
|
else if (len <= 0xFF)
|
|
{
|
|
var rt = new byte[2 + len];
|
|
rt[0] = (byte)((byte)identifier | 0x8);
|
|
rt[1] = (byte)len;
|
|
Buffer.BlockCopy(data, 0, rt, 2, (int)len);
|
|
return rt;
|
|
}
|
|
else if (len <= 0xFF_FF)
|
|
{
|
|
var rt = new byte[3 + len];
|
|
rt[0] = (byte)((byte)identifier | 0x10);
|
|
rt[1] = (byte)((len >> 8) & 0xFF);
|
|
rt[2] = (byte)(len & 0xFF);
|
|
Buffer.BlockCopy(data, 0, rt, 3, (int)len);
|
|
return rt;
|
|
}
|
|
else if (len <= 0xFF_FF_FF)
|
|
{
|
|
var rt = new byte[4 + len];
|
|
rt[0] = (byte)((byte)identifier | 0x18);
|
|
rt[1] = (byte)((len >> 16) & 0xFF);
|
|
rt[2] = (byte)((len >> 8) & 0xFF);
|
|
rt[3] = (byte)(len & 0xFF);
|
|
Buffer.BlockCopy(data, 0, rt, 4, (int)len);
|
|
return rt;
|
|
}
|
|
else if (len <= 0xFF_FF_FF_FF)
|
|
{
|
|
var rt = new byte[5 + len];
|
|
rt[0] = (byte)((byte)identifier | 0x20);
|
|
rt[1] = (byte)((len >> 24) & 0xFF);
|
|
rt[2] = (byte)((len >> 16) & 0xFF);
|
|
rt[3] = (byte)((len >> 8) & 0xFF);
|
|
rt[4] = (byte)(len & 0xFF);
|
|
Buffer.BlockCopy(data, 0, rt, 5, (int)len);
|
|
return rt;
|
|
}
|
|
else if (len <= 0xFF_FF_FF_FF_FF)
|
|
{
|
|
var rt = new byte[6 + len];
|
|
rt[0] = (byte)((byte)identifier | 0x28);
|
|
rt[1] = (byte)((len >> 32) & 0xFF);
|
|
rt[2] = (byte)((len >> 24) & 0xFF);
|
|
rt[3] = (byte)((len >> 16) & 0xFF);
|
|
rt[4] = (byte)((len >> 8) & 0xFF);
|
|
rt[5] = (byte)(len & 0xFF);
|
|
Buffer.BlockCopy(data, 0, rt, 6, (int)len);
|
|
return rt;
|
|
}
|
|
else if (len <= 0xFF_FF_FF_FF_FF_FF)
|
|
{
|
|
var rt = new byte[7 + len];
|
|
rt[0] = (byte)((byte)identifier | 0x30);
|
|
rt[1] = (byte)((len >> 40) & 0xFF);
|
|
rt[2] = (byte)((len >> 32) & 0xFF);
|
|
rt[3] = (byte)((len >> 24) & 0xFF);
|
|
rt[4] = (byte)((len >> 16) & 0xFF);
|
|
rt[5] = (byte)((len >> 8) & 0xFF);
|
|
rt[6] = (byte)(len & 0xFF);
|
|
Buffer.BlockCopy(data, 0, rt, 7, (int)len);
|
|
return rt;
|
|
}
|
|
else //if (len <= 0xFF_FF_FF_FF_FF_FF_FF)
|
|
{
|
|
var rt = new byte[8 + len];
|
|
rt[0] = (byte)((byte)identifier | 0x38);
|
|
rt[1] = (byte)((len >> 48) & 0xFF);
|
|
rt[2] = (byte)((len >> 40) & 0xFF);
|
|
rt[3] = (byte)((len >> 32) & 0xFF);
|
|
rt[4] = (byte)((len >> 24) & 0xFF);
|
|
rt[5] = (byte)((len >> 16) & 0xFF);
|
|
rt[6] = (byte)((len >> 8) & 0xFF);
|
|
rt[7] = (byte)(len & 0xFF);
|
|
Buffer.BlockCopy(data, 0, rt, 8, (int)len);
|
|
return rt;
|
|
}
|
|
//else // if (len <= 0xFF_FF_FF_FF_FF_FF_FF_FF)
|
|
//{
|
|
// var rt = new byte[9 + len];
|
|
// rt[0] = (byte)((byte)identifier | 0x8);
|
|
// rt[1] = (byte)((len >> 56) & 0xFF);
|
|
// rt[2] = (byte)((len >> 48) & 0xFF);
|
|
// rt[3] = (byte)((len >> 40) & 0xFF);
|
|
// rt[4] = (byte)((len >> 32) & 0xFF);
|
|
// rt[5] = (byte)((len >> 24) & 0xFF);
|
|
// rt[6] = (byte)((len >> 16) & 0xFF);
|
|
// rt[7] = (byte)((len >> 8) & 0xFF);
|
|
// rt[8] = (byte)(len & 0xFF);
|
|
// Buffer.BlockCopy(data, 0, rt, 9, (int)len);
|
|
// return rt;
|
|
//}
|
|
|
|
|
|
// // add length
|
|
// int bytes = 1;
|
|
//for (var i = 56; i > 0; i -= 8, bytes++)
|
|
// if (len <= (0xFF_FF_FF_FF_FF_FF_FF_FF >> i))
|
|
// break;
|
|
|
|
//var rt = new byte[1 + bytes + data.Length];
|
|
//rt[0] = (byte)((byte)identifier | (bytes << 3));
|
|
|
|
//for (var i = 1; i <= bytes; i++)
|
|
// rt[i] = data.LongLength >> i * 8;
|
|
|
|
//Buffer.BlockCopy(data, 0, rt, 1 + bytes, data.Length);
|
|
}
|
|
}
|
|
|
|
public static (ulong, TransmissionType?) Parse(byte[] data, uint offset, uint ends)
|
|
{
|
|
var h = data[offset++];
|
|
|
|
var cls = (TransmissionTypeClass)(h >> 6);
|
|
|
|
if (cls == TransmissionTypeClass.Fixed)
|
|
{
|
|
var exp = (h & 0x38) >> 3;
|
|
|
|
if (exp == 0)
|
|
return (1, new TransmissionType((TransmissionTypeIdentifier)h, cls, h & 0x7, 0, (byte)exp));
|
|
|
|
ulong cl = (ulong)(1 << (exp -1));
|
|
|
|
if (ends - offset < cl)
|
|
return (cl - (ends - offset), null);
|
|
|
|
//offset += (uint)cl;
|
|
|
|
return (1 + cl, new TransmissionType((TransmissionTypeIdentifier)h, cls, h & 0x7, offset, cl, (byte)exp));
|
|
}
|
|
else
|
|
{
|
|
ulong cll = (ulong)(h >> 3) & 0x7;
|
|
|
|
if (ends - offset < cll)
|
|
return (cll - (ends - offset), null);
|
|
|
|
ulong cl = 0;
|
|
|
|
for (uint i = 0; i < cll; i++)
|
|
cl = cl << 8 | data[offset++];
|
|
|
|
if (ends - offset < cl)
|
|
return (cl - (ends - offset), null);
|
|
|
|
return (1 + cl + cll, new TransmissionType((TransmissionTypeIdentifier)(h & 0xC7), cls, h & 0x7, offset, cl));
|
|
}
|
|
}
|
|
|
|
}
|