2
0
mirror of https://github.com/esiur/esiur-dotnet.git synced 2025-05-06 03:32:57 +00:00
esiur-dotnet/Esiur/Data/TransmissionType.cs
2022-03-09 21:55:30 +03:00

248 lines
7.6 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 (ends - offset - (uint)cl, 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 (ends - offset - (uint)cll, null);
ulong cl = 0;
for (uint i = 0; i < cll; i++)
cl = cl << 8 | data[offset++];
return (1 + cl + cll, new TransmissionType((TransmissionTypeIdentifier)(h & 0xC7), cls, h & 0x7, offset, cl));
}
}
}